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