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