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