packages/sql-faker/tests/Unit/Compiler/Bison/Directive/DefineDirectiveReaderTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Compiler\Bison\Directive;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Compiler\Bison\Ast\BisonDefineDeclaration;
11use SqlFaker\Compiler\Bison\Directive\BisonDeclarationBoundary;
12use SqlFaker\Compiler\Bison\Directive\DefineDirectiveReader;
13use SqlFaker\Compiler\Bison\Lexer\ActionScanner;
14use SqlFaker\Compiler\Bison\Lexer\BisonLexeme;
15use SqlFaker\Compiler\Bison\Lexer\BisonLexer;
16use SqlFaker\Compiler\Bison\Lexer\BisonScannerChain;
17use SqlFaker\Compiler\Bison\Lexer\BisonToken;
18use SqlFaker\Compiler\Bison\Lexer\BisonTokenStream;
19use SqlFaker\Compiler\Bison\Lexer\BisonTrivia;
20use SqlFaker\Compiler\Bison\Lexer\DirectiveScanner;
21use SqlFaker\Compiler\Bison\Lexer\IdentifierScanner;
22use SqlFaker\Compiler\Bison\Lexer\NumberScanner;
23use SqlFaker\Compiler\Bison\Lexer\QuotedLiteralScanner;
24use SqlFaker\Compiler\Bison\Lexer\SourceCursor;
25use SqlFaker\Compiler\Bison\Lexer\TypeTagScanner;
26
27#[CoversClass(DefineDirectiveReader::class)]
28#[UsesClass(BisonDeclarationBoundary::class)]
29#[UsesClass(BisonLexeme::class)]
30#[UsesClass(BisonLexer::class)]
31#[UsesClass(BisonScannerChain::class)]
32#[UsesClass(BisonToken::class)]
33#[UsesClass(BisonTokenStream::class)]
34#[UsesClass(BisonTrivia::class)]
35#[UsesClass(SourceCursor::class)]
36#[UsesClass(BisonDefineDeclaration::class)]
37#[UsesClass(IdentifierScanner::class)]
38#[UsesClass(NumberScanner::class)]
39#[UsesClass(QuotedLiteralScanner::class)]
40#[UsesClass(ActionScanner::class)]
41#[UsesClass(DirectiveScanner::class)]
42#[UsesClass(TypeTagScanner::class)]
43#[UsesClass(\SqlFaker\Compiler\Bison\Lexer\PunctuationScanner::class)]
44#[UsesClass(\SqlFaker\Compiler\GrammarParseException::class)]
45final class DefineDirectiveReaderTest extends TestCase
46{
47 public function testHandlesClaimsOnlyTheDefineDirective(): void
48 {
49 $reader = new DefineDirectiveReader();
50
51 self::assertTrue($reader->handles('%define'));
52 self::assertFalse($reader->handles('%expect'));
53 }
54
55 public function testReadTakesANameWithoutAValueAsAFlag(): void
56 {
57 $declaration = (new DefineDirectiveReader())->read(BisonTokenStream::over('api.pure'), '%define');
58
59 self::assertInstanceOf(BisonDefineDeclaration::class, $declaration);
60 self::assertSame('api.pure', $declaration->name);
61 self::assertNull($declaration->value);
62 }
63
64 public function testReadTakesAQuotedValue(): void
65 {
66 $declaration = (new DefineDirectiveReader())->read(BisonTokenStream::over('api.prefix "yy"'), '%define');
67
68 self::assertInstanceOf(BisonDefineDeclaration::class, $declaration);
69 self::assertSame('yy', $declaration->value);
70 }
71
72 public function testReadTakesANumericValue(): void
73 {
74 $declaration = (new DefineDirectiveReader())->read(BisonTokenStream::over('lr.keep 3'), '%define');
75
76 self::assertInstanceOf(BisonDefineDeclaration::class, $declaration);
77 self::assertSame('3', $declaration->value);
78 }
79
80 public function testReadStopsBeforeTheNextDirective(): void
81 {
82 $stream = BisonTokenStream::over('api.pure %token');
83
84 $declaration = (new DefineDirectiveReader())->read($stream, '%define');
85
86 self::assertInstanceOf(BisonDefineDeclaration::class, $declaration);
87 self::assertNull($declaration->value);
88 self::assertSame('%token', $stream->next()->value);
89 }
90
91 public function testReadDeclaresNothingWhenNoNameFollows(): void
92 {
93 self::assertNull((new DefineDirectiveReader())->read(BisonTokenStream::over('42'), '%define'));
94 }
95}
96