packages/sql-faker/tests/Unit/MySql/Generation/StartRuleResolverTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Grammar\Model\Grammar;
11use SqlFaker\Grammar\Model\NonTerminal;
12use SqlFaker\Grammar\Model\Production;
13use SqlFaker\Grammar\Model\ProductionRule;
14use SqlFaker\Grammar\Model\Terminal;
15use SqlFaker\Grammar\Resource\SqlVersion;
16use SqlFaker\Grammar\Resource\SqlVersionRegistry;
17use SqlFaker\MySql\Generation\StartRuleResolver;
18use SqlFaker\MySql\Grammar\MySqlGrammar;
19
20#[CoversClass(StartRuleResolver::class)]
21#[UsesClass(Grammar::class)]
22#[CoversClass(ProductionRule::class)]
23#[CoversClass(Production::class)]
24#[CoversClass(Terminal::class)]
25#[CoversClass(NonTerminal::class)]
26#[UsesClass(SqlVersion::class)]
27#[UsesClass(SqlVersionRegistry::class)]
28#[UsesClass(MySqlGrammar::class)]
29final class StartRuleResolverTest extends TestCase
30{
31    public function testStartSymbolForTakesARuleThisReleaseDeclaresAsItStands(): void
32    {
33        $grammar = MySqlGrammar::load('mysql-8.4.7');
34
35        self::assertSame('select_stmt', (new StartRuleResolver($grammar))->startSymbolFor('select_stmt'));
36    }
37
38    public function testStartSymbolForFallsBackToTheEntryPointOfTheReleaseItWasAskedOf(): void
39    {
40        $grammar = new Grammar('start', ['start' => new ProductionRule('start', [new Production([new Terminal('A')])])]);
41
42        self::assertSame('start', (new StartRuleResolver($grammar))->startSymbolFor(null));
43    }
44
45    public function testStartSymbolForHandsBackARequestNothingMatches(): void
46    {
47        $grammar = new Grammar('start', ['start' => new ProductionRule('start', [new Production([new Terminal('A')])])]);
48
49        self::assertSame('no_such_rule', (new StartRuleResolver($grammar))->startSymbolFor('no_such_rule'));
50    }
51    public function testStartSymbolForMapsModernRequestsToLegacyGrammarRules(): void
52    {
53        $grammar = MySqlGrammar::load('mysql-5.6.51');
54        $resolver = new StartRuleResolver($grammar);
55
56        self::assertSame('select', $resolver->startSymbolFor('select_stmt'));
57        self::assertSame('insert', $resolver->startSymbolFor('insert_stmt'));
58        self::assertSame('update', $resolver->startSymbolFor('update_stmt'));
59        self::assertSame('delete', $resolver->startSymbolFor('delete_stmt'));
60        self::assertSame($grammar->startSymbol, $resolver->startSymbolFor('simple_statement_or_begin'));
61    }
62    /**
63     * @return list<array{string}>
64     */
65    public static function providerEntryVersions(): array
66    {
67        return [['mysql-5.6.51'], ['mysql-8.4.7']];
68    }
69
70    #[\PHPUnit\Framework\Attributes\DataProvider('providerEntryVersions')]
71    public function testStartSymbolForPreservesGrammarEntryEvenWhenStatementRulesExist(string $version): void
72    {
73        $grammar = MySqlGrammar::load($version);
74        self::assertSame($grammar->startSymbol, (new StartRuleResolver($grammar))->startSymbolFor(null));
75    }
76}
77