packages/sql-faker/tests/Unit/MySql/Generation/Lexeme/FactorLexemeGeneratorTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\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\Lexeme\Lexeme;
12use SqlFaker\Generation\Lexeme\LexemeInput;
13use SqlFaker\Generation\Lexeme\OutputPart;
14use SqlFaker\Generation\Lexeme\ResolvedOutput;
15use SqlFaker\Generation\Token\TerminalOccurrence;
16use SqlFaker\Generation\Token\TerminalSequence;
17use SqlFaker\MySql\Generation\Lexeme\FactorLexemeGenerator;
18
19#[CoversClass(FactorLexemeGenerator::class)]
20#[UsesClass(Lexeme::class)]
21#[UsesClass(LexemeInput::class)]
22#[UsesClass(OutputPart::class)]
23#[UsesClass(ResolvedOutput::class)]
24#[UsesClass(TerminalOccurrence::class)]
25#[UsesClass(TerminalSequence::class)]
26#[UsesClass(\SqlFaker\Generation\Lexeme\LexemeCandidates::class)]
27#[UsesClass(\SqlFaker\Generation\Lexeme\LexemeSequence::class)]
28#[UsesClass(\SqlFaker\Generation\Lexeme\SpacingConstraint::class)]
29#[UsesClass(\SqlFaker\Generation\Candidate\ValueLexemeGenerator::class)]
30#[UsesClass(\SqlFaker\Generation\Value\WordDomain::class)]
31final class FactorLexemeGeneratorTest extends TestCase
32{
33    /**
34     * @param list<string> $expected
35     */
36    #[DataProvider('providerFactors')]
37    public function testGenerateKeepsFactorPairsDistinctWithinTheirUser(string $action, bool $prior, ?string $rightValue, bool $sameUser, array $expected): void
38    {
39        $terminals = $prior ? [new TerminalOccurrence('AUTH_FACTOR_NUMBER', 10, [0, 1], ['alter_user', 'factor'])] : [];
40        $terminals[] = new TerminalOccurrence($action, 11, [0], ['alter_user']);
41        $origin = new TerminalOccurrence('AUTH_FACTOR_NUMBER', 12, [0, 2], ['alter_user', 'factor']);
42        $terminals[] = $origin;
43        $rightOrigin = new TerminalOccurrence('AUTH_FACTOR_NUMBER', 13, [$sameUser ? 0 : 9, 3], ['alter_user', 'factor']);
44        $right = new ResolvedOutput($rightValue === null ? [] : [new OutputPart(new Lexeme($rightValue, 'number', $rightOrigin, 'source'), '', 'candidate')]);
45        $input = new LexemeInput(new TerminalSequence($terminals), count($terminals) - 1, $right);
46        $result = (new FactorLexemeGenerator())->generate($input);
47        self::assertNotNull($result);
48        $candidates = [...$result->sequences()];
49        self::assertSame($expected, array_map(static fn ($candidate): string => $candidate->lexemes[0]->text, $candidates));
50        self::assertSame(array_fill(0, count($expected), $origin), array_map(static fn ($candidate) => $candidate->lexemes[0]->origin, $candidates));
51    }
52
53    /**
54     * @return list<array{string, bool, string|null, bool, list<string>}>
55     */
56    public static function providerFactors(): array
57    {
58        return [['DROP', false, null, true, ['2', '3']], ['DROP', false, '2', true, ['3']], ['DROP', false, '3', true, ['2']], ['ADD', true, null, true, ['3']], ['ADD', false, '3', true, ['2']], ['MODIFY_SYM', true, null, true, ['2', '3']], ['DROP', false, '2', false, ['2', '3']]];
59    }
60
61    #[DataProvider('providerSpellings')]
62    public function testGenerateAcceptsOnlyExactFactorSpellings(string $spelling, bool $valid): void
63    {
64        $input = new LexemeInput(TerminalSequence::fromNames(['AUTH_FACTOR_NUMBER']), 0, new ResolvedOutput(), $spelling);
65        $result = (new FactorLexemeGenerator())->generate($input);
66        self::assertNotNull($result);
67        self::assertSame($valid ? [$spelling] : [], array_map(static fn ($candidate): string => $candidate->lexemes[0]->text, [...$result->sequences()]));
68    }
69
70    /**
71     * @return list<array{string, bool}>
72     */
73    public static function providerSpellings(): array
74    {
75        return [['2', true], ['3', true], ['0', false], ['1', false], ['02', false], ['4', false]];
76    }
77
78    public function testGenerateLeavesOrdinaryNumbersToTheirGenerator(): void
79    {
80        self::assertNull((new FactorLexemeGenerator())->generate(new LexemeInput(TerminalSequence::fromNames(['NUM']), 0, new ResolvedOutput())));
81    }
82}
83