packages/sql-faker/tests/Unit/Generation/Value/CharacterDomainTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Generation\Value;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Value\CharacterDomain;
11use SqlFaker\Generation\Value\ChoiceDomain;
12use SqlFaker\Generation\Value\IntegerDomain;
13use SqlFaker\Generation\Value\SequenceDomain;
14use SqlFaker\Generation\Value\ValueChoices;
15use SqlFaker\Generation\Value\ValueDomain;
16
17#[CoversClass(CharacterDomain::class)]
18#[UsesClass(IntegerDomain::class)]
19#[UsesClass(SequenceDomain::class)]
20#[UsesClass(ChoiceDomain::class)]
21#[UsesClass(ValueChoices::class)]
22#[UsesClass(ValueDomain::class)]
23final class CharacterDomainTest extends TestCase
24{
25    public function testChoosePreservesEncodedAtomsAndEvenDigitLengths(): void
26    {
27        $domain = new CharacterDomain(['0', 'f'], 0, 2, "X'", "'", 2);
28        self::assertSame("X''", $domain->choose(static fn (int $count): int => 0));
29        self::assertSame("X'ffff'", $domain->choose(static fn (int $count): int => $count - 1));
30        self::assertSame("'a''b'", (new CharacterDomain(["a''b"], 1, 1, "'", "'"))->choose(static fn (int $count): int => 0));
31    }
32
33    public function testMatchKeepsAtomsDelimitersAndMultiplesTogether(): void
34    {
35        $domain = new CharacterDomain(['a', 'bb'], 0, 1, "'", "'", 2);
36        self::assertSame([2], $domain->match("''"));
37        self::assertSame([6], $domain->match("!'abb'!", 1));
38        self::assertSame([], $domain->match("'a'"));
39        self::assertSame([], $domain->match("'ab'"));
40        self::assertSame([], $domain->match('abb'));
41        self::assertSame([6], $domain->match("'aaaa'"));
42    }
43
44    public function testChooseSpansTheDefaultLengthsFromEmptyToTheScannerMaximum(): void
45    {
46        $domain = new CharacterDomain(['a']);
47        self::assertSame('', $domain->choose(static fn (int $count): int => 0));
48        self::assertSame(str_repeat('a', 255), $domain->choose(static fn (int $count): int => $count - 1));
49    }
50
51    public function testChooseStaysInsideDeclaredLengthBounds(): void
52    {
53        $domain = new CharacterDomain(['a'], 2, 4);
54        self::assertSame('aa', $domain->choose(static fn (int $count): int => 0));
55        self::assertSame('aaaa', $domain->choose(static fn (int $count): int => $count - 1));
56    }
57
58    public function testChooseAcceptsTheLargestScannerLength(): void
59    {
60        self::assertSame('', (new CharacterDomain(['a'], 0, 65535))->choose(static fn (int $count): int => 0));
61    }
62
63    public function testMatchRequiresTheDeclaredPrefix(): void
64    {
65        self::assertSame([], (new CharacterDomain(['a'], 0, 2, "X'", "'"))->match("'a'"));
66    }
67
68    public function testMatchCountsMultiplesFromTheMinimumLength(): void
69    {
70        self::assertSame([4, 6], (new CharacterDomain(['a'], 2, 3, multiple: 2))->match('aaaaaa'));
71    }
72
73    public function testMatchReportsEachEndOnceWhenAtomsOverlap(): void
74    {
75        self::assertSame([0, 1, 2, 3], (new CharacterDomain(['a', 'aa']))->match('aaa'));
76    }
77}
78