packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Name/AnyRelationNameRuleTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite\Name;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFaker\Generation\Token\ProductionOccurrence;
12use SqlFaker\Generation\Token\TerminalOccurrence;
13use SqlFaker\Generation\Token\TerminalSequence;
14use SqlFaker\PostgreSql\Generation\Rewrite\Name\AnyRelationNameRule;
15
16#[CoversClass(AnyRelationNameRule::class)]
17#[UsesClass(ProductionOccurrence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(TerminalSequence::class)]
20final class AnyRelationNameRuleTest extends TestCase
21{
22    /**
23     * @param list<string> $expected
24     */
25    #[DataProvider('providerNames')]
26    public function testRewriteLimitsOnlyNamesConvertedToRelations(TerminalSequence $input, array $expected): void
27    {
28        $rule = new AnyRelationNameRule();
29        $result = $rule->rewrite($input);
30        self::assertSame($expected, $result->names());
31        self::assertSame($input->original, $result->original);
32        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
33        self::assertSame($result, $rule->rewrite($result));
34    }
35
36    /**
37     * @return iterable<string, array{TerminalSequence, list<string>}>
38     */
39    public static function providerNames(): iterable
40    {
41        foreach (['AlterCompositeTypeStmt', 'DefineStmt', 'RenameStmt', 'DropStmt', 'CreateDomainStmt'] as $scope) {
42            $names = [new TerminalOccurrence('IDENT', 100, [0, 1], [$scope, 'any_name'])];
43            $productions = [new ProductionOccurrence(0, null, $scope, 0), new ProductionOccurrence(1, 0, 'any_name', 0)];
44            foreach (range(2, 4) as $id) {
45                $names[] = new TerminalOccurrence('.', 100 + count($names), [0, 1], [$scope, 'any_name']);
46                $names[] = new TerminalOccurrence('IDENT', 100 + count($names), [0, 1, $id], [$scope, 'any_name', 'attr_name']);
47                $productions[] = new ProductionOccurrence($id, 1, 'attr_name', 0);
48            }
49            $suffix = [];
50            if ($scope === 'DefineStmt') {
51                $productions[] = new ProductionOccurrence(9, 0, 'OptTableFuncElementList', 0);
52            }
53            if ($scope === 'RenameStmt') {
54                $suffix = ['RENAME', 'ATTRIBUTE'];
55                $names[] = new TerminalOccurrence('RENAME', 110, [0], [$scope]);
56                $names[] = new TerminalOccurrence('ATTRIBUTE', 111, [0], [$scope]);
57            }
58            $expected = ['IDENT', '.', 'IDENT', '.', 'IDENT'];
59            if (in_array($scope, ['DropStmt', 'CreateDomainStmt'], true)) {
60                array_push($expected, '.', 'IDENT');
61            }
62            yield $scope => [new TerminalSequence($names, $names, [], $productions), [...$expected, ...$suffix]];
63        }
64    }
65}
66