packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Routine/SubstringRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite\Routine;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFaker\Generation\Token\ProductionOccurrence;
12use SqlFaker\Generation\Token\TerminalOccurrence;
13use SqlFaker\Generation\Token\TerminalSequence;
14use SqlFaker\PostgreSql\Generation\Rewrite\Routine\SubstringRule;
15
16#[CoversClass(SubstringRule::class)]
17#[UsesClass(ProductionOccurrence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(TerminalSequence::class)]
20final class SubstringRuleTest extends TestCase
21{
22 #[DataProvider('providerArguments')]
23 public function testRewriteKeepsSubstringSeparatorsOutsideCompoundArguments(TerminalSequence $input, string $expected): void
24 {
25 $rule = new SubstringRule();
26 $result = $rule->rewrite($input);
27 self::assertSame(explode(' ', $expected), $result->names());
28 self::assertSame($input->original, $result->original);
29 self::assertSame($input->productions, $result->productions);
30 self::assertSame($input->terminals, array_values(array_filter($result->terminals, static fn (TerminalOccurrence $token): bool => $token->id >= 0)));
31 self::assertCount(count($result->terminals), array_unique(array_column($result->terminals, 'id')));
32 self::assertSame($result, $rule->rewrite($result));
33 }
34
35 /**
36 * @return iterable<array{TerminalSequence, string}>
37 */
38 public static function providerArguments(): iterable
39 {
40 foreach (['substr_list', 'func_arg_list'] as $scope) {
41 $tokens = [];
42 foreach ([1 => 'DEFAULT IS NOT DISTINCT FROM DEFAULT', 0 => 'SIMILAR', 2 => 'DEFAULT LIKE DEFAULT', 4 => 'ESCAPE', 3 => 'DEFAULT'] as $id => $text) {
43 foreach (explode(' ', $text) as $name) {
44 $tokens[] = new TerminalOccurrence($name, count($tokens), $id === 0 || $id === 4 ? [0] : [0, $id], $id === 0 || $id === 4 ? [$scope] : [$scope, 'a_expr']);
45 }
46 }
47 $productions = [new ProductionOccurrence(0, null, $scope, 0), new ProductionOccurrence(1, 0, 'a_expr', 0), new ProductionOccurrence(2, 0, 'a_expr', 0), new ProductionOccurrence(3, 0, 'a_expr', 0)];
48 yield [new TerminalSequence($tokens, $tokens, productions: $productions), $scope === 'substr_list' ? '( DEFAULT IS NOT DISTINCT FROM DEFAULT ) SIMILAR ( DEFAULT LIKE DEFAULT ) ESCAPE DEFAULT' : 'DEFAULT IS NOT DISTINCT FROM DEFAULT SIMILAR DEFAULT LIKE DEFAULT ESCAPE DEFAULT'];
49 }
50 }
51
52 public function testRewritePreservesAnEmptyArgument(): void
53 {
54 $input = new TerminalSequence([], productions: [new ProductionOccurrence(0, null, 'substr_list', 0), new ProductionOccurrence(1, 0, 'a_expr', 0)]);
55 self::assertSame($input, (new SubstringRule())->rewrite($input));
56 }
57}
58