packages/sql-faker/tests/Unit/Sqlite/Generation/Lexeme/JoinModifiersTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Sqlite\Generation\Lexeme;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFaker\Generation\Exception\LexicalException;
12use SqlFaker\Sqlite\Generation\Lexeme\JoinModifiers;
13
14#[CoversClass(JoinModifiers::class)]
15#[UsesClass(LexicalException::class)]
16final class JoinModifiersTest extends TestCase
17{
18 public function testMaskRecognizesCaseInsensitiveSourceWordsAndFullJoinFlags(): void
19 {
20 $types = new JoinModifiers();
21 self::assertSame($types->mask('LEFT') | $types->mask('RIGHT'), $types->mask('full'));
22 self::assertSame($types->mask('INNER') | 32, $types->mask('CROSS'));
23 }
24
25 public function testMaskReportsAnUnknownSourceRegistration(): void
26 {
27 $this->expectException(LexicalException::class);
28 $this->expectExceptionMessage('Unknown SQLite join modifier: UNREVIEWED');
29 (new JoinModifiers())->mask('UNREVIEWED');
30 }
31
32 public function testValidRejectsInnerOuterConflictsAndNaturalJoinConditions(): void
33 {
34 $types = new JoinModifiers();
35 self::assertFalse($types->valid($types->mask('LEFT') | $types->mask('INNER'), false));
36 self::assertFalse($types->valid($types->mask('OUTER'), false));
37 self::assertFalse($types->valid($types->mask('NATURAL'), true));
38 self::assertTrue($types->valid($types->mask('FULL') | $types->mask('OUTER'), true));
39 }
40
41 public function testCanCompleteConsidersAllReachablePrefixStates(): void
42 {
43 $types = new JoinModifiers();
44 $words = ['INNER', 'CROSS', 'NATURAL', 'LEFT', 'RIGHT', 'FULL', 'OUTER'];
45 self::assertFalse($types->canComplete($types->mask('OUTER'), 0, false, $words));
46 self::assertTrue($types->canComplete($types->mask('OUTER'), 1, false, $words));
47 self::assertFalse($types->canComplete($types->mask('INNER') | $types->mask('OUTER'), 2, false, $words));
48 self::assertFalse($types->canComplete($types->mask('NATURAL'), 2, true, $words));
49 }
50 #[DataProvider('providerModifierPairs')]
51 public function testValidChecksNaturalOuterAndDirectionalCombinations(string $first, string $second, bool $hasCondition, bool $valid): void
52 {
53 $types = new JoinModifiers();
54 self::assertSame($valid, $types->valid($types->mask($first) | $types->mask($second), $hasCondition));
55 }
56
57 /**
58 * @return iterable<array{string, string, bool, bool}>
59 */
60 public static function providerModifierPairs(): iterable
61 {
62 yield ['NATURAL', 'OUTER', false, false];
63 yield ['NATURAL', 'LEFT', false, true];
64 yield ['NATURAL', 'RIGHT', false, true];
65 yield ['LEFT', 'OUTER', true, true];
66 yield ['RIGHT', 'OUTER', true, true];
67 yield ['LEFT', 'CROSS', false, false];
68 yield ['FULL', 'INNER', false, false];
69 yield ['NATURAL', 'FULL', true, false];
70 yield ['NATURAL', 'INNER', false, true];
71 yield ['NATURAL', 'INNER', true, false];
72 }
73}
74