packages/sql-faker/tests/Unit/Compiler/Bison/Directive/BisonDirectiveReaderTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Compiler\Bison\Directive;
6
7use PHPUnit\Framework\Attributes\CoversNothing;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Compiler\Bison\Directive\BisonDirectiveReader;
11use SqlFaker\Compiler\Bison\Directive\DefineDirectiveReader;
12use SqlFaker\Compiler\Bison\Directive\ExpectDirectiveReader;
13use SqlFaker\Compiler\Bison\Directive\ParamDirectiveReader;
14use SqlFaker\Compiler\Bison\Directive\PrecedenceDirectiveReader;
15use SqlFaker\Compiler\Bison\Directive\StartDirectiveReader;
16use SqlFaker\Compiler\Bison\Directive\TokenDirectiveReader;
17use SqlFaker\Compiler\Bison\Directive\TypeDirectiveReader;
18use SqlFaker\Compiler\Bison\Lexer\BisonTokenStream;
19
20#[CoversNothing]
21#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFaker\Generation\Derivation\CompletionCosts::class)]
22#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFaker\Generation\Derivation\DerivationNode::class)]
23final class BisonDirectiveReaderTest extends TestCase
24{
25    #[DataProvider('providerReader')]
26    public function testHandlesClaimsTheDirectiveTheReaderIsNamedFor(
27        BisonDirectiveReader $reader,
28        string $directive,
29        string $arguments,
30    ): void {
31        unset($arguments);
32
33        self::assertTrue($reader->handles($directive));
34    }
35
36    #[DataProvider('providerReader')]
37    public function testHandlesRejectsADirectiveThatIsNotItsOwn(
38        BisonDirectiveReader $reader,
39        string $directive,
40        string $arguments,
41    ): void {
42        unset($directive, $arguments);
43
44        self::assertFalse($reader->handles('%no-such-directive'));
45    }
46
47    #[DataProvider('providerReader')]
48    public function testReadConsumesTheArgumentsUpToTheNextDeclaration(
49        BisonDirectiveReader $reader,
50        string $directive,
51        string $arguments,
52    ): void {
53        $stream = BisonTokenStream::over($arguments . ' %%');
54
55        $reader->read($stream, $directive);
56
57        self::assertSame('%%', $stream->next()->value);
58    }
59
60    /**
61     * @return iterable<string, array{BisonDirectiveReader, string, string}>
62     */
63    public static function providerReader(): iterable
64    {
65        yield 'start' => [new StartDirectiveReader(), '%start', 'statement'];
66        yield 'token' => [new TokenDirectiveReader(), '%token', 'IDENT'];
67        yield 'type' => [new TypeDirectiveReader(), '%type', '<num> expr'];
68        yield 'precedence' => [new PrecedenceDirectiveReader(), '%left', 'OR_SYM'];
69        yield 'param' => [new ParamDirectiveReader(), '%parse-param', '{ THD *thd }'];
70        yield 'expect' => [new ExpectDirectiveReader(), '%expect', '3'];
71        yield 'define' => [new DefineDirectiveReader(), '%define', 'api.pure'];
72    }
73}
74