packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/HashPartitionBoundRuleTest.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\Grammar\Model\NonTerminal;
12use SqlFaker\Grammar\Model\Production;
13use SqlFaker\Grammar\Model\Terminal;
14use SqlFaker\PostgreSql\Generation\Rewrite\HashPartitionBoundRule;
15
16#[CoversClass(HashPartitionBoundRule::class)]
17#[UsesClass(DerivationTrace::class)]
18#[UsesClass(NonTerminal::class)]
19#[UsesClass(Production::class)]
20#[UsesClass(Terminal::class)]
21#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
22#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
23#[UsesClass(\SqlFaker\Generation\Token\TerminalSequence::class)]
24final class HashPartitionBoundRuleTest extends TestCase
25{
26    public function testRewriteCompletesBothBoundsAndPreservesTheOriginalValue(): void
27    {
28        $trace = new DerivationTrace('PartitionBoundSpec');
29        $trace->expand(0, new Production([new Terminal('('), new NonTerminal('hash_partbound'), new Terminal(')')]), 0);
30        $trace->expand(1, new Production([new NonTerminal('hash_partbound_elem')]), 0);
31        $trace->expand(1, new Production([new Terminal('IDENT'), new NonTerminal('Iconst')]), 0);
32        $trace->expand(2, new Production([new Terminal('ICONST')]), 0);
33        $input = $trace->terminals();
34        $result = (new HashPartitionBoundRule())->rewrite($input);
35        self::assertSame(['(', 'HASH_BOUND_NAME', 'ICONST', ',', 'HASH_BOUND_NAME', 'ICONST', ')'], $result->names());
36        self::assertSame($input->terminals[2], $result->terminals[2]);
37        self::assertSame($input->original, $result->original);
38        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
39    }
40
41    public function testRewritePreservesTheFirstTwoValuesAndSurroundingStatements(): void
42    {
43        $trace = new DerivationTrace('PartitionBoundSpec');
44        $trace->expand(0, new Production([new Terminal('PREFIX'), new NonTerminal('hash_partbound'), new Terminal('TAIL')]), 0);
45        $trace->expand(1, new Production([new NonTerminal('hash_partbound_elem'), new Terminal(','), new NonTerminal('hash_partbound_elem'), new Terminal(','), new NonTerminal('hash_partbound_elem')]), 0);
46        $trace->expand(1, new Production([new Terminal('IDENT'), new NonTerminal('Iconst')]), 0);
47        $trace->expand(2, new Production([new Terminal('FIRST')]), 0);
48        $trace->expand(4, new Production([new Terminal('IDENT'), new NonTerminal('Iconst')]), 0);
49        $trace->expand(5, new Production([new Terminal('SECOND')]), 0);
50        $trace->expand(7, new Production([new Terminal('IDENT'), new NonTerminal('Iconst')]), 0);
51        $trace->expand(8, new Production([new Terminal('DISCARDED')]), 0);
52        $input = $trace->terminals();
53        $result = (new HashPartitionBoundRule())->rewrite($input);
54        self::assertSame(['PREFIX', 'HASH_BOUND_NAME', 'FIRST', ',', 'HASH_BOUND_NAME', 'SECOND', 'TAIL'], $result->names());
55        self::assertSame($input->terminals[2], $result->terminals[2]);
56        self::assertSame($input->terminals[5], $result->terminals[5]);
57        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
58    }
59}
60