packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Name/ColumnNameRuleTest.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\ColumnNameRule;
15
16#[CoversClass(ColumnNameRule::class)]
17#[UsesClass(ProductionOccurrence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(TerminalSequence::class)]
20#[UsesClass(\SqlFaker\PostgreSql\Generation\Rewrite\Name\ParserNameRule::class)]
21#[UsesClass(\SqlFaker\PostgreSql\Generation\Rewrite\Column\NumericContextRule::class)]
22final class ColumnNameRuleTest extends TestCase
23{
24 /**
25 * @param list<TerminalOccurrence> $terminals
26 * @param list<ProductionOccurrence> $productions
27 * @param list<string> $expected
28 */
29 #[DataProvider('providerChains')]
30 public function testRewriteKeepsTheFinalColumnAndIndependentIndirections(array $terminals, array $productions, array $expected): void
31 {
32 $input = new TerminalSequence($terminals, $terminals, [], $productions);
33 $rule = new ColumnNameRule();
34 $result = $rule->rewrite($input);
35 self::assertSame($expected, $result->names());
36 self::assertSame($input->original, $result->original);
37 self::assertSame($input->productions, $result->productions);
38 self::assertSame($result, $rule->rewrite($result));
39 }
40
41 /**
42 * @return iterable<array{list<TerminalOccurrence>, list<ProductionOccurrence>, list<string>}>
43 */
44 public static function providerChains(): iterable
45 {
46 foreach (['columnref', 'a_expr'] as $context) {
47 foreach ([2, 3, 4, 5] as $count) {
48 foreach ([false, true] as $subscript) {
49 $terminals = [new TerminalOccurrence('IDENT', 100, [0], [$context])];
50 $productions = [];
51 $expected = ['IDENT'];
52 for ($index = 1; $index <= $count; ++$index) {
53 $rules = [$context, 'indirection', 'indirection_el'];
54 $ancestors = [0, 10, $index];
55 $names = $index === 2 && $subscript ? ['[', 'ICONST', ']'] : ['.', $index === $count ? '*' : 'NAME' . $index];
56 $productions[] = new ProductionOccurrence($index, 10, 'indirection_el', 0);
57 foreach ($names as $offset => $name) {
58 $terminals[] = new TerminalOccurrence($name, $index * 10 + $offset, $ancestors, $rules);
59 }
60 if ($context !== 'columnref' || $subscript || $index > $count - 3) {
61 $expected = [...$expected, ...$names];
62 }
63 }
64 yield [$terminals, $productions, $expected];
65 }
66 }
67 }
68 }
69
70 public function testRewritePreservesAnEmptyIndirection(): void
71 {
72 $input = new TerminalSequence([], [], [], [new ProductionOccurrence(0, null, 'indirection_el', 0)]);
73 self::assertSame($input, (new ColumnNameRule())->rewrite($input));
74 }
75}
76