packages/sql-faker/tests/Unit/MySql/Generation/Rewrite/Partition/FieldListRuleTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Rewrite\Partition;
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\Generation\Token\TerminalSequence;
13use SqlFaker\Grammar\Model\NonTerminal;
14use SqlFaker\Grammar\Model\Production;
15use SqlFaker\Grammar\Model\Terminal;
16use SqlFaker\MySql\Generation\Rewrite\Partition\FieldListRule;
17
18#[CoversClass(FieldListRule::class)]
19#[UsesClass(DerivationTrace::class)]
20#[UsesClass(NonTerminal::class)]
21#[UsesClass(Production::class)]
22#[UsesClass(Terminal::class)]
23#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
24#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
25#[UsesClass(TerminalSequence::class)]
26final class FieldListRuleTest extends TestCase
27{
28    /**
29     * @param list<string> $expected
30     */
31    #[DataProvider('providerLists')]
32    public function testRewriteKeepsUpToSixteenPartitionFieldsAndPreservesOtherLists(TerminalSequence $input, array $expected): void
33    {
34        $rule = new FieldListRule();
35        $result = $rule->rewrite($input);
36        self::assertSame($expected, $result->names());
37        self::assertSame($input->original, $result->original);
38        self::assertSame($input->productions, $result->productions);
39        self::assertSame($input->terminals[1], $result->terminals[1]);
40        self::assertSame($result, $rule->rewrite($result));
41    }
42
43    /**
44     * @return iterable<array{TerminalSequence, list<string>}>
45     */
46    public static function providerLists(): iterable
47    {
48        foreach ([['part_type_def', 'name_list', true], ['opt_sub_part', 'name_list', true], ['part_field_list', 'part_field_item_list', true], ['opt_sub_part', 'sub_part_field_list', true], ['ordinary', 'name_list', false]] as [$scope, $list, $limited]) {
49            foreach ([1, 16, 17, 19] as $count) {
50                $trace = new DerivationTrace($scope);
51                $trace->expand(0, new Production([new Terminal('PREFIX'), new NonTerminal($list), new Terminal('TAIL')]), 0);
52                $symbols = [];
53                $expected = ['PREFIX'];
54                for ($index = 0; $index < $count; ++$index) {
55                    if ($index !== 0) {
56                        $symbols[] = new Terminal(',');
57                    }
58                    $symbols[] = new NonTerminal('ident');
59                    if (!$limited || $index < 16) {
60                        if ($index !== 0) {
61                            $expected[] = ',';
62                        }
63                        $expected[] = 'FIELD_' . $index;
64                    }
65                }
66                $trace->expand(1, new Production($symbols), 0);
67                for ($index = 0; $index < $count; ++$index) {
68                    $trace->expand(1 + 2 * $index, new Production([new Terminal('FIELD_' . $index)]), 0);
69                }
70                yield [$trace->terminals(), [...$expected, 'TAIL']];
71            }
72        }
73    }
74}
75