packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/LookaheadRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite;
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\LookaheadRule;
15
16#[CoversClass(LookaheadRule::class)]
17#[UsesClass(TerminalSequence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(\SqlFaker\PostgreSql\Generation\Lookahead\PgLookahead::class)]
20#[UsesClass(ProductionOccurrence::class)]
21final class LookaheadRuleTest extends TestCase
22{
23 #[DataProvider('providerOptionNames')]
24 public function testRewriteKeepsWithBeforeOptionNamesAsTheGrammarRequires(string $name, string $prefix, string $scope, string $expected): void
25 {
26 $input = new TerminalSequence([
27 new TerminalOccurrence($prefix, 10, [0], ['GrantRoleStmt']),
28 new TerminalOccurrence($name, 11, [0, 1, 2], ['GrantRoleStmt', $scope, 'ColLabel']),
29 new TerminalOccurrence('OPTION', 12, [0, 1], ['GrantRoleStmt', $scope]),
30 ], productions: [new ProductionOccurrence(0, null, 'GrantRoleStmt', 0), new ProductionOccurrence(1, 0, $scope, 0), new ProductionOccurrence(2, 1, 'ColLabel', 0)]);
31 $result = (new LookaheadRule())->rewrite($input);
32 self::assertSame($expected, $result->terminals[1]->name);
33 self::assertSame($input->terminals[1]->id, $result->terminals[1]->id);
34 self::assertSame($input->productions, $result->productions);
35 self::assertSame($result, (new LookaheadRule())->rewrite($result));
36 }
37
38 /**
39 * @return list<array{string, string, string, string}>
40 */
41 public static function providerOptionNames(): array
42 {
43 return [['ORDINALITY', 'WITH', 'grant_role_opt', 'IDENT'], ['TIME', 'WITH_LA', 'grant_role_opt', 'IDENT'], ['IDENT', 'WITH', 'grant_role_opt', 'IDENT'], ['TIME', ',', 'grant_role_opt', 'TIME'], ['ORDINALITY', 'WITH', 'ordinary', 'ORDINALITY']];
44 }
45
46 public function testRewriteResolvesAliasesFromTheActualFollowersAndRecordsChanges(): void
47 {
48 $input = TerminalSequence::fromNames(['WITH_LA', 'IDENT', 'WITH', 'ORDINALITY']);
49 $result = (new LookaheadRule())->rewrite($input);
50 self::assertSame(['WITH', 'IDENT', 'WITH_LA', 'ORDINALITY'], $result->names());
51 self::assertSame($input->original, $result->original);
52 self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
53 self::assertCount(2, $result->rewrites);
54 self::assertSame($result, (new LookaheadRule())->rewrite($result));
55 }
56}
57