packages/sql-fixture/tests/Unit/Version/ServerVersionTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Version;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFixture\Version\ReleaseNumber;
12use SqlFixture\Version\Releases;
13use SqlFixture\Version\ServerVersion as Subject;
14use SqlFixture\Version\UnsupportedVersionException;
15
16#[CoversClass(Subject::class)]
17#[UsesClass(Releases::class)]
18#[UsesClass(ReleaseNumber::class)]
19#[UsesClass(UnsupportedVersionException::class)]
20final class ServerVersionTest extends TestCase
21{
22 public function testResolveNamesTheDefaultOfEachDialect(): void
23 {
24 self::assertSame('mysql-8.4.7', Subject::resolve('mysql')->tag);
25 self::assertSame('pg-17.2', Subject::resolve('pgsql')->tag);
26 self::assertSame('sqlite-3.47.2', Subject::resolve('sqlite')->tag);
27 }
28
29 public function testResolveReadsTheNumberOfATag(): void
30 {
31 $release = Subject::resolve('mysql', 'mysql-5.7.44');
32 self::assertSame('mysql', $release->dialect);
33 self::assertSame('mysql-5.7.44', $release->tag);
34 self::assertSame('5.7.44', $release->number);
35 }
36
37 public function testResolveRejectsATagOfAnotherDialect(): void
38 {
39 $this->expectException(UnsupportedVersionException::class);
40 $this->expectExceptionMessage('Unsupported mysql version: pg-17.2');
41 Subject::resolve('mysql', 'pg-17.2');
42 }
43
44 public function testResolveRejectsAnUnknownDialect(): void
45 {
46 $this->expectException(UnsupportedVersionException::class);
47 $this->expectExceptionMessage('No supported versions are registered for the oracle driver');
48 Subject::resolve('oracle');
49 }
50
51 /**
52 * @return iterable<string, array{string, string, string}>
53 */
54 public static function providerServerVersions(): iterable
55 {
56 yield 'same series with a build suffix' => ['mysql', '8.0.36-0ubuntu0.22.04.1', 'mysql-8.0.44'];
57 yield 'same series with a log suffix' => ['mysql', '5.7.44-log', 'mysql-5.7.44'];
58 yield 'exact release' => ['mysql', '9.1.0', 'mysql-9.1.0'];
59 yield 'newer than every release' => ['mysql', '9.4.0', 'mysql-9.1.0'];
60 yield 'older than every release' => ['mysql', '5.5.62', 'mysql-5.6.51'];
61 yield 'postgres with a distribution note' => ['pgsql', '17.2 (Debian 17.2-1.pgdg120+1)', 'pg-17.2'];
62 yield 'postgres of an older series' => ['pgsql', '16.6', 'pg-16.6'];
63 yield 'postgres older than every release' => ['pgsql', '15.8', 'pg-16.6'];
64 yield 'sqlite newer than the release' => ['sqlite', '3.53.3', 'sqlite-3.47.2'];
65 yield 'sqlite older than the release' => ['sqlite', '3.45.1', 'sqlite-3.47.2'];
66 }
67
68 #[DataProvider('providerServerVersions')]
69 public function testFromServerMatchesTheClosestRelease(string $dialect, string $reported, string $expected): void
70 {
71 self::assertSame($expected, Subject::fromServer($dialect, $reported)->tag);
72 }
73
74 public function testFromServerRejectsAStringWithoutANumber(): void
75 {
76 $this->expectException(UnsupportedVersionException::class);
77 $this->expectExceptionMessage('Unsupported mysql version: unknown');
78 Subject::fromServer('mysql', 'unknown');
79 }
80
81 public function testAllListsTheReleasesOldestFirst(): void
82 {
83 $numbers = array_map(static fn (Subject $release): string => $release->number, Subject::all('mysql'));
84 self::assertSame(['5.6.51', '5.7.44', '8.0.44', '8.1.0', '8.2.0', '8.3.0', '8.4.7', '9.0.1', '9.1.0'], $numbers);
85 }
86
87 public function testTagsMatchTheOtherSqlPackages(): void
88 {
89 self::assertSame([
90 'mysql-5.6.51',
91 'mysql-5.7.44',
92 'mysql-8.0.44',
93 'mysql-8.1.0',
94 'mysql-8.2.0',
95 'mysql-8.3.0',
96 'mysql-8.4.7',
97 'mysql-9.0.1',
98 'mysql-9.1.0',
99 ], Subject::tags('mysql'));
100 self::assertSame(['pg-16.6', 'pg-17.2'], Subject::tags('pgsql'));
101 self::assertSame(['sqlite-3.47.2'], Subject::tags('sqlite'));
102 }
103
104 public function testIsDefaultMarksOneReleasePerDialect(): void
105 {
106 $defaults = array_values(array_filter(Subject::all('mysql'), static fn (Subject $release): bool => $release->isDefault()));
107 self::assertCount(1, $defaults);
108 self::assertSame('mysql-8.4.7', $defaults[0]->tag);
109 }
110
111 public function testIdNumbersTheReleaseLikeMysql(): void
112 {
113 self::assertSame(80044, Subject::resolve('mysql', 'mysql-8.0.44')->id());
114 self::assertSame(170200, Subject::resolve('pgsql', 'pg-17.2')->id());
115 }
116
117 public function testSeriesDropsTheLastNumber(): void
118 {
119 self::assertSame('8.0', Subject::resolve('mysql', 'mysql-8.0.44')->series());
120 self::assertSame('17', Subject::resolve('pgsql', 'pg-17.2')->series());
121 }
122
123 public function testIsAtLeastComparesNumbers(): void
124 {
125 $release = Subject::resolve('mysql', 'mysql-5.7.44');
126 self::assertTrue($release->isAtLeast('5.7.8'));
127 self::assertTrue($release->isAtLeast('5.7.44'));
128 self::assertFalse($release->isAtLeast('8.0'));
129 }
130}
131