packages/sql-faker/tests/Unit/Generation/Coverage/SequenceObservationTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Generation\Coverage;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Coverage\SequenceObservation;
11use SqlFaker\Generation\Token\ProductionOccurrence;
12use SqlFaker\Generation\Token\TerminalOccurrence;
13use SqlFaker\Generation\Token\TerminalSequence;
14
15#[CoversClass(SequenceObservation::class)]
16#[UsesClass(ProductionOccurrence::class)]
17#[UsesClass(TerminalOccurrence::class)]
18#[UsesClass(TerminalSequence::class)]
19final class SequenceObservationTest extends TestCase
20{
21    public function testLeavesGroupsCompleteIdentitiesUnderEveryAncestor(): void
22    {
23        $leaf = new TerminalOccurrence('A', 2, [0, 1], ['root', 'child']);
24        self::assertSame([0 => [[2, 'A']], 1 => [[2, 'A']]], (new SequenceObservation())->leaves([$leaf]));
25        self::assertSame([], (new SequenceObservation())->leaves([]));
26    }
27
28    public function testPreservedCreditsUnmodifiedSiblingsAndTheirEmptyChildren(): void
29    {
30        $a = new TerminalOccurrence('A', 4, [0, 1], ['root', 'a']);
31        $b = new TerminalOccurrence('B', 5, [0, 2], ['root', 'b']);
32        $input = new TerminalSequence([$a, $b], [$a, $b], [], [
33            new ProductionOccurrence(0, null, 'root', 0), new ProductionOccurrence(1, 0, 'a', 0),
34            new ProductionOccurrence(2, 0, 'b', 0), new ProductionOccurrence(3, 2, 'empty', 0),
35        ]);
36        $observer = new SequenceObservation();
37        self::assertSame([0, 1, 2, 3], $observer->preserved($input));
38        self::assertSame([2, 3], $observer->preserved($input->replace(0, 1, [$a->replaced('OTHER', 'source')], 'source')));
39        self::assertSame([2, 3], $observer->preserved($input->replace(0, 1, [], 'source')));
40    }
41
42    public function testPreservedDistinguishesEmptyGrammarFromInsertedOutput(): void
43    {
44        $input = new TerminalSequence([], [], [], [new ProductionOccurrence(0, null, 'root', 0), new ProductionOccurrence(1, 0, 'empty', 0)]);
45        $observer = new SequenceObservation();
46        self::assertSame([0, 1], $observer->preserved($input));
47        self::assertSame([], $observer->preserved($input->replace(0, 0, [$input->insertedFor('X', 1, 'source')], 'source')));
48    }
49}
50