packages/sql-faker/tests/Unit/PostgreSql/Generation/Lookahead/PgLookaheadTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Lookahead;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\PostgreSql\Generation\Lookahead\PgLookahead;
11
12#[CoversClass(PgLookahead::class)]
13#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFaker\Generation\Derivation\CompletionCosts::class)]
14#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFaker\Generation\Derivation\DerivationNode::class)]
15final class PgLookaheadTest extends TestCase
16{
17 #[DataProvider('providerLookahead')]
18 public function testAppliedSubstitutesWhenTheFollowerCallsForIt(PgLookahead $lookahead): void
19 {
20 self::assertSame(['NOT_LA', 'NULL_P'], $lookahead->applied(['NOT', 'NULL_P']));
21 }
22
23 #[DataProvider('providerLookahead')]
24 public function testAppliedLeavesTheTokenAloneForAnotherFollower(PgLookahead $lookahead): void
25 {
26 self::assertSame(['NOT', 'IDENT'], $lookahead->applied(['NOT', 'IDENT']));
27 }
28
29 #[DataProvider('providerLookahead')]
30 public function testAppliedLeavesTheLastTokenAloneBecauseNothingFollowsIt(PgLookahead $lookahead): void
31 {
32 self::assertSame(['NOT'], $lookahead->applied(['NOT']));
33 }
34
35 #[DataProvider('providerLookahead')]
36 public function testAppliedLeavesATokenThatTriggersNothing(PgLookahead $lookahead): void
37 {
38 self::assertSame(['SELECT', 'IDENT'], $lookahead->applied(['SELECT', 'IDENT']));
39 }
40
41 #[DataProvider('providerLookahead')]
42 public function testNormalizedSettlesTheBaseTokenOnItsSubstitute(PgLookahead $lookahead): void
43 {
44 self::assertSame(['NOT_LA', 'NULL_P'], $lookahead->normalized(['NOT', 'NULL_P']));
45 }
46
47 #[DataProvider('providerLookahead')]
48 public function testNormalizedWalksASubstitutionBackWhenTheFollowerDoesNotCallForIt(
49 PgLookahead $lookahead,
50 ): void {
51 self::assertSame(['NOT', 'IDENT'], $lookahead->normalized(['NOT_LA', 'IDENT']));
52 }
53
54 #[DataProvider('providerLookahead')]
55 public function testNormalizedLeavesATerminalThatTriggersNothing(PgLookahead $lookahead): void
56 {
57 self::assertSame(['SELECT', 'IDENT'], $lookahead->normalized(['SELECT', 'IDENT']));
58 }
59
60 #[DataProvider('providerLookahead')]
61 public function testBaseOfReportsTheTokenASubstituteIsSpelledAs(PgLookahead $lookahead): void
62 {
63 self::assertSame('NOT', $lookahead->baseOf('NOT_LA'));
64 }
65
66 #[DataProvider('providerLookahead')]
67 public function testBaseOfReportsNothingForATokenThatSubstitutesForNone(PgLookahead $lookahead): void
68 {
69 self::assertNull($lookahead->baseOf('SELECT'));
70 }
71
72 public function testAppliedFindsNothingToDoWithoutRules(): void
73 {
74 self::assertSame(['NOT', 'NULL_P'], (new PgLookahead([]))->applied(['NOT', 'NULL_P']));
75 }
76
77 /**
78 * @return iterable<string, array{PgLookahead}>
79 */
80 public static function providerLookahead(): iterable
81 {
82 yield 'NOT before NULL' => [new PgLookahead([
83 'NOT' => ['token' => 'NOT_LA', 'followed_by' => ['NULL_P', 'IN_P']],
84 ])];
85 }
86
87 public function testDefinitionsKeepsTheParserLookaheadFollowersExplicit(): void
88 {
89 $definitions = PgLookahead::definitions();
90 self::assertSame('WITH_LA', $definitions['WITH']['token']);
91 self::assertSame(['TIME', 'ORDINALITY'], $definitions['WITH']['followed_by']);
92 }
93
94}
95