2024-06-04 01:13:55 -04:00
< ? php declare ( strict_types = 1 );
2021-05-28 16:39:50 -04:00
use Google\Auth\HttpHandler\HttpHandlerFactory ;
use GuzzleHttp\Client ;
2021-10-07 16:20:25 -04:00
use PHPUnit\Framework\TestCase ;
2021-05-28 16:39:50 -04:00
use PrivateBin\Data\GoogleCloudStorage ;
2021-10-07 16:20:25 -04:00
class GoogleCloudStorageTest extends TestCase
2021-05-28 16:39:50 -04:00
{
private static $_client ;
private static $_bucket ;
2021-10-07 16:22:32 -04:00
public static function setUpBeforeClass () : void
2021-05-28 16:39:50 -04:00
{
$httpClient = new Client ( array ( 'debug' => false ));
$handler = HttpHandlerFactory :: build ( $httpClient );
$name = 'pb-' ;
$alphabet = 'abcdefghijklmnopqrstuvwxyz' ;
for ( $i = 0 ; $i < 29 ; ++ $i ) {
$name .= $alphabet [ rand ( 0 , strlen ( $alphabet ) - 1 )];
}
self :: $_client = new StorageClientStub ( array ());
self :: $_bucket = self :: $_client -> createBucket ( $name );
}
2021-10-07 16:22:32 -04:00
public function setUp () : void
2021-05-28 16:39:50 -04:00
{
2021-06-04 23:38:05 -04:00
ini_set ( 'error_log' , stream_get_meta_data ( tmpfile ())[ 'uri' ]);
2022-10-27 19:01:02 -04:00
$this -> _model = new GoogleCloudStorage ( array (
2021-05-28 16:39:50 -04:00
'bucket' => self :: $_bucket -> name (),
'prefix' => 'pastes' ,
2021-06-13 04:44:26 -04:00
));
2021-05-28 16:39:50 -04:00
}
2021-10-07 16:22:32 -04:00
public function tearDown () : void
2021-05-28 16:39:50 -04:00
{
foreach ( self :: $_bucket -> objects () as $object ) {
$object -> delete ();
}
}
2021-10-07 16:25:51 -04:00
public static function tearDownAfterClass () : void
2021-05-28 16:39:50 -04:00
{
self :: $_bucket -> delete ();
}
public function testFileBasedDataStoreWorks ()
{
$this -> _model -> delete ( Helper :: getPasteId ());
// storing pastes
$paste = Helper :: getPaste ( 2 , array ( 'expire_date' => 1344803344 ));
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does not yet exist' );
$this -> assertTrue ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'store new paste' );
$this -> assertTrue ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste exists after storing it' );
$this -> assertFalse ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'unable to store the same paste twice' );
$this -> assertEquals ( $paste , $this -> _model -> read ( Helper :: getPasteId ()));
// storing comments
$this -> assertFalse ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment does not yet exist' );
$this -> assertTrue ( $this -> _model -> createComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId (), Helper :: getComment ()), 'store comment' );
$this -> assertTrue ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment exists after storing it' );
$this -> assertFalse ( $this -> _model -> createComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId (), Helper :: getComment ()), 'unable to store the same comment twice' );
$comment = Helper :: getComment ();
$comment [ 'id' ] = Helper :: getCommentId ();
$comment [ 'parentid' ] = Helper :: getPasteId ();
$this -> assertEquals (
array ( $comment [ 'meta' ][ 'created' ] => $comment ),
$this -> _model -> readComments ( Helper :: getPasteId ())
);
// deleting pastes
$this -> _model -> delete ( Helper :: getPasteId ());
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste successfully deleted' );
$this -> assertFalse ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment was deleted with paste' );
$this -> assertFalse ( $this -> _model -> read ( Helper :: getPasteId ()), 'paste can no longer be found' );
}
/**
* pastes a - g are expired and should get deleted , x never expires and y - z expire in an hour
*/
public function testPurge ()
{
$expired = Helper :: getPaste ( 2 , array ( 'expire_date' => 1344803344 ));
$paste = Helper :: getPaste ( 2 , array ( 'expire_date' => time () + 3600 ));
$keys = array ( 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'x' , 'y' , 'z' );
$ids = array ();
foreach ( $keys as $key ) {
$ids [ $key ] = hash ( 'fnv164' , $key );
$this -> assertFalse ( $this -> _model -> exists ( $ids [ $key ]), " paste $key does not yet exist " );
if ( in_array ( $key , array ( 'x' , 'y' , 'z' ))) {
$this -> assertTrue ( $this -> _model -> create ( $ids [ $key ], $paste ), " store $key paste " );
} elseif ( $key === 'x' ) {
$this -> assertTrue ( $this -> _model -> create ( $ids [ $key ], Helper :: getPaste ()), " store $key paste " );
} else {
$this -> assertTrue ( $this -> _model -> create ( $ids [ $key ], $expired ), " store $key paste " );
}
$this -> assertTrue ( $this -> _model -> exists ( $ids [ $key ]), " paste $key exists after storing it " );
}
$this -> _model -> purge ( 10 );
foreach ( $ids as $key => $id ) {
if ( in_array ( $key , array ( 'x' , 'y' , 'z' ))) {
$this -> assertTrue ( $this -> _model -> exists ( $id ), " paste $key exists after purge " );
$this -> _model -> delete ( $id );
} else {
$this -> assertFalse ( $this -> _model -> exists ( $id ), " paste $key was purged " );
}
}
}
public function testErrorDetection ()
{
$this -> _model -> delete ( Helper :: getPasteId ());
$paste = Helper :: getPaste ( 2 , array ( 'expire' => " Invalid UTF-8 sequence: \xB1 \x31 " ));
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does not yet exist' );
$this -> assertFalse ( $this -> _model -> create ( Helper :: getPasteId (), $paste ), 'unable to store broken paste' );
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does still not exist' );
}
public function testCommentErrorDetection ()
{
$this -> _model -> delete ( Helper :: getPasteId ());
$comment = Helper :: getComment ( 1 , array ( 'nickname' => " Invalid UTF-8 sequence: \xB1 \x31 " ));
$this -> assertFalse ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste does not yet exist' );
$this -> assertTrue ( $this -> _model -> create ( Helper :: getPasteId (), Helper :: getPaste ()), 'store new paste' );
$this -> assertTrue ( $this -> _model -> exists ( Helper :: getPasteId ()), 'paste exists after storing it' );
$this -> assertFalse ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment does not yet exist' );
$this -> assertFalse ( $this -> _model -> createComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId (), $comment ), 'unable to store broken comment' );
$this -> assertFalse ( $this -> _model -> existsComment ( Helper :: getPasteId (), Helper :: getPasteId (), Helper :: getCommentId ()), 'comment does still not exist' );
}
2021-06-07 03:11:24 -04:00
/**
* @ throws Exception
*/
public function testKeyValueStore ()
{
$salt = bin2hex ( random_bytes ( 256 ));
2021-06-10 15:39:15 -04:00
$this -> _model -> setValue ( $salt , 'salt' , '' );
$storedSalt = $this -> _model -> getValue ( 'salt' , '' );
2021-06-07 03:11:24 -04:00
$this -> assertEquals ( $salt , $storedSalt );
2021-06-09 16:27:34 -04:00
$this -> _model -> purgeValues ( 'salt' , time () + 60 );
2021-06-13 05:08:38 -04:00
$this -> assertEquals ( '' , $this -> _model -> getValue ( 'salt' , 'master' ));
2021-06-07 03:11:24 -04:00
$client = hash_hmac ( 'sha512' , '127.0.0.1' , $salt );
$expire = time ();
2021-06-13 15:16:30 -04:00
$this -> _model -> setValue ( strval ( $expire ), 'traffic_limiter' , $client );
2021-06-07 03:11:24 -04:00
$storedExpired = $this -> _model -> getValue ( 'traffic_limiter' , $client );
2021-06-13 15:16:30 -04:00
$this -> assertEquals ( strval ( $expire ), $storedExpired );
2021-06-09 16:27:34 -04:00
$this -> _model -> purgeValues ( 'traffic_limiter' , time () - 60 );
$this -> assertEquals ( $storedExpired , $this -> _model -> getValue ( 'traffic_limiter' , $client ));
$this -> _model -> purgeValues ( 'traffic_limiter' , time () + 60 );
2021-06-13 05:08:38 -04:00
$this -> assertEquals ( '' , $this -> _model -> getValue ( 'traffic_limiter' , $client ));
2021-06-07 03:11:24 -04:00
$purgeAt = $expire + ( 15 * 60 );
2021-06-13 15:16:30 -04:00
$this -> _model -> setValue ( strval ( $purgeAt ), 'purge_limiter' , '' );
2021-06-10 15:39:15 -04:00
$storedPurgedAt = $this -> _model -> getValue ( 'purge_limiter' , '' );
2021-06-13 15:16:30 -04:00
$this -> assertEquals ( strval ( $purgeAt ), $storedPurgedAt );
$this -> _model -> purgeValues ( 'purge_limiter' , $purgeAt + 60 );
$this -> assertEquals ( '' , $this -> _model -> getValue ( 'purge_limiter' , '' ));
2021-06-13 05:08:38 -04:00
$this -> assertEquals ( '' , $this -> _model -> getValue ( 'purge_limiter' , 'at' ));
2021-06-07 03:11:24 -04:00
}
2021-06-10 15:39:15 -04:00
/**
* @ throws Exception
*/
public function testKeyValuePurgeTrafficLimiter ()
{
$salt = bin2hex ( random_bytes ( 256 ));
$client = hash_hmac ( 'sha512' , '127.0.0.1' , $salt );
$expire = time ();
2021-06-13 15:16:30 -04:00
$this -> _model -> setValue ( strval ( $expire ), 'traffic_limiter' , $client );
2021-06-10 15:39:15 -04:00
$storedExpired = $this -> _model -> getValue ( 'traffic_limiter' , $client );
2021-06-13 15:16:30 -04:00
$this -> assertEquals ( strval ( $expire ), $storedExpired );
2021-06-10 15:39:15 -04:00
$this -> _model -> purgeValues ( 'traffic_limiter' , time () - 60 );
$this -> assertEquals ( $storedExpired , $this -> _model -> getValue ( 'traffic_limiter' , $client ));
$this -> _model -> purgeValues ( 'traffic_limiter' , time () + 60 );
2021-06-13 05:12:19 -04:00
$this -> assertEquals ( '' , $this -> _model -> getValue ( 'traffic_limiter' , $client ));
2021-06-10 15:39:15 -04:00
}
2021-05-28 16:39:50 -04:00
}