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

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Derivation\DerivationTrace;
11use SqlFaker\Generation\Token\TerminalSequence;
12use SqlFaker\Grammar\Model\Production;
13use SqlFaker\Grammar\Model\Terminal;
14use SqlFaker\PostgreSql\Generation\Rewrite\OperatorArgumentsRule;
15
16#[CoversClass(OperatorArgumentsRule::class)]
17#[UsesClass(DerivationTrace::class)]
18#[UsesClass(Production::class)]
19#[UsesClass(Terminal::class)]
20#[UsesClass(TerminalSequence::class)]
21#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
22#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
23#[UsesClass(\SqlFaker\Grammar\Model\NonTerminal::class)]
24final class OperatorArgumentsRuleTest extends TestCase
25{
26    public function testRewriteCompletesOnlyAUnaryOperatorSignature(): void
27    {
28        $trace = new DerivationTrace('oper_argtypes');
29        $trace->expand(0, new Production([new Terminal('('), new Terminal('NUMERIC'), new Terminal('('), new Terminal('ICONST'), new Terminal(','), new Terminal('ICONST'), new Terminal(')'), new Terminal(')')]), 0);
30        $input = $trace->terminals();
31        $result = (new OperatorArgumentsRule())->rewrite($input);
32        self::assertSame(['(', 'NONE', ',', 'NUMERIC', '(', 'ICONST', ',', 'ICONST', ')', ')'], $result->names());
33        self::assertSame($input->original, $result->original);
34        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
35        self::assertSame($result, (new OperatorArgumentsRule())->rewrite($result));
36    }
37
38    public function testHasArgumentSeparatorDistinguishesNestedTypeModifiers(): void
39    {
40        $rule = new OperatorArgumentsRule();
41        $nested = TerminalSequence::fromNames(['(', 'NUMERIC', '(', 'ICONST', ',', 'ICONST', ')', ')']);
42        self::assertFalse($rule->hasArgumentSeparator($nested, 0, 8));
43        $binary = TerminalSequence::fromNames(['(', 'NONE', ',', 'INT', ')']);
44        self::assertTrue($rule->hasArgumentSeparator($binary, 0, 5));
45    }
46}
47