packages/sql-faker/tests/Unit/Generation/Plan/Compilation/PreparedGrammarTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Generation\Plan\Compilation;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Plan\Compilation\PreparedGrammar;
11use SqlFaker\Generation\Plan\Compilation\ScopedGeneration;
12use SqlFaker\Generation\Plan\LexemeConstraint;
13use SqlFaker\Generation\Token\ProductionOccurrence;
14use SqlFaker\Generation\Token\TerminalOccurrence;
15use SqlFaker\Generation\Token\TerminalSequence;
16use SqlFaker\Grammar\Model\Grammar;
17use SqlFaker\Grammar\Model\Production;
18use SqlFaker\Grammar\Model\ProductionRule;
19use SqlFaker\Grammar\Model\Terminal;
20
21#[CoversClass(PreparedGrammar::class)]
22#[UsesClass(ScopedGeneration::class)]
23#[UsesClass(Grammar::class)]
24#[UsesClass(Production::class)]
25#[UsesClass(ProductionRule::class)]
26#[UsesClass(Terminal::class)]
27#[UsesClass(ProductionOccurrence::class)]
28#[UsesClass(TerminalOccurrence::class)]
29#[UsesClass(TerminalSequence::class)]
30#[UsesClass(LexemeConstraint::class)]
31final class PreparedGrammarTest extends TestCase
32{
33    public function testRestoreKeepsOriginalOrdinalsAndAncestorIdentity(): void
34    {
35        $grammar = new Grammar('@plan0', ['@plan0' => new ProductionRule('@plan0', [new Production([new Terminal('ID')], 7)])], ['@plan0' => 'name']);
36        $sequence = new TerminalSequence([new TerminalOccurrence('ID', 1, [0], ['@plan0'])], productions: [new ProductionOccurrence(0, null, '@plan0', 0)]);
37        $restored = (new PreparedGrammar($grammar, []))->restore($sequence)->sequence;
38        self::assertSame('name', $restored->productions[0]->rule);
39        self::assertSame(7, $restored->productions[0]->ordinal);
40        self::assertSame(['name'], $restored->terminals[0]->rules);
41        self::assertSame([0], $restored->terminals[0]->ancestors);
42        self::assertSame($restored->terminals, $restored->original);
43    }
44
45    public function testRestoreRetainsTheLexicalScopeOfEachSelectedProduction(): void
46    {
47        $grammar = new Grammar('special', ['special' => new ProductionRule('special', [new Production([new Terminal('ID')], 7)])], ['special' => 'name']);
48        $name = LexemeConstraint::oneOf('users');
49        $sequence = new TerminalSequence([new TerminalOccurrence('ID', 4, [3], ['special'])], productions: [new ProductionOccurrence(3, null, 'special', 0)]);
50        $restored = (new PreparedGrammar($grammar, ['special' => [0 => ['ID' => $name]]]))->restore($sequence);
51        self::assertSame($name, $restored->constraint($restored->sequence->terminals[0]));
52        self::assertSame(7, $restored->sequence->productions[0]->ordinal);
53    }
54
55}
56