packages/sql-faker/tests/Unit/Sqlite/Generation/Rewrite/GeneratedColumnRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Sqlite\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\Derivation\DerivationTrace;
12use SqlFaker\Generation\Token\ProductionOccurrence;
13use SqlFaker\Generation\Token\TerminalOccurrence;
14use SqlFaker\Generation\Token\TerminalSequence;
15use SqlFaker\Grammar\Model\NonTerminal;
16use SqlFaker\Grammar\Model\Production;
17use SqlFaker\Grammar\Model\Terminal;
18use SqlFaker\Sqlite\Generation\Rewrite\GeneratedColumnRule;
19
20#[CoversClass(GeneratedColumnRule::class)]
21#[UsesClass(DerivationTrace::class)]
22#[UsesClass(ProductionOccurrence::class)]
23#[UsesClass(TerminalOccurrence::class)]
24#[UsesClass(TerminalSequence::class)]
25#[UsesClass(NonTerminal::class)]
26#[UsesClass(Production::class)]
27#[UsesClass(Terminal::class)]
28final class GeneratedColumnRuleTest extends TestCase
29{
30 /**
31 * @param list<string> $expected
32 */
33 #[DataProvider('providerConstraints')]
34 public function testRewriteKeepsOneGeneratedExpressionWithoutDefaults(TerminalSequence $input, array $expected): void
35 {
36 $rule = new GeneratedColumnRule();
37 $result = $rule->rewrite($input);
38 self::assertSame($expected, $result->names());
39 self::assertSame($input->original, $result->original);
40 self::assertSame($input->productions, $result->productions);
41 self::assertSame($result, $rule->rewrite($result));
42 }
43
44 /**
45 * @return iterable<array{TerminalSequence, list<string>}>
46 */
47 public static function providerConstraints(): iterable
48 {
49 foreach (['column', 'carglist'] as $scope) {
50 foreach ([['AS', 'AS'], ['DEFAULT', 'AS'], ['AS', 'DEFAULT'], ['DEFAULT', 'DEFAULT'], ['AS', 'NULL', 'AS', 'DEFAULT']] as $clauses) {
51 $trace = new DerivationTrace($scope);
52 $trace->expand(0, new Production(array_fill(0, count($clauses), new NonTerminal('ccons'))), 0);
53 $position = 0;
54 $expected = [];
55 $seen = false;
56 foreach ($clauses as $index => $clause) {
57 if ($clause === 'AS') {
58 $trace->expand($position, new Production([new Terminal('AS'), new NonTerminal('generated')]), 0);
59 $trace->expand($position + 1, new Production([new Terminal('LP'), new Terminal('VALUE_' . $index), new Terminal('RP')]), 0);
60 if (!$seen) {
61 array_push($expected, 'AS', 'LP', 'VALUE_' . $index, 'RP');
62 }
63 $seen = true;
64 $position += 4;
65 } else {
66 $trace->expand($position, new Production([new Terminal($clause)]), 0);
67 if ($clause !== 'DEFAULT' || !in_array('AS', $clauses, true)) {
68 $expected[] = $clause;
69 }
70 ++$position;
71 }
72 }
73 yield [$trace->terminals(), $expected];
74 }
75 }
76 }
77
78 public function testRewriteKeepsGeneratedExpressionsOnSeparateColumns(): void
79 {
80 $trace = new DerivationTrace('table');
81 $trace->expand(0, new Production([new NonTerminal('column'), new Terminal('COMMA'), new NonTerminal('column')]), 0);
82 $trace->expand(0, new Production([new NonTerminal('ccons')]), 0);
83 $trace->expand(0, new Production([new Terminal('AS'), new NonTerminal('generated')]), 0);
84 $trace->expand(1, new Production([new Terminal('FIRST')]), 0);
85 $trace->expand(3, new Production([new NonTerminal('ccons')]), 0);
86 $trace->expand(3, new Production([new Terminal('AS'), new NonTerminal('generated')]), 0);
87 $trace->expand(4, new Production([new Terminal('SECOND')]), 0);
88 $input = $trace->terminals();
89 self::assertSame($input, (new GeneratedColumnRule())->rewrite($input));
90 }
91}
92