From 0b0ecfb755659f4e8f04b6ce1ff6b9323989e44a Mon Sep 17 00:00:00 2001 From: Imam Ali Mustofa Date: Thu, 18 Jul 2024 03:51:28 +0700 Subject: [PATCH] refactor: format and merge tests --- src/Database/LibSQLConnection.php | 6 ++--- src/Database/LibSQLDatabase.php | 6 ++--- tests/Feature/ConnectionsSetupTest.php | 26 +++++++++++++-------- tests/Feature/CreateRecordsTest.php | 31 +++++++++++++------------ tests/Unit/LibSQLConnectionTest.php | 32 +++++++++++++------------- 5 files changed, 55 insertions(+), 46 deletions(-) diff --git a/src/Database/LibSQLConnection.php b/src/Database/LibSQLConnection.php index a62cc74..be34298 100644 --- a/src/Database/LibSQLConnection.php +++ b/src/Database/LibSQLConnection.php @@ -49,18 +49,18 @@ public function statement($query, $bindings = []): bool return ! empty($res); } - + public function getPdo(): LibSQLDatabase { return $this->db; - + } public function getReadPdo(): LibSQLDatabase { return $this->getPdo(); } - + public function getRawPdo(): LibSQLDatabase { return $this->getPdo(); diff --git a/src/Database/LibSQLDatabase.php b/src/Database/LibSQLDatabase.php index cd7ad9b..680ed32 100644 --- a/src/Database/LibSQLDatabase.php +++ b/src/Database/LibSQLDatabase.php @@ -22,7 +22,7 @@ public function __construct(array $config = []) if ($config['url'] !== ':memory:') { $url = str_replace('file:', '', $config['url']); $config['url'] = match ($this->checkPathOrFilename($config['url'])) { - 'filename' => 'file:' . database_path($url), + 'filename' => 'file:'.database_path($url), default => $config['url'], }; } @@ -151,9 +151,9 @@ public function quote(string $value): string private function setConnectionMode(string $path, string $url = '', string $token = '', bool $remoteOnly = false): void { - if ((str_starts_with($path, 'file:') !== false || $path !== 'file:') && !empty($url) && !empty($token) && $remoteOnly === false) { + if ((str_starts_with($path, 'file:') !== false || $path !== 'file:') && ! empty($url) && ! empty($token) && $remoteOnly === false) { $this->connection_mode = 'remote_replica'; - } elseif (strpos($path, 'file:') !== false && !empty($url) && !empty($token) && $remoteOnly === true) { + } elseif (strpos($path, 'file:') !== false && ! empty($url) && ! empty($token) && $remoteOnly === true) { $this->connection_mode = 'remote'; } elseif (strpos($path, 'file:') !== false) { $this->connection_mode = 'local'; diff --git a/tests/Feature/ConnectionsSetupTest.php b/tests/Feature/ConnectionsSetupTest.php index 3e0c23b..0174cf5 100644 --- a/tests/Feature/ConnectionsSetupTest.php +++ b/tests/Feature/ConnectionsSetupTest.php @@ -7,7 +7,6 @@ use Turso\Driver\Laravel\Database\LibSQLConnection; use Turso\Driver\Laravel\Database\LibSQLDatabase; - class ConnectionsSetupTest extends TestCase { public function setUp(): void @@ -17,18 +16,19 @@ public function setUp(): void public function tearDown(): void { - if (File::exists('tests/_files/test.db')) { - File::delete('tests/_files/test.db'); + $dbFile = getcwd().'/tests/_files/test.db'; + if (File::exists($dbFile)) { + File::delete($dbFile); } parent::tearDown(); } public function testConnectionInMemory(): void { - config()->set('database.default', 'libsql'); + config()->set('database.default', 'sqlite'); config()->set('database.connections.libsql', [ 'driver' => 'libsql', - 'url' => 'file::memory:', // Taken from README docs + 'url' => ':memory:', // Taken from README docs 'authToken' => '', // This should be defied even with memory, which is not right 'syncUrl' => '', // This should be defied even with memory, which is not right 'encryptionKey' => '', // This should be defied even with memory, which is not right @@ -43,6 +43,9 @@ public function testConnectionInMemory(): void $this->assertInstanceOf(LibSQLConnection::class, $connection); // Get the PDO instance + /** + * @var LibSQLConnection $connection + */ $pdo = $connection->getPdo(); $this->assertInstanceOf(LibSQLDatabase::class, $pdo); @@ -58,10 +61,12 @@ public function testConnectionInMemory(): void public function testConnectionLocalFile(): void { + + $dbFile = getcwd().'/tests/_files/test.db'; config()->set('database.default', 'sqlite'); - config()->set('database.connections.local_file', [ + config()->set('database.connections.libsql', [ 'driver' => 'libsql', - 'url' => 'file:/tests/_files/test.db', + 'url' => "file:$dbFile", 'authToken' => '', 'syncUrl' => '', 'syncInterval' => 5, @@ -72,12 +77,15 @@ public function testConnectionLocalFile(): void 'database' => null, // doesn't matter actually, since we use sqlite ]); - $connection = DB::connection('local_file'); + $connection = DB::connection('libsql'); // Assert that the connection is an instance of LibSQLConnection $this->assertInstanceOf(LibSQLConnection::class, $connection); // Get the PDO instance + /** + * @var LibSQLConnection $connection + */ $pdo = $connection->getPdo(); $this->assertInstanceOf(LibSQLDatabase::class, $pdo); @@ -88,6 +96,6 @@ public function testConnectionLocalFile(): void $result = $pdo->query('SELECT sqlite_version()'); $this->assertNotEmpty($result, 'Failed to query SQLite version'); - $this->assertTrue(File::exists('tests/_files/test.db'), 'No file created or wrong path'); + $this->assertTrue(File::exists($dbFile), 'No file created or wrong path'); } } diff --git a/tests/Feature/CreateRecordsTest.php b/tests/Feature/CreateRecordsTest.php index 03f0afb..931684a 100644 --- a/tests/Feature/CreateRecordsTest.php +++ b/tests/Feature/CreateRecordsTest.php @@ -12,10 +12,11 @@ class CreateRecordsTest extends TestCase public function setUp(): void { parent::setUp(); + $dbFile = getcwd().'/tests/_files/test.db'; config()->set('database.default', 'sqlite'); - config()->set('database.connections.local_file', [ + config()->set('database.connections.libsql', [ 'driver' => 'libsql', - 'url' => 'file:/tests/_files/test.db', + 'url' => "file:$dbFile", 'authToken' => '', 'syncUrl' => '', 'syncInterval' => 5, @@ -25,9 +26,9 @@ public function setUp(): void 'prefix' => '', 'database' => null, // doesn't matter actually, since we use sqlite ]); - Schema::connection('local_file') + Schema::connection('libsql') ->dropIfExists('test'); - Schema::connection('local_file') + Schema::connection('libsql') ->create('test', function (\Illuminate\Database\Schema\Blueprint $table) { $table->id(); $table->text('text'); @@ -40,19 +41,20 @@ public function setUp(): void public function tearDown(): void { - if (File::exists('tests/_files/test.db')) { - File::delete('tests/_files/test.db'); + $dbFile = getcwd().'/tests/_files/test.db'; + if (File::exists($dbFile)) { + File::delete($dbFile); } parent::tearDown(); } public function testCreateViaDB(): void { - DB::connection('local_file') + DB::connection('libsql') ->table('test') ->delete(); - $id = DB::connection('local_file') + $id = DB::connection('libsql') ->table('test') ->insertGetId([ 'text' => 'text', @@ -62,7 +64,7 @@ public function testCreateViaDB(): void $this->assertEquals(1, $id); // not working, since insertGetId returns false instead of 1 - DB::connection('local_file') + DB::connection('libsql') ->table('test') ->insert([ 'text' => 'text2', @@ -70,8 +72,7 @@ public function testCreateViaDB(): void 'string' => 'string2', ]); - - $data = DB::connection('local_file') + $data = DB::connection('libsql') ->table('test') ->select() ->get(); @@ -84,7 +85,7 @@ public function testWithBLOBType(): void { $modelClass = new class extends Model { - protected $connection = 'local_file'; + protected $connection = 'libsql'; protected $table = 'test'; @@ -104,7 +105,7 @@ public function casts() $model->save(); - $data = DB::connection('local_file') + $data = DB::connection('libsql') ->table('test') ->select() ->get() @@ -117,7 +118,7 @@ public function testCreateViaEloquent(): void { $modelClass = new class extends Model { - protected $connection = 'local_file'; + protected $connection = 'libsql'; protected $table = 'test'; @@ -141,7 +142,7 @@ public function casts() $this->assertNotEmpty($model->created_at); - $data = DB::connection('local_file') + $data = DB::connection('libsql') ->table('test') ->select() ->get(); diff --git a/tests/Unit/LibSQLConnectionTest.php b/tests/Unit/LibSQLConnectionTest.php index 72c867d..c12dabb 100644 --- a/tests/Unit/LibSQLConnectionTest.php +++ b/tests/Unit/LibSQLConnectionTest.php @@ -40,10 +40,10 @@ public static function escapeStringProvider(): array 'string with single quote' => ["O'Reilly", "O\\'Reilly"], 'string with double quote' => ['Say "Hello"', 'Say \\"Hello\\"'], 'string with backslash' => ['C:\\path\\to\\file', 'C:\\\\path\\\\to\\\\file'], - 'string with newline' => ["Line1\nLine2", "Line1\\nLine2"], - 'string with carriage return' => ["Line1\rLine2", "Line1\\rLine2"], - 'string with null byte' => ["Null\x00Byte", "Null\\0Byte"], - 'string with substitute character' => ["Sub\x1aChar", "Sub\\ZChar"], + 'string with newline' => ["Line1\nLine2", 'Line1\\nLine2'], + 'string with carriage return' => ["Line1\rLine2", 'Line1\\rLine2'], + 'string with null byte' => ["Null\x00Byte", 'Null\\0Byte'], + 'string with substitute character' => ["Sub\x1aChar", 'Sub\\ZChar'], 'complex string' => ["It's a \"complex\" string\nWith multiple 'special' chars\x00\r\n", "It\\'s a \\\"complex\\\" string\\nWith multiple \\'special\\' chars\\0\\r\\n"], ]; } @@ -68,7 +68,7 @@ public static function quoteProvider(): array 'string with null byte' => ["Null\x00Byte", "'Null\\0Byte'"], 'string with substitute character' => ["Sub\x1aChar", "'Sub\\ZChar'"], 'multi-byte characters' => ['こんにちは', "'こんにちは'"], - 'very long string' => [str_repeat('a', 1000000), "'" . str_repeat('a', 1000000) . "'"], + 'very long string' => [str_repeat('a', 1000000), "'".str_repeat('a', 1000000)."'"], ]; } @@ -78,7 +78,7 @@ public function testSQLInjectionViaEncoding($input, $expected) $result = $this->connection->quote($input); $this->assertEquals($expected, $result); - $this->assertFalse(strpos($result, "';") !== false, "Potential SQL injection point found"); + $this->assertFalse(strpos($result, "';") !== false, 'Potential SQL injection point found'); } public static function sqlInjectionEncodingProvider(): array @@ -86,39 +86,39 @@ public static function sqlInjectionEncodingProvider(): array return [ 'Single Quote' => [ "OR '1'='1;", - "'OR \\'1\\'=\\'1;'" + "'OR \\'1\\'=\\'1;'", ], 'Double Quote' => [ 'OR "1"="1;', - "'OR \\\"1\\\"=\\\"1;'" + "'OR \\\"1\\\"=\\\"1;'", ], 'Latin1 to UTF-8 Single Quote' => [ - utf8_encode("¿'").";", - "'¿\\';'" + mb_convert_encoding("¿'", 'utf8').';', + "'¿\\';'", ], 'Unicode Code Points' => [ "' OR 1=1--;", - "'\\' OR 1=1--;'" + "'\\' OR 1=1--;'", ], 'URL Encoded Quotes' => [ "' %27 OR '1'='1;", - "'\\' %27 OR \\'1\\'=\\'1;'" + "'\\' %27 OR \\'1\\'=\\'1;'", ], 'Multi-byte Character Before Quote' => [ '中文\'OR\'1\'=\'1;', - "'中文\\'OR\\'1\\'=\\'1;'" + "'中文\\'OR\\'1\\'=\\'1;'", ], 'Null Byte Injection' => [ "admin\0' OR '1'='1;", - "'admin\\0\\' OR \\'1\\'=\\'1;'" + "'admin\\0\\' OR \\'1\\'=\\'1;'", ], 'Unicode Normalization' => [ "¼' OR '1'='1;", - "'¼\\' OR \\'1\\'=\\'1;'" + "'¼\\' OR \\'1\\'=\\'1;'", ], 'Emoji with Single Quote' => [ "🔥' OR '1'='1;", - "'🔥\\' OR \\'1\\'=\\'1;'" + "'🔥\\' OR \\'1\\'=\\'1;'", ], ]; }