packages/sql-faker/tests/Unit/MySql/Generation/Value/QuotedDomainTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Value;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use SqlFaker\MySql\Generation\Value\QuotedDomain;
10
11#[CoversClass(QuotedDomain::class)]
12final class QuotedDomainTest extends TestCase
13{
14 public function testChooseEscapesDelimitersBackslashesAndUnicodeEscapeMarkersDuringConstruction(): void
15 {
16 self::assertSame("''''", (new QuotedDomain("'", minimum: 1, maximum: 1, alphabet: ["'"]))->choose(static fn (int $count): int => 0));
17 self::assertSame("E'\\\\'", (new QuotedDomain("'", ['E'], true, 1, 1, ['\\']))->choose(static fn (int $count): int => 0));
18 self::assertSame("U&'\\\\'", (new QuotedDomain("'", ['U&'], alphabet: ['\\'], minimum: 1, maximum: 1, unicodeEscapes: true))->choose(static fn (int $count): int => 0));
19 self::assertSame('`a`', (new QuotedDomain('`', minimum: 1, maximum: 1, alphabet: ['a', ' '], trailingSpace: false))->choose(static fn (int $count): int => $count - 1));
20 }
21
22 public function testMatchStopsAtTheFirstUnescapedClosingDelimiter(): void
23 {
24 $domain = new QuotedDomain("'", backslash: true);
25 self::assertSame([7], $domain->match("!'a''b' trailing", 1));
26 self::assertSame([6], $domain->match("'a\\'b'"));
27 self::assertSame([], $domain->match("'unclosed"));
28 self::assertSame([], $domain->match("'a\0b'"));
29 self::assertSame([], $domain->match("'a\\"));
30 self::assertSame([], $domain->match("'a\\\0'"));
31 self::assertSame([], (new QuotedDomain('"', minimum: 1))->match('""'));
32 self::assertSame([3], (new QuotedDomain('[', closing: ']'))->match('[a]b]'));
33 self::assertSame([], (new QuotedDomain("'", ['N']))->match("'text'"));
34 }
35
36 public function testEncodeReturnsCompleteEscapedAtoms(): void
37 {
38 $domain = new QuotedDomain("'", backslash: true);
39 self::assertSame("''", $domain->encode("'"));
40 self::assertSame('\\\\', $domain->encode('\\'));
41 self::assertSame('猫', $domain->encode('猫'));
42 }
43
44 public function testEndReadsTheContentAfterAnOpeningDelimiter(): void
45 {
46 self::assertSame(5, (new QuotedDomain("'"))->end("text'", 1));
47 self::assertNull((new QuotedDomain("'"))->end('unclosed', 0));
48 }
49
50 public function testChooseSpansTheDefaultBodyLengthsFromEmptyToTheScannerMaximum(): void
51 {
52 $domain = new QuotedDomain("'");
53 self::assertSame("''", $domain->choose(static fn (int $count): int => 0));
54 self::assertSame("'" . str_repeat('a', 255) . "'", $domain->choose(static fn (int $count): int => $count === 10 ? 0 : $count - 1));
55 }
56
57 public function testChooseKeepsATrailingSpaceUnlessTheScannerTrimsIt(): void
58 {
59 self::assertSame("' '", (new QuotedDomain("'", minimum: 1, maximum: 1))->choose(static fn (int $count): int => $count === 10 ? 3 : 0));
60 self::assertSame("''''", (new QuotedDomain("'", minimum: 1, maximum: 1, trailingSpace: false))->choose(static fn (int $count): int => $count === 9 ? 3 : 0));
61 }
62
63 public function testChooseClosesWithTheDistinctClosingDelimiterWhenOneIsDeclared(): void
64 {
65 self::assertSame('[a]', (new QuotedDomain('[', minimum: 1, maximum: 1, closing: ']'))->choose(static fn (int $count): int => 0));
66 }
67
68 public function testEncodeLeavesBackslashesAloneUnlessTheScannerReadsEscapes(): void
69 {
70 self::assertSame('\\', (new QuotedDomain("'"))->encode('\\'));
71 self::assertSame('\\\\', (new QuotedDomain("'", unicodeEscapes: true))->encode('\\'));
72 }
73
74 public function testMatchReadsEveryDeclaredPrefixInTurn(): void
75 {
76 $domain = new QuotedDomain("'", ['N', '']);
77 self::assertSame([7], $domain->match("N'text'"));
78 self::assertSame([6], $domain->match("'text'"));
79 self::assertSame([], $domain->match("n'text'"));
80 }
81
82 public function testEndRequiresTheMinimumBodyLength(): void
83 {
84 $domain = new QuotedDomain("'", minimum: 1);
85 self::assertSame(3, $domain->end("'a'", 1));
86 self::assertNull($domain->end("''", 1));
87 }
88}
89