packages/sql-faker/tests/Unit/MySql/Generation/Lexeme/PrecisionLexemeGeneratorTest.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\PrecisionLexemeGenerator;
18
19#[CoversClass(PrecisionLexemeGenerator::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\IntegerLexemeGenerator::class)]
30#[UsesClass(\SqlFaker\Generation\Value\IntegerDomain::class)]
31final class PrecisionLexemeGeneratorTest extends TestCase
32{
33 #[DataProvider('providerWidths')]
34 public function testGenerateEnforcesPrecisionAndScaleTogether(string $name, int $scale, string $requested, bool $valid): void
35 {
36 $origin = new TerminalOccurrence($name, 10, [1], ['precision']);
37 $scaleOrigin = new TerminalOccurrence('NUMERIC_SCALE_NUMBER', 11, [1], ['precision']);
38 $right = new ResolvedOutput([new OutputPart(new Lexeme((string) $scale, 'number', $scaleOrigin, 'source'), '', 'candidate')]);
39 $input = new LexemeInput(new TerminalSequence([$origin]), 0, $right, $requested);
40 $result = (new PrecisionLexemeGenerator())->generate($input);
41 self::assertNotNull($result);
42 $candidates = [...$result->sequences()];
43 self::assertSame($valid ? [$requested] : [], array_map(static fn ($candidate): string => $candidate->lexemes[0]->text, $candidates));
44 self::assertSame($valid ? [$origin] : [], array_map(static fn ($candidate) => $candidate->lexemes[0]->origin, $candidates));
45 }
46
47 /**
48 * @return list<array{string, int, string, bool}>
49 */
50 public static function providerWidths(): array
51 {
52 return [['DECIMAL_DIGITS_NUMBER', 0, '0', true], ['DECIMAL_DIGITS_NUMBER', 1, '0', false], ['DECIMAL_DIGITS_NUMBER', 2, '1', false], ['DECIMAL_DIGITS_NUMBER', 30, '030', true], ['DECIMAL_DIGITS_NUMBER', 30, '65', true], ['DECIMAL_DIGITS_NUMBER', 30, '66', false], ['FLOAT_DIGITS_NUMBER', 0, '0', true], ['FLOAT_DIGITS_NUMBER', 2, '1', false], ['FLOAT_DIGITS_NUMBER', 30, '255', true], ['FLOAT_DIGITS_NUMBER', 0, '256', false], ['FLOAT_DIGITS_NUMBER', 0, '1.0', false]];
53 }
54
55 public function testGenerateUsesOnlyTheScaleInTheSameOccurrence(): void
56 {
57 $origin = new TerminalOccurrence('DECIMAL_DIGITS_NUMBER', 10, [1], ['precision']);
58 $foreign = new TerminalOccurrence('NUMERIC_SCALE_NUMBER', 11, [2], ['precision']);
59 $scale = new TerminalOccurrence('NUMERIC_SCALE_NUMBER', 12, [1], ['precision']);
60 $right = new ResolvedOutput([new OutputPart(new Lexeme('30', 'number', $foreign, 'source'), '', 'a'), new OutputPart(new Lexeme('2', 'number', $scale, 'source'), '', 'b')]);
61 $result = (new PrecisionLexemeGenerator())->generate(new LexemeInput(new TerminalSequence([$origin]), 0, $right));
62 self::assertNotNull($result);
63 self::assertSame(['2', '65'], array_map(static fn ($candidate): string => $candidate->lexemes[0]->text, [...$result->sequences()]));
64 $missing = (new PrecisionLexemeGenerator())->generate(new LexemeInput(new TerminalSequence([$origin]), 0, new ResolvedOutput()));
65 self::assertNotNull($missing);
66 self::assertSame([], [...$missing->sequences()]);
67 self::assertNull((new PrecisionLexemeGenerator())->generate(new LexemeInput(TerminalSequence::fromNames(['NUM']), 0, $right)));
68 }
69}
70