packages/sql-faker/tests/Unit/Generation/Plan/Compilation/ScopeTest.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\Scope;
11use SqlFaker\Generation\Plan\LexemeConstraint;
12use SqlFaker\Generation\Plan\RulePlan;
13
14#[CoversClass(Scope::class)]
15#[UsesClass(RulePlan::class)]
16#[UsesClass(LexemeConstraint::class)]
17final class ScopeTest extends TestCase
18{
19 public function testEnterNearerScopesOverrideDefaultsWithoutLeakingToSiblings(): void
20 {
21 $outer = new Scope([], ['ID' => LexemeConstraint::oneOf('outer')]);
22 $inner = $outer->enter(RulePlan::any()->withLexeme('ID', LexemeConstraint::oneOf('inner')));
23 self::assertTrue($inner->lexemes['ID']->accepts('inner'));
24 self::assertFalse($inner->lexemes['ID']->accepts('outer'));
25 self::assertTrue($outer->lexemes['ID']->accepts('outer'));
26 }
27
28 public function testEnterOverridesOnlyDeclaredRolesAndCanonicalizesIndependentDeclarationOrder(): void
29 {
30 $defaultName = RulePlan::any();
31 $targetName = RulePlan::any()->withLexeme('ID', LexemeConstraint::oneOf('users'));
32 $value = RulePlan::any()->withLexeme('INTEGER', LexemeConstraint::oneOf('42'));
33 $identifier = LexemeConstraint::oneOf('outer');
34 $literal = LexemeConstraint::oneOf("'Alice'");
35 $first = (new Scope(['value' => $value, 'name' => $defaultName], ['STRING' => $literal, 'ID' => $identifier]))
36 ->enter(RulePlan::any()->withRule('name', $targetName)->withLexeme('ID', LexemeConstraint::oneOf('inner')));
37 $second = (new Scope(['name' => $defaultName, 'value' => $value], ['ID' => $identifier, 'STRING' => $literal]))
38 ->enter(RulePlan::any()->withLexeme('ID', LexemeConstraint::oneOf('inner'))->withRule('name', $targetName));
39 self::assertSame(['name' => $targetName, 'value' => $value], $first->rules);
40 self::assertSame($literal, $first->lexemes['STRING']);
41 self::assertSame(serialize($first), serialize($second));
42 }
43
44}
45