packages/ztd-query-pdo-adapter/fuzz/Container/DatabaseEndpoint.php

1<?php
2
3declare(strict_types=1);
4
5namespace Fuzz\Container;
6
7use Container\MySql80Container;
8use Container\MySql84Container;
9use Container\PostgreSql16Container;
10use RuntimeException;
11use Testcontainers\Testcontainers;
12
13/**
14 * Selects a disposable service supplied by CI or starts a local test container.
15 */
16final class DatabaseEndpoint
17{
18    /**
19     * @return array{string, int}
20     * @throws RuntimeException When the service port is invalid or unmapped.
21     */
22    public static function mysql(): array
23    {
24        $host = getenv('MYSQL_HOST');
25        if ($host !== false) {
26            return [$host, self::port('MYSQL_PORT', 3306)];
27        }
28        $instance = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
29
30        return [str_replace('localhost', '127.0.0.1', $instance->getHost()), $instance->getMappedPort(3306) ?? throw new RuntimeException('MySQL port was not mapped.')];
31    }
32
33    /**
34     * @return array{string, int}
35     * @throws RuntimeException When the service port is invalid or unmapped.
36     */
37    public static function postgres(): array
38    {
39        $host = getenv('PG_HOST');
40        if ($host !== false) {
41            return [$host, self::port('PG_PORT', 5432)];
42        }
43        $instance = Testcontainers::run(PostgreSql16Container::class);
44
45        return [str_replace('localhost', '127.0.0.1', $instance->getHost()), $instance->getMappedPort(5432) ?? throw new RuntimeException('PostgreSQL port was not mapped.')];
46    }
47
48    /**
49     * @throws RuntimeException When a configured port is not a valid TCP port.
50     */
51    public static function port(string $variable, int $default): int
52    {
53        $value = getenv($variable);
54        if ($value === false) {
55            return $default;
56        }
57        $port = filter_var($value, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 65535]]);
58        if ($port === false) {
59            throw new RuntimeException($variable . ' must be a TCP port between 1 and 65535.');
60        }
61
62        return $port;
63    }
64}
65