packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Routine/AggregateArgumentRuleTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite\Routine;
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\Routine\AggregateArgumentRule;
15
16#[CoversClass(AggregateArgumentRule::class)]
17#[UsesClass(ProductionOccurrence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(TerminalSequence::class)]
20final class AggregateArgumentRuleTest extends TestCase
21{
22    #[DataProvider('providerModes')]
23    public function testRewriteKeepsOrdinaryFunctionModesAndNormalizesAggregateInputModes(string $scope, string $mode, bool $ordered, bool $kept): void
24    {
25        $words = explode(' ', $mode);
26        $modes = array_map(static fn (int $index, string $name): TerminalOccurrence =>
27            new TerminalOccurrence($name, $index + 10, [0, 1, 2], ['aggr_args', $scope, 'arg_class']), array_keys($words), $words);
28        $order = new TerminalOccurrence('ORDER', 20, [0], ['aggr_args']);
29        $terminals = [...$modes, ...($ordered ? [$order] : [])];
30        $input = new TerminalSequence($terminals, $terminals, [], [
31            new ProductionOccurrence(0, null, 'aggr_args', 0), new ProductionOccurrence(1, 0, $scope, 0),
32            new ProductionOccurrence(2, 1, 'arg_class', 0),
33        ]);
34        $rule = new AggregateArgumentRule();
35        $result = $rule->rewrite($input);
36        self::assertSame([...($kept ? $words : ['IN_P']), ...($ordered ? ['ORDER'] : [])], $result->names());
37        self::assertSame($input->original, $result->original);
38        self::assertSame($result, $rule->rewrite($result));
39    }
40
41    /**
42     * @return iterable<array{string, string, bool, bool}>
43     */
44    public static function providerModes(): iterable
45    {
46        yield ['aggr_arg', 'OUT_P', false, false];
47        yield ['aggr_arg', 'INOUT', false, false];
48        yield ['aggr_arg', 'IN_P OUT_P', false, false];
49        yield ['aggr_arg', 'IN_P', true, true];
50        yield ['aggr_arg', 'VARIADIC', false, true];
51        yield ['aggr_arg', 'VARIADIC', true, false];
52        yield ['func_arg', 'OUT_P', false, true];
53    }
54}
55