packages/sql-fixture/tests/Integration/MySql/MySqlReleaseRoundTripTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Integration\MySql;
6
7use Container\Endpoint;
8use Container\MySql56Container;
9use Container\MySql57Container;
10use Container\MySql80Container;
11use Container\MySql81Container;
12use Container\MySql82Container;
13use Container\MySql83Container;
14use Container\MySql84Container;
15use Container\MySql90Container;
16use Container\MySql91Container;
17use Container\MySqlContainer;
18use Faker\Factory;
19use PDO;
20use PHPUnit\Framework\Attributes\CoversNothing;
21use PHPUnit\Framework\Attributes\DataProvider;
22use PHPUnit\Framework\Attributes\Large;
23use PHPUnit\Framework\TestCase;
24use SqlFixture\Provider\DatabaseFixtureProvider;
25use SqlFixture\Version\ServerVersion;
26use Testcontainers\Testcontainers;
27
28#[CoversNothing]
29#[Large]
30final class MySqlReleaseRoundTripTest extends TestCase
31{
32 /**
33 * @return iterable<string, array{class-string<MySqlContainer>, int}>
34 */
35 public static function providerReleases(): iterable
36 {
37 $selected = getenv('SQL_FIXTURE_MYSQL_VERSION');
38 $containers = [
39 MySql56Container::class,
40 MySql57Container::class,
41 MySql80Container::class,
42 MySql81Container::class,
43 MySql82Container::class,
44 MySql83Container::class,
45 MySql84Container::class,
46 MySql90Container::class,
47 MySql91Container::class,
48 ];
49 foreach ($containers as $container) {
50 $tag = $container::getGrammarVersion();
51 if ($selected !== false && $selected !== '' && $tag !== 'mysql-' . $selected) {
52 continue;
53 }
54 foreach ([1, 2, 3] as $seed) {
55 yield $tag . ' seed ' . $seed => [$container, $seed];
56 }
57 }
58 }
59
60 /**
61 * @param class-string<MySqlContainer> $container
62 */
63 #[DataProvider('providerReleases')]
64 public function testRowGeneratedFromTheReportedSchemaIsAccepted(string $container, int $seed): void
65 {
66 $endpoint = Testcontainers::run($container)->getData(Endpoint::class);
67 $pdo = new PDO($endpoint->dsn(), $endpoint->username, $endpoint->password, [
68 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
69 PDO::ATTR_EMULATE_PREPARES => false,
70 ]);
71 $faker = Factory::create();
72 $faker->seed($seed);
73 $provider = new DatabaseFixtureProvider($faker, $pdo);
74 self::assertSame($container::getGrammarVersion(), $provider->getVersion());
75
76 $table = 'fixture_' . bin2hex(random_bytes(4));
77 $json = ServerVersion::resolve('mysql', $provider->getVersion())->isAtLeast('5.7.8') ? 'col_json JSON NOT NULL,' : '';
78 $pdo->exec(<<<SQL
79 CREATE TABLE {$table} (
80 id INT PRIMARY KEY AUTO_INCREMENT,
81 col_tinyint TINYINT NOT NULL,
82 col_tinyint_unsigned TINYINT UNSIGNED NOT NULL,
83 col_smallint SMALLINT NOT NULL,
84 col_mediumint MEDIUMINT NOT NULL,
85 col_int INT NOT NULL,
86 col_bigint BIGINT NOT NULL,
87 col_bigint_unsigned BIGINT UNSIGNED NOT NULL,
88 col_float FLOAT NOT NULL,
89 col_double DOUBLE NOT NULL,
90 col_decimal DECIMAL(10, 2) NOT NULL,
91 col_bit BIT(8) NOT NULL,
92 col_bool BOOLEAN NOT NULL,
93 col_char CHAR(10) NOT NULL,
94 col_varchar VARCHAR(255) NOT NULL,
95 col_binary BINARY(8) NOT NULL,
96 col_varbinary VARBINARY(32) NOT NULL,
97 col_tinytext TINYTEXT NOT NULL,
98 col_text TEXT NOT NULL,
99 col_mediumtext MEDIUMTEXT NOT NULL,
100 col_longtext LONGTEXT NOT NULL,
101 col_tinyblob TINYBLOB NOT NULL,
102 col_blob BLOB NOT NULL,
103 col_enum ENUM('a', 'b', 'c') NOT NULL,
104 col_set SET('x', 'y', 'z') NOT NULL,
105 col_date DATE NOT NULL,
106 col_time TIME NOT NULL,
107 col_datetime DATETIME NOT NULL,
108 col_timestamp TIMESTAMP NULL,
109 col_year YEAR NOT NULL,
110 col_nullable VARCHAR(20) NULL DEFAULT 'none',
111 {$json}
112 col_point POINT NOT NULL,
113 col_polygon POLYGON NOT NULL
114 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
115 SQL);
116 try {
117 $row = $provider->fixture($table);
118 $expressions = ['col_bit' => 'CAST(? AS UNSIGNED)', 'col_point' => 'ST_GeomFromText(?)', 'col_polygon' => 'ST_GeomFromText(?)'];
119 $statement = $pdo->prepare(sprintf(
120 'INSERT INTO %s (%s) VALUES (%s)',
121 $table,
122 implode(', ', array_keys($row)),
123 implode(', ', array_map(static fn (string $column): string => $expressions[$column] ?? '?', array_keys($row))),
124 ));
125 self::assertTrue($statement->execute(array_values(array_replace($row, array_map('intval', array_filter($row, 'is_bool'))))));
126 $count = $pdo->query(sprintf('SELECT COUNT(*) FROM %s', $table));
127 self::assertNotFalse($count);
128 self::assertSame(1, (int) $count->fetchColumn());
129 } finally {
130 $pdo->exec(sprintf('DROP TABLE IF EXISTS %s', $table));
131 }
132 }
133}
134