packages/sql-faker/tests/Unit/MySql/Generation/Rewrite/Replication/StartRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Rewrite\Replication;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFaker\Generation\Derivation\DerivationTrace;
12use SqlFaker\Grammar\Model\NonTerminal;
13use SqlFaker\Grammar\Model\Production;
14use SqlFaker\Grammar\Model\Terminal;
15use SqlFaker\MySql\Generation\Rewrite\Replication\StartRule;
16
17#[CoversClass(StartRule::class)]
18#[UsesClass(DerivationTrace::class)]
19#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
20#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
21#[UsesClass(\SqlFaker\Generation\Token\TerminalSequence::class)]
22#[UsesClass(NonTerminal::class)]
23#[UsesClass(Production::class)]
24#[UsesClass(Terminal::class)]
25final class StartRuleTest extends TestCase
26{
27 /**
28 * @param list<string> $threads
29 * @param list<string> $authentication
30 */
31 #[DataProvider('providerStarts')]
32 public function testRewriteEnablesTheIoThreadOnlyWhenAuthenticationRequiresIt(string $scope, string $verb, array $threads, array $authentication, bool $added): void
33 {
34 $option = $scope === 'slave' ? 'opt_slave_thread_option_list' : 'opt_replica_thread_option_list';
35 $trace = new DerivationTrace($scope);
36 $trace->expand(0, new Production([new Terminal($verb), new Terminal('REPLICA_SYM'), new NonTerminal($option), new NonTerminal('authentication')]), 0);
37 $trace->expand(2, new Production(array_map(static fn (string $name): Terminal => new Terminal($name), $threads)), 0);
38 $trace->expand(2 + count($threads), new Production(array_map(static fn (string $name): Terminal => new Terminal($name), $authentication)), 0);
39 $input = $trace->terminals();
40 $rule = new StartRule();
41 $result = $rule->rewrite($input);
42 self::assertSame([$verb, 'REPLICA_SYM', ...$threads, ...($added ? [',', 'RELAY_THREAD'] : []), ...$authentication], $result->names());
43 self::assertSame($input->original, $result->original);
44 self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
45 self::assertSame($result, $rule->rewrite($result));
46 $ids = array_map(static fn ($terminal): int => $terminal->id, $result->terminals);
47 self::assertCount(count($ids), array_unique($ids));
48 }
49
50 /**
51 * @return iterable<array{string, string, list<string>, list<string>, bool}>
52 */
53 public static function providerStarts(): iterable
54 {
55 foreach (['start_replica_stmt', 'slave'] as $scope) {
56 foreach (['USER', 'PASSWORD', 'DEFAULT_AUTH_SYM', 'PLUGIN_DIR_SYM'] as $auth) {
57 yield [$scope, 'START_SYM', ['SQL_THREAD'], [$auth, 'EQ', 'TEXT_STRING'], true];
58 }
59 yield [$scope, 'START_SYM', ['SQL_THREAD'], [], false];
60 yield [$scope, 'START_SYM', ['SQL_THREAD', ',', 'RELAY_THREAD'], ['USER'], false];
61 yield [$scope, 'START_SYM', ['RELAY_THREAD'], ['USER'], false];
62 yield [$scope, 'START_SYM', [], ['USER'], false];
63 yield [$scope, 'STOP_SYM', ['SQL_THREAD'], ['USER'], false];
64 }
65 yield ['ordinary', 'START_SYM', ['SQL_THREAD'], ['USER'], false];
66 }
67}
68