packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Option/UniqueOptionRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite\Option;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Derivation\DerivationTrace;
11use SqlFaker\Generation\Token\ProductionOccurrence;
12use SqlFaker\Generation\Token\TerminalOccurrence;
13use SqlFaker\Generation\Token\TerminalSequence;
14use SqlFaker\Grammar\Model\NonTerminal;
15use SqlFaker\Grammar\Model\Production;
16use SqlFaker\Grammar\Model\Terminal;
17use SqlFaker\PostgreSql\Generation\Rewrite\Option\UniqueOptionRule;
18
19#[CoversClass(UniqueOptionRule::class)]
20#[UsesClass(DerivationTrace::class)]
21#[UsesClass(NonTerminal::class)]
22#[UsesClass(Production::class)]
23#[UsesClass(ProductionOccurrence::class)]
24#[UsesClass(Terminal::class)]
25#[UsesClass(TerminalOccurrence::class)]
26#[UsesClass(TerminalSequence::class)]
27final class UniqueOptionRuleTest extends TestCase
28{
29 public function testRewriteRetainsFirstValuesAndDoesNotShareStateBetweenScopes(): void
30 {
31 $first = new TerminalOccurrence('NOT', 2, [0, 1], ['column', 'option']);
32 $duplicate = new TerminalOccurrence('NULL', 4, [0, 3], ['column', 'option']);
33 $other = new TerminalOccurrence('NULL', 7, [5, 6], ['column', 'option']);
34 $input = new TerminalSequence([$first, $duplicate, $other], [$first, $duplicate, $other], [], [
35 new ProductionOccurrence(1, 0, 'option', 0), new ProductionOccurrence(3, 0, 'option', 1),
36 new ProductionOccurrence(6, 5, 'option', 1),
37 ]);
38 $result = (new UniqueOptionRule('column', 'option', ['NOT' => 'null', 'NULL' => 'null'], null, 'source:option'))->rewrite($input);
39 self::assertSame([$first, $other], $result->terminals);
40 self::assertSame($input->original, $result->original);
41 self::assertSame($input->productions, $result->productions);
42 }
43
44 public function testRewriteRemovesTheDuplicateSeparatorAndRetainsOtherCategories(): void
45 {
46 $trace = new DerivationTrace('trigger');
47 $trace->expand(0, new Production([new NonTerminal('event'), new Terminal('OR'), new NonTerminal('event'), new Terminal('OR'), new NonTerminal('event')]), 0);
48 $trace->expand(0, new Production([new Terminal('INSERT')]), 0);
49 $trace->expand(2, new Production([new Terminal('INSERT')]), 0);
50 $trace->expand(4, new Production([new Terminal('UPDATE')]), 1);
51 $result = (new UniqueOptionRule('trigger', 'event', ['INSERT' => 'insert', 'UPDATE' => 'update'], 'OR', 'source:event'))->rewrite($trace->terminals());
52 self::assertSame(['INSERT', 'OR', 'UPDATE'], $result->names());
53 }
54}
55