packages/sql-faker/tests/Unit/Generation/Candidate/VersionedLexemeGeneratorTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Generation\Candidate;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use RuntimeException;
11use SqlFaker\Generation\Candidate\FixedLexemeGenerator;
12use SqlFaker\Generation\Candidate\VersionCase;
13use SqlFaker\Generation\Candidate\VersionedLexemeGenerator;
14use SqlFaker\Generation\Lexeme\LexemeGenerator;
15use SqlFaker\Generation\Lexeme\LexemeInput;
16use SqlFaker\Generation\Lexeme\ResolvedOutput;
17use SqlFaker\Generation\Token\TerminalSequence;
18
19#[CoversClass(VersionedLexemeGenerator::class)]
20#[UsesClass(FixedLexemeGenerator::class)]
21#[UsesClass(\SqlFaker\Generation\Lexeme\Lexeme::class)]
22#[UsesClass(\SqlFaker\Generation\Lexeme\LexemeCandidates::class)]
23#[UsesClass(LexemeInput::class)]
24#[UsesClass(\SqlFaker\Generation\Lexeme\LexemeSequence::class)]
25#[UsesClass(ResolvedOutput::class)]
26#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
27#[UsesClass(TerminalSequence::class)]
28#[UsesClass(VersionCase::class)]
29#[UsesClass(\SqlFaker\Generation\Lexeme\SpacingConstraint::class)]
30#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
31final class VersionedLexemeGeneratorTest extends TestCase
32{
33    public function testGenerateFromAnUnselectedCaseNeverGeneratesAndSharedDefinitionsRemainReusable(): void
34    {
35        $unused = $this->createMock(LexemeGenerator::class);
36        $unused->expects(self::never())->method('generate');
37        $shared = new FixedLexemeGenerator('NOW', 'function', 'shared');
38        $old = new VersionCase(['demo-1', 'demo-2'], $shared, 'shared-case');
39        $new = new VersionCase(['demo-3'], $unused, 'new-case');
40        $input = new LexemeInput(TerminalSequence::fromNames(['NOW_SYM']), 0, new ResolvedOutput());
41        $first = new VersionedLexemeGenerator('demo-1', $old, $new);
42        $second = new VersionedLexemeGenerator('demo-2', $old, $new);
43        self::assertSame($old, $first->selected);
44        self::assertSame($old, $second->selected);
45        self::assertSame($old, (new VersionedLexemeGenerator('demo-1', $new, $old))->selected);
46        $firstResult = $first->generate($input);
47        $secondResult = $second->generate($input);
48        self::assertNotNull($firstResult);
49        self::assertNotNull($secondResult);
50        self::assertSame('NOW', [...$firstResult->sequences()][0]->lexemes[0]->text);
51        self::assertSame(['shared:NOW', 'version-case:shared-case'], [...[...$firstResult->sequences()][0]->sources()]);
52        self::assertSame('NOW', [...$secondResult->sequences()][0]->lexemes[0]->text);
53        self::assertNull((new VersionedLexemeGenerator('unknown', $old, $new))->generate($input));
54    }
55
56    public function testOverlappingCasesAreAnErrorEvenWhenTheyShareAnImplementation(): void
57    {
58        $fixed = new FixedLexemeGenerator('NOW', 'function', 'shared');
59        $this->expectException(RuntimeException::class);
60        $this->expectExceptionMessage('Overlapping version cases for demo: first, second');
61        new VersionedLexemeGenerator('demo', new VersionCase(['demo'], $fixed, 'first'), new VersionCase(['demo'], $fixed, 'second'));
62    }
63}
64