Skip to content

Commit

Permalink
refactor: format and merge tests
Browse files Browse the repository at this point in the history
  • Loading branch information
darkterminal committed Jul 17, 2024
1 parent 6c7ee8f commit 0b0ecfb
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 46 deletions.
6 changes: 3 additions & 3 deletions src/Database/LibSQLConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
6 changes: 3 additions & 3 deletions src/Database/LibSQLDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
};
}
Expand Down Expand Up @@ -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';
Expand Down
26 changes: 17 additions & 9 deletions tests/Feature/ConnectionsSetupTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Turso\Driver\Laravel\Database\LibSQLConnection;
use Turso\Driver\Laravel\Database\LibSQLDatabase;


class ConnectionsSetupTest extends TestCase
{
public function setUp(): void
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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');
}
}
31 changes: 16 additions & 15 deletions tests/Feature/CreateRecordsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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');
Expand All @@ -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',
Expand All @@ -62,16 +64,15 @@ 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',
'json' => json_encode(['test2' => 'test']),
'string' => 'string2',
]);


$data = DB::connection('local_file')
$data = DB::connection('libsql')
->table('test')
->select()
->get();
Expand All @@ -84,7 +85,7 @@ public function testWithBLOBType(): void
{
$modelClass = new class extends Model
{
protected $connection = 'local_file';
protected $connection = 'libsql';

protected $table = 'test';

Expand All @@ -104,7 +105,7 @@ public function casts()

$model->save();

$data = DB::connection('local_file')
$data = DB::connection('libsql')
->table('test')
->select()
->get()
Expand All @@ -117,7 +118,7 @@ public function testCreateViaEloquent(): void
{
$modelClass = new class extends Model
{
protected $connection = 'local_file';
protected $connection = 'libsql';

protected $table = 'test';

Expand All @@ -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();
Expand Down
32 changes: 16 additions & 16 deletions tests/Unit/LibSQLConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
];
}
Expand All @@ -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)."'"],
];
}

Expand All @@ -78,47 +78,47 @@ 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
{
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;'",
],
];
}
Expand Down

0 comments on commit 0b0ecfb

Please sign in to comment.