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