packages/sql-faker/tests/Unit/MySql/Generation/Spacing/CloneAddressSpacingRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Spacing;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFaker\Generation\Lexeme\Lexeme;
12use SqlFaker\Generation\Lexeme\LexemeBoundary;
13use SqlFaker\Generation\Lexeme\LexemeInput;
14use SqlFaker\Generation\Lexeme\ResolvedOutput;
15use SqlFaker\Generation\Lexeme\SpacingConstraint;
16use SqlFaker\Generation\Lexeme\SpacingRule;
17use SqlFaker\Generation\Token\TerminalOccurrence;
18use SqlFaker\Generation\Token\TerminalSequence;
19use SqlFaker\MySql\Generation\Spacing\CloneAddressSpacingRule;
20
21#[CoversClass(CloneAddressSpacingRule::class)]
22#[UsesClass(Lexeme::class)]
23#[UsesClass(LexemeBoundary::class)]
24#[UsesClass(LexemeInput::class)]
25#[UsesClass(ResolvedOutput::class)]
26#[UsesClass(SpacingConstraint::class)]
27#[UsesClass(SpacingRule::class)]
28#[UsesClass(TerminalOccurrence::class)]
29#[UsesClass(TerminalSequence::class)]
30#[UsesClass(\SqlFaker\Generation\Lexeme\LexemeSequence::class)]
31#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
32final class CloneAddressSpacingRuleTest extends TestCase
33{
34 public function testApplyConstrainsOnlyItsSourceDefinedBoundary(): void
35 {
36 $origin = new TerminalOccurrence('TOKEN', 1, [0], ['clone_stmt']);
37 $input = new LexemeInput(new TerminalSequence([$origin]), 0, new ResolvedOutput());
38 $left = new Lexeme('host', 'identifier', $origin, 'source');
39 $right = new Lexeme(':', 'symbol', $origin, 'source');
40 $rule = new CloneAddressSpacingRule();
41 self::assertSame(SpacingConstraint::JOIN, $rule->apply(new LexemeBoundary($left, $right), $input)?->allowed);
42 $plain = new Lexeme('word', 'keyword', new TerminalOccurrence('OTHER', 2), 'other');
43 self::assertNull($rule->apply(new LexemeBoundary($plain, $plain), $input));
44 }
45
46 #[DataProvider('providerColonSides')]
47 public function testApplyRecognizesAFlatStatementAndBothSidesOfTheAddressColon(bool $left): void
48 {
49 $sequence = TerminalSequence::fromNames(['CLONE_SYM', 'INSTANCE_SYM', 'FROM', 'HOST', ':', 'PORT']);
50 $input = new LexemeInput($sequence, 3, new ResolvedOutput());
51 $host = new Lexeme('host', 'string', $sequence->terminals[3], 'host');
52 $colon = new Lexeme(':', 'symbol', $sequence->terminals[4], 'colon');
53 $port = new Lexeme('3306', 'number', $sequence->terminals[5], 'port');
54 $rule = new CloneAddressSpacingRule();
55 $boundary = $left ? new LexemeBoundary($colon, $port) : new LexemeBoundary($host, $colon);
56 $constraint = $rule->apply($boundary, $input);
57 self::assertNotNull($constraint);
58 self::assertSame(SpacingConstraint::JOIN, $constraint->allowed);
59 self::assertSame(['mysql.clone-address'], $constraint->rules);
60 self::assertNull($rule->apply($boundary, new LexemeInput(TerminalSequence::fromNames(['OTHER']), 0, new ResolvedOutput())));
61 }
62 /**
63 * @return iterable<array{bool}>
64 */
65 public static function providerColonSides(): iterable
66 {
67 yield [false];
68 yield [true];
69 }
70}
71