packages/sql-faker/tests/Unit/Compiler/Bison/Lexer/BisonScannerTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Compiler\Bison\Lexer;
6
7use PHPUnit\Framework\Attributes\CoversNothing;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Compiler\Bison\Lexer\ActionScanner;
11use SqlFaker\Compiler\Bison\Lexer\BisonScanner;
12use SqlFaker\Compiler\Bison\Lexer\DirectiveScanner;
13use SqlFaker\Compiler\Bison\Lexer\IdentifierScanner;
14use SqlFaker\Compiler\Bison\Lexer\NumberScanner;
15use SqlFaker\Compiler\Bison\Lexer\PunctuationScanner;
16use SqlFaker\Compiler\Bison\Lexer\QuotedLiteralScanner;
17use SqlFaker\Compiler\Bison\Lexer\SourceCursor;
18use SqlFaker\Compiler\Bison\Lexer\TypeTagScanner;
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 BisonScannerTest extends TestCase
24{
25    #[DataProvider('providerScanner')]
26    public function testScanConsumesTheLexemeTheScannerClaims(BisonScanner $scanner, string $source): void
27    {
28        $cursor = new SourceCursor($source);
29
30        self::assertTrue($scanner->handles($cursor->current()));
31
32        $scanner->scan($cursor);
33
34        self::assertTrue($cursor->atEnd(), 'the scanner left input behind');
35    }
36
37    #[DataProvider('providerScanner')]
38    public function testHandlesRejectsWhatNoScannerReads(BisonScanner $scanner, string $source): void
39    {
40        unset($source);
41
42        self::assertFalse($scanner->handles('@'));
43    }
44
45    /**
46     * @return iterable<string, array{BisonScanner, string}>
47     */
48    public static function providerScanner(): iterable
49    {
50        yield 'directive' => [new DirectiveScanner(), '%token'];
51        yield 'action' => [new ActionScanner(), '{ x; }'];
52        yield 'type tag' => [new TypeTagScanner(), '<num>'];
53        yield 'quoted literal' => [new QuotedLiteralScanner(), '"alias"'];
54        yield 'number' => [new NumberScanner(), '42'];
55        yield 'identifier' => [new IdentifierScanner(), 'expr'];
56        yield 'punctuation' => [new PunctuationScanner(), ':'];
57    }
58}
59