packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Column/IdentityOptionRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite\Column;
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\Grammar\Model\NonTerminal;
13use SqlFaker\Grammar\Model\Production;
14use SqlFaker\Grammar\Model\Terminal;
15use SqlFaker\PostgreSql\Generation\Rewrite\Column\IdentityOptionRule;
16
17#[CoversClass(IdentityOptionRule::class)]
18#[UsesClass(DerivationTrace::class)]
19#[UsesClass(NonTerminal::class)]
20#[UsesClass(Production::class)]
21#[UsesClass(Terminal::class)]
22#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
23#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
24#[UsesClass(\SqlFaker\Generation\Token\TerminalSequence::class)]
25final class IdentityOptionRuleTest extends TestCase
26{
27 /**
28 * @param list<string> $option
29 * @param list<string> $expected
30 */
31 #[DataProvider('providerOptions')]
32 public function testRewriteKeepsSequenceOptionsWithinTheirOwningContext(string $scope, array $option, array $expected): void
33 {
34 $trace = new DerivationTrace($scope);
35 $trace->expand(0, new Production([new Terminal('SET'), new NonTerminal('SeqOptElem')]), 0);
36 $trace->expand(1, new Production(array_map(static fn (string $name): Terminal => new Terminal($name), $option)), 0);
37 $input = $trace->terminals();
38 $rule = new IdentityOptionRule();
39 $result = $rule->rewrite($input);
40 self::assertSame($expected, $result->names());
41 self::assertSame($input->original, $result->original);
42 self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
43 self::assertSame($result, $rule->rewrite($result));
44 }
45
46 /**
47 * @return iterable<array{string, list<string>, list<string>}>
48 */
49 public static function providerOptions(): iterable
50 {
51 foreach ([['AS', 'INT_P'], ['OWNED', 'BY', 'IDENT']] as $option) {
52 yield ['alter_identity_column_option', $option, ['SET', 'NO', 'CYCLE']];
53 yield ['SeqOptList', $option, ['SET', ...$option]];
54 }
55 yield ['alter_identity_column_option', ['RESTART'], ['RESTART']];
56 yield ['alter_identity_column_option', ['RESTART', 'WITH', 'ICONST'], ['RESTART', 'WITH', 'ICONST']];
57 yield ['alter_identity_column_option', ['NO', 'CYCLE'], ['SET', 'NO', 'CYCLE']];
58 yield ['alter_identity_column_option', ['CACHE', 'ICONST'], ['SET', 'CACHE', 'ICONST']];
59 yield ['alter_identity_column_option', [], ['SET']];
60 }
61
62 public function testRewriteLeavesTheDedicatedRestartAlternativeUntouched(): void
63 {
64 $trace = new DerivationTrace('alter_identity_column_option');
65 $trace->expand(0, new Production([new Terminal('RESTART'), new Terminal('ICONST')]), 0);
66 $input = $trace->terminals();
67 self::assertSame($input, (new IdentityOptionRule())->rewrite($input));
68 }
69}
70