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