packages/sql-faker/tests/Unit/MySql/Generation/Rewrite/SetNamesRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Rewrite;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Derivation\DerivationTrace;
11use SqlFaker\Grammar\Model\NonTerminal;
12use SqlFaker\Grammar\Model\Production;
13use SqlFaker\Grammar\Model\Terminal;
14use SqlFaker\MySql\Generation\Rewrite\SetNamesRule;
15
16#[CoversClass(SetNamesRule::class)]
17#[UsesClass(DerivationTrace::class)]
18#[UsesClass(NonTerminal::class)]
19#[UsesClass(Production::class)]
20#[UsesClass(Terminal::class)]
21#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
22#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
23#[UsesClass(\SqlFaker\Generation\Token\TerminalSequence::class)]
24final class SetNamesRuleTest extends TestCase
25{
26 public function testRewriteRepairsColonEqualsWithoutChangingOtherAssignments(): void
27 {
28 $trace = new DerivationTrace('option_value_no_option_type');
29 $trace->expand(0, new Production([new Terminal('NAMES_SYM'), new Terminal('SET_VAR'), new Terminal('NUM')]), 0);
30 $input = $trace->terminals();
31 $result = (new SetNamesRule())->rewrite($input);
32 self::assertSame(['NAMES_SYM', 'DEFAULT_SYM'], $result->names());
33 self::assertSame($input->original, $result->original);
34 self::assertSame($input->productions, $result->productions);
35 self::assertSame($result, (new SetNamesRule())->rewrite($result));
36
37 $ordinary = new DerivationTrace('option_value_no_option_type');
38 $ordinary->expand(0, new Production([new Terminal('IDENT'), new Terminal('SET_VAR'), new Terminal('NUM')]), 0);
39 $assignment = $ordinary->terminals();
40 self::assertSame($assignment, (new SetNamesRule())->rewrite($assignment));
41 }
42
43 public function testRewriteUsesTheConfiguredDefaultToken(): void
44 {
45 $trace = new DerivationTrace('option_value_no_option_type');
46 $trace->expand(0, new Production([new Terminal('NAMES_SYM'), new Terminal('EQ'), new Terminal('NUM')]), 0);
47 self::assertSame(['NAMES_SYM', 'DEFAULT'], (new SetNamesRule('DEFAULT'))->rewrite($trace->terminals())->names());
48 }
49
50 public function testRewriteReplacesTheEntireErrorProductionWithoutTouchingAdjacentOptions(): void
51 {
52 $trace = new DerivationTrace('root');
53 $trace->expand(0, new Production([new NonTerminal('option_value_no_option_type'), new Terminal(','), new Terminal('IDENT'), new Terminal('EQ'), new Terminal('NUM')]), 0);
54 $trace->expand(0, new Production([new Terminal('NAMES_SYM'), new Terminal('EQ'), new Terminal('COMPLEX'), new Terminal('EXPR')]), 0);
55 $input = $trace->terminals();
56 $result = (new SetNamesRule())->rewrite($input);
57 self::assertSame(['NAMES_SYM', 'DEFAULT_SYM', ',', 'IDENT', 'EQ', 'NUM'], $result->names());
58 self::assertSame($input->original, $result->original);
59 self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
60 self::assertSame($result, (new SetNamesRule())->rewrite($result));
61 }
62}
63