packages/ztd-query-sqlite/tests/Unit/Sql/SqliteLexicalMaskerTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Sql;
6
7use Generator;
8use PHPUnit\Framework\Attributes\CoversClass;
9use PHPUnit\Framework\Attributes\DataProvider;
10use PHPUnit\Framework\Attributes\UsesClass;
11use PHPUnit\Framework\TestCase;
12use ZtdQuery\Platform\Sqlite\Sql\SqliteLexicalMasker;
13
14#[CoversClass(SqliteLexicalMasker::class)]
15#[UsesClass(\ZtdQuery\Platform\Sqlite\Sql\Lexing\QuotedSpan::class)]
16final class SqliteLexicalMaskerTest extends TestCase
17{
18    #[DataProvider('providerComments')]
19    public function testMaskCommentsMasksCommentsAsSingleLexicalSeparators(string $sql, string $expected): void
20    {
21        self::assertSame($expected, SqliteLexicalMasker::maskComments($sql));
22    }
23
24    #[DataProvider('providerQuotedForms')]
25    public function testPreservesCommentMarkersInsideQuotedForms(string $quoted, bool $terminated): void
26    {
27        $sql = 'SELECT ' . $quoted . '/* outside */1';
28        $expected = $terminated ? 'SELECT ' . $quoted . ' 1' : $sql;
29
30        self::assertSame($expected, SqliteLexicalMasker::maskComments($sql));
31    }
32
33    /**
34     * @return Generator<string, array{string, string}>
35     */
36    public static function providerComments(): Generator
37    {
38        yield 'empty query' => ['', ''];
39        yield 'line comment' => ['SELECT-- comment', 'SELECT '];
40        yield 'line comment with newline' => ["SELECT-- comment\n1", "SELECT \n1"];
41        yield 'line comment with carriage return' => ["SELECT-- comment\r1", "SELECT \r1"];
42        yield 'empty line comment' => ["--\nSELECT", " \nSELECT"];
43        yield 'separated minus signs' => ['SELECT- -1', 'SELECT- -1'];
44        yield 'hash comment' => ['SELECT# comment', 'SELECT '];
45        yield 'empty hash comment' => ["#\nSELECT", " \nSELECT"];
46        yield 'block comment' => ['SELECT/* comment */1', 'SELECT 1'];
47        yield 'minimal block comment' => ['SELECT/**/1', 'SELECT 1'];
48        yield 'adjacent block comments' => ['SELECT/**//**/1', 'SELECT  1'];
49        yield 'unterminated block comment' => ['SELECT/* comment', 'SELECT '];
50        yield 'separated slash and asterisk' => ['SELECT/ *1', 'SELECT/ *1'];
51        yield 'comment-like closing marker' => ['SELECT*/1', 'SELECT*/1'];
52        yield 'comment closing boundary' => ['SELECT/**/*1', 'SELECT *1'];
53        yield 'overlapping unterminated block marker' => ['SELECT/*/1', 'SELECT '];
54    }
55
56    /**
57     * @return Generator<string, array{string, bool}>
58     */
59    public static function providerQuotedForms(): Generator
60    {
61        yield 'single quoted line marker' => ["'-- comment'", true];
62        yield 'single quoted block marker' => ["'/* comment */'", true];
63        yield 'empty single quote' => ["''", true];
64        yield 'doubled single quote' => ["'value''/* comment */'", true];
65        yield 'triple single quote closing run' => ["'value'''", true];
66        yield 'unterminated single quote' => ["'/* comment", false];
67        yield 'double quoted line marker' => ['"-- comment"', true];
68        yield 'double quoted block marker' => ['"/* comment */"', true];
69        yield 'empty double quote' => ['""', true];
70        yield 'doubled double quote' => ['"value""/* comment */"', true];
71        yield 'unterminated double quote' => ['"/* comment', false];
72        yield 'backtick quoted hash marker' => ['`# comment`', true];
73        yield 'empty backtick quote' => ['``', true];
74        yield 'doubled backtick' => ['`value``/* comment */`', true];
75        yield 'unterminated backtick' => ['`/* comment', false];
76        yield 'bracket quoted line marker' => ['[-- comment]', true];
77        yield 'bracket quoted block marker' => ['[/* comment */]', true];
78        yield 'empty bracket quote' => ['[]', true];
79        yield 'unterminated bracket' => ['[/* comment', false];
80    }
81}
82