diff --git a/composer.json b/composer.json index 42cc19a..4632765 100644 --- a/composer.json +++ b/composer.json @@ -41,8 +41,7 @@ } }, "scripts": { - "integration": "paratest tests/ --exclude-group=legacy --bootstrap vendor/autoload.php -f", - "integration:old": "phpunit tests/Integration/OldTests --bootstrap vendor/autoload.php", + "integration": "paratest tests/ --bootstrap vendor/autoload.php -f", "cs": "php-cs-fixer fix --dry-run", "cs:fix": "php-cs-fixer fix", "phpstan": "phpstan analyse --memory-limit=256M" diff --git a/src/Container/Container.php b/src/Container/Container.php deleted file mode 100644 index ade3661..0000000 --- a/src/Container/Container.php +++ /dev/null @@ -1,172 +0,0 @@ - $cmd - */ - public function withCmd(array $cmd): self - { - return $this->withCommand($cmd); - } - - /** - * @deprecated Use `withPrivilegedMode` instead - */ - public function withPrivileged(bool $privileged = true): self - { - return $this->withPrivilegedMode($privileged); - } - - /** - * @deprecated Use `withExposedPorts` instead - */ - public function withPort(string $localPort, string $containerPort): self - { - $this->withPortGenerator(new FixedPortGenerator([(int)$localPort])); - return $this->withExposedPorts($containerPort); - } - - /** - * @deprecated there will be no replacement - */ - public function withImage(string $image): self - { - $this->image = $image; - - return $this; - } - - /** - * @deprecated Use `start` instead - */ - public function run(): self - { - $this->startedContainer = $this->start(); - - return $this; - } - - /** - * @param array $commandAsArray - * @deprecated Use 'exec' from StartedTestContainer instead - */ - public function execute(array $commandAsArray): string - { - if ($this->startedContainer === null) { - throw new \RuntimeException('Container is not started'); - } - - return $this->startedContainer->exec($commandAsArray); - } - - /** - * @deprecated Use 'logs' from StartedTestContainer instead - */ - public function logs(): string - { - if ($this->startedContainer === null) { - throw new \RuntimeException('Container is not started'); - } - - return $this->startedContainer->logs(); - } - - /** - * @deprecated Use 'getHost' from StartedTestContainer instead - */ - public function getAddress(): string - { - if ($this->startedContainer === null) { - throw new \RuntimeException('Container is not started'); - } - - return $this->startedContainer->getHost(); - } - - /** - * @deprecated Use 'getFirstMappedPort' from StartedTestContainer instead - */ - public function getPort(): int - { - if ($this->startedContainer === null) { - throw new \RuntimeException('Container is not started'); - } - - return $this->startedContainer->getFirstMappedPort(); - } - - /** - * @deprecated Use 'stop' from StartedTestContainer instead - */ - public function kill(): self - { - $this->dockerClient->containerKill($this->id); - - return $this; - } - - /** - * @deprecated Use `stop` from StartedTestContainer instead - */ - public function stop(): self - { - if ($this->startedContainer === null) { - throw new \RuntimeException('Container is not started'); - } - - $this->stoppedContainer = $this->startedContainer->stop(); - - return $this; - } - - /** - * @deprecated Use 'restart' method from StartedTestContainer instead - */ - public function restart(): self - { - if ($this->startedContainer === null) { - throw new \RuntimeException('Container is not started'); - } - - $restartedTestContainer = $this->startedContainer->restart(); - $this->startedContainer = $restartedTestContainer; - - return $this; - } - - /** - * @deprecated Use 'stop' method from StartedTestContainer instead - */ - public function remove(): self - { - if ($this->startedContainer === null) { - throw new \RuntimeException('Container is not started'); - } - - $this->startedContainer->stop(); - - return $this; - } -} diff --git a/src/Container/GenericContainer.php b/src/Container/GenericContainer.php index 65555f7..abdbc5c 100644 --- a/src/Container/GenericContainer.php +++ b/src/Container/GenericContainer.php @@ -154,25 +154,13 @@ class GenericContainer implements TestContainer } /** - * To support temporarily backwards compatibility, the method supports two formats: - * 1. A single key-value pair (deprecated): $object->withEnvironment('key', 'value'); - * 2. An array of key-value pairs: $object->withEnvironment(['key1' => 'value1', 'key2' => 'value2']); - * - * @param string | array $env An array of environment variables or the name of a single variable. - * @param string|null $value The value of the environment variable if a single variable is passed. + * @param array $env An array of key-value pairs: $object->withEnvironment(['key1' => 'value1', 'key2' => 'value2']); * @return static Returns itself for chaining purposes. */ - public function withEnvironment(string | array $env, ?string $value = null): static + public function withEnvironment(array $env): static { - if (is_array($env)) { - foreach ($env as $key => $val) { - $this->env[$key] = $val; - } - } else { - if ($value === null) { - throw new InvalidArgumentException("Value cannot be null when setting a single environment variable."); - } - $this->env[$env] = $value; + foreach ($env as $key => $val) { + $this->env[$key] = $val; } return $this; @@ -267,7 +255,6 @@ class GenericContainer implements TestContainer return $this; } - //TODO: not yet implemented public function withNetwork(string $networkName): static { $this->networkName = $networkName; diff --git a/src/Container/MariaDBContainer.php b/src/Container/MariaDBContainer.php deleted file mode 100644 index dfd5dbc..0000000 --- a/src/Container/MariaDBContainer.php +++ /dev/null @@ -1,49 +0,0 @@ -withPortGenerator(new FixedPortGenerator([3306])); - $this->withExposedPorts(3306); - $this->withEnvironment('MARIADB_ROOT_PASSWORD', $mysqlRootPassword); - $this->withWait(new WaitForExec([ - "mariadb-admin", - "ping", - "-h", "127.0.0.1", - ])); - } - - public static function make(string $version = 'latest', string $mysqlRootPassword = 'root'): self - { - return new self($version, $mysqlRootPassword); - } - - public function withMariaDBUser(string $username, string $password): self - { - $this->withEnvironment('MARIADB_USER', $username); - $this->withEnvironment('MARIADB_PASSWORD', $password); - - return $this; - } - - public function withMariaDBDatabase(string $database): self - { - $this->withEnvironment('MARIADB_DATABASE', $database); - - return $this; - } -} diff --git a/src/Container/MySQLContainer.php b/src/Container/MySQLContainer.php deleted file mode 100644 index ee8f653..0000000 --- a/src/Container/MySQLContainer.php +++ /dev/null @@ -1,49 +0,0 @@ -withPortGenerator(new FixedPortGenerator([3306])); - $this->withExposedPorts(3306); - $this->withEnvironment('MYSQL_ROOT_PASSWORD', $mysqlRootPassword); - $this->withWait(new WaitForExec([ - "mysqladmin", - "ping", - "-h", "127.0.0.1", - ])); - } - - public static function make(string $version = 'latest', string $mysqlRootPassword = 'root'): self - { - return new self($version, $mysqlRootPassword); - } - - public function withMySQLUser(string $username, string $password): self - { - $this->withEnvironment('MYSQL_USER', $username); - $this->withEnvironment('MYSQL_PASSWORD', $password); - - return $this; - } - - public function withMySQLDatabase(string $database): self - { - $this->withEnvironment('MYSQL_DATABASE', $database); - - return $this; - } -} diff --git a/src/Container/OpenSearchContainer.php b/src/Container/OpenSearchContainer.php deleted file mode 100644 index dde44a7..0000000 --- a/src/Container/OpenSearchContainer.php +++ /dev/null @@ -1,42 +0,0 @@ -withPortGenerator(new FixedPortGenerator([9200])); - $this->withExposedPorts(9200); - $this->withEnvironment('discovery.type', 'single-node'); - $this->withEnvironment('OPENSEARCH_INITIAL_ADMIN_PASSWORD', 'c3o_ZPHo!'); - $this->withWait(new WaitForLog( - '/\]\s+started\?\[/', - true, - 30000 - )); - } - - public static function make(string $version = 'latest'): self - { - return new self($version); - } - - public function disableSecurityPlugin(): self - { - $this->withEnvironment('plugins.security.disabled', 'true'); - - return $this; - } -} diff --git a/src/Container/PostgresContainer.php b/src/Container/PostgresContainer.php deleted file mode 100644 index 073144e..0000000 --- a/src/Container/PostgresContainer.php +++ /dev/null @@ -1,53 +0,0 @@ -withPortGenerator(new FixedPortGenerator([5432])); - $this->withExposedPorts(5432); - $this->withEnvironment('POSTGRES_USER', $this->username); - $this->withEnvironment('POSTGRES_PASSWORD', $this->password); - $this->withEnvironment('POSTGRES_DB', $this->database); - $this->withWait(new WaitForExec(["pg_isready", "-h", "127.0.0.1", "-U", $this->username])); - } - - public static function make(string $version = 'latest', string $dbPassword = 'root'): self - { - return new self( - version: $version, - password: $dbPassword - ); - } - - public function withPostgresUser(string $username): self - { - $this->withEnvironment('POSTGRES_USER', $username); - - return $this; - } - - public function withPostgresDatabase(string $database): self - { - $this->withEnvironment('POSTGRES_DB', $database); - - return $this; - } -} diff --git a/src/Container/RedisContainer.php b/src/Container/RedisContainer.php deleted file mode 100644 index 8b895ec..0000000 --- a/src/Container/RedisContainer.php +++ /dev/null @@ -1,29 +0,0 @@ -withPortGenerator(new FixedPortGenerator([6379])); - $this->withExposedPorts(6379); - $this->withWait(new WaitForLog('Ready to accept connections')); - } - - public static function make(string $version = 'latest'): self - { - return new self($version); - } -} diff --git a/src/Container/TestContainer.php b/src/Container/TestContainer.php index 2885e62..43b68ed 100644 --- a/src/Container/TestContainer.php +++ b/src/Container/TestContainer.php @@ -19,10 +19,9 @@ interface TestContainer public function withEntrypoint(string $entryPoint): static; /** - * TODO: replace with array after deprecated implementation is removed - * @param array|string $env + * @param array $env An array of key-value pairs */ - public function withEnvironment(array | string $env, ?string $value): static; + public function withEnvironment(array $env): static; /** @param int|string|array $ports One or more ports to expose. */ public function withExposedPorts(...$ports): static; diff --git a/src/Modules/MariaDBContainer.php b/src/Modules/MariaDBContainer.php index a45ffb3..c6603d4 100644 --- a/src/Modules/MariaDBContainer.php +++ b/src/Modules/MariaDBContainer.php @@ -13,7 +13,7 @@ class MariaDBContainer extends GenericContainer { parent::__construct('mariadb:' . $version); $this->withExposedPorts(3306); - $this->withEnvironment('MARIADB_ROOT_PASSWORD', $mysqlRootPassword); + $this->withEnvironment(['MARIADB_ROOT_PASSWORD' => $mysqlRootPassword]); $this->withWait(new WaitForExec([ "mariadb-admin", "ping", @@ -23,15 +23,15 @@ class MariaDBContainer extends GenericContainer public function withMariaDBUser(string $username, string $password): self { - $this->withEnvironment('MARIADB_USER', $username); - $this->withEnvironment('MARIADB_PASSWORD', $password); + $this->withEnvironment(['MARIADB_USER' => $username]); + $this->withEnvironment(['MARIADB_PASSWORD' => $password]); return $this; } public function withMariaDBDatabase(string $database): self { - $this->withEnvironment('MARIADB_DATABASE', $database); + $this->withEnvironment(['MARIADB_DATABASE' => $database]); return $this; } diff --git a/src/Modules/MySQLContainer.php b/src/Modules/MySQLContainer.php index 00c6a90..283c999 100644 --- a/src/Modules/MySQLContainer.php +++ b/src/Modules/MySQLContainer.php @@ -13,7 +13,7 @@ class MySQLContainer extends GenericContainer { parent::__construct('mysql:' . $version); $this->withExposedPorts(3306); - $this->withEnvironment('MYSQL_ROOT_PASSWORD', $mysqlRootPassword); + $this->withEnvironment(['MYSQL_ROOT_PASSWORD' => $mysqlRootPassword]); $this->withWait(new WaitForExec([ "mysqladmin", "ping", @@ -23,15 +23,15 @@ class MySQLContainer extends GenericContainer public function withMySQLUser(string $username, string $password): self { - $this->withEnvironment('MYSQL_USER', $username); - $this->withEnvironment('MYSQL_PASSWORD', $password); + $this->withEnvironment(['MYSQL_USER' => $username]); + $this->withEnvironment(['MYSQL_PASSWORD' => $password]); return $this; } public function withMySQLDatabase(string $database): self { - $this->withEnvironment('MYSQL_DATABASE', $database); + $this->withEnvironment(['MYSQL_DATABASE' => $database]); return $this; } diff --git a/src/Modules/OpenSearchContainer.php b/src/Modules/OpenSearchContainer.php index ddbb445..57b1f94 100644 --- a/src/Modules/OpenSearchContainer.php +++ b/src/Modules/OpenSearchContainer.php @@ -13,8 +13,11 @@ class OpenSearchContainer extends GenericContainer { parent::__construct('opensearchproject/opensearch:' . $version); $this->withExposedPorts(9200); - $this->withEnvironment('discovery.type', 'single-node'); - $this->withEnvironment('OPENSEARCH_INITIAL_ADMIN_PASSWORD', 'c3o_ZPHo!'); + $this->withEnvironment([ + 'discovery.type' => 'single-node', + 'OPENSEARCH_INITIAL_ADMIN_PASSWORD' => 'c3o_ZPHo!', + ]); + $this->withWait(new WaitForLog( '/\]\s+started\?\[/', true, @@ -24,7 +27,7 @@ class OpenSearchContainer extends GenericContainer public function withDisabledSecurityPlugin(): self { - $this->withEnvironment('plugins.security.disabled', 'true'); + $this->withEnvironment(['plugins.security.disabled' => 'true']); return $this; } diff --git a/src/Modules/PostgresContainer.php b/src/Modules/PostgresContainer.php index 764663b..6b5e43f 100644 --- a/src/Modules/PostgresContainer.php +++ b/src/Modules/PostgresContainer.php @@ -17,29 +17,31 @@ class PostgresContainer extends GenericContainer ) { parent::__construct('postgres:' . $version); $this->withExposedPorts(5432); - $this->withEnvironment('POSTGRES_USER', $this->username); - $this->withEnvironment('POSTGRES_PASSWORD', $this->password); - $this->withEnvironment('POSTGRES_DB', $this->database); + $this->withEnvironment([ + 'POSTGRES_USER' => $this->username, + 'POSTGRES_PASSWORD' => $this->password, + 'POSTGRES_DB' => $this->database, + ]); $this->withWait(new WaitForExec(["pg_isready", "-h", "127.0.0.1", "-U", $this->username])); } public function withPostgresUser(string $username): self { - $this->withEnvironment('POSTGRES_USER', $username); + $this->withEnvironment(['POSTGRES_USER' => $username]); return $this; } public function withPostgresPassword(string $password): self { - $this->withEnvironment('POSTGRES_PASSWORD', $password); + $this->withEnvironment(['POSTGRES_PASSWORD' => $password]); return $this; } public function withPostgresDatabase(string $database): self { - $this->withEnvironment('POSTGRES_DB', $database); + $this->withEnvironment(['POSTGRES_DB' => $database]); return $this; } diff --git a/src/Wait/WaitForTcpPortOpen.php b/src/Wait/WaitForTcpPortOpen.php deleted file mode 100644 index a65cebe..0000000 --- a/src/Wait/WaitForTcpPortOpen.php +++ /dev/null @@ -1,26 +0,0 @@ -stop(); } - /** - * @throws \JsonException - */ public function testShouldReturnFirstMappedPort(): void { $container = (new GenericContainer('nginx')) diff --git a/tests/Integration/OldTests/ContainerTest.php b/tests/Integration/OldTests/ContainerTest.php deleted file mode 100644 index 74c16d1..0000000 --- a/tests/Integration/OldTests/ContainerTest.php +++ /dev/null @@ -1,142 +0,0 @@ -withMySQLDatabase('foo'); - $container->withMySQLUser('bar', 'baz'); - - $container->run(); - - $pdo = new \PDO( - sprintf('mysql:host=%s;port=3306', $container->getAddress()), - 'bar', - 'baz', - ); - - $query = $pdo->query('SHOW databases'); - - $this->assertInstanceOf(\PDOStatement::class, $query); - - $databases = $query->fetchAll(\PDO::FETCH_COLUMN); - - $this->assertContains('foo', $databases); - - $container->stop(); - } - - public function testMariaDB(): void - { - $container = MariaDBContainer::make(); - $container->withMariaDBDatabase('foo'); - $container->withMariaDBUser('bar', 'baz'); - - $container->run(); - - $pdo = new \PDO( - sprintf('mysql:host=%s;port=3306', $container->getAddress()), - 'bar', - 'baz', - ); - - $query = $pdo->query('SHOW databases'); - - $this->assertInstanceOf(\PDOStatement::class, $query); - - $databases = $query->fetchAll(\PDO::FETCH_COLUMN); - - $this->assertContains('foo', $databases); - - $container->stop(); - } - - public function testRedis(): void - { - $container = RedisContainer::make(); - - $container->run(); - - $redis = new Client([ - 'scheme' => 'tcp', - 'host' => $container->getAddress(), - 'port' => 6379, - ]); - - $redis->ping(); - - $this->assertTrue($redis->isConnected()); - - $container->stop(); - } - - /** - * @throws \JsonException - */ - public function testOpenSearch(): void - { - $container = OpenSearchContainer::make(); - $container->disableSecurityPlugin(); - - $container->run(); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, sprintf('http://%s:%d', $container->getAddress(), 9200)); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - - $response = (string) curl_exec($ch); - - $this->assertNotEmpty($response); - - /** @var array{cluster_name: string} $data */ - $data = json_decode($response, true, JSON_THROW_ON_ERROR, JSON_THROW_ON_ERROR); - - $this->assertArrayHasKey('cluster_name', $data); - - $this->assertEquals('docker-cluster', $data['cluster_name']); - - $container->stop(); - } - - public function testPostgreSQLContainer(): void - { - $container = PostgresContainer::make('latest', 'test') - ->withPostgresUser('test') - ->withPostgresDatabase('foo') - ->run(); - - - $pdo = new \PDO( - sprintf('pgsql:host=%s;port=5432;dbname=foo', $container->getAddress()), - 'test', - 'test', - ); - - $query = $pdo->query('SELECT datname FROM pg_database'); - - $this->assertInstanceOf(\PDOStatement::class, $query); - - $databases = $query->fetchAll(\PDO::FETCH_COLUMN); - - $this->assertContains('foo', $databases); - - $container->stop(); - } -} diff --git a/tests/Integration/OldTests/WaitStrategyTest.php b/tests/Integration/OldTests/WaitStrategyTest.php deleted file mode 100644 index a7c63cb..0000000 --- a/tests/Integration/OldTests/WaitStrategyTest.php +++ /dev/null @@ -1,138 +0,0 @@ -withEnvironment('MYSQL_ROOT_PASSWORD', 'root') - ->withWait( - new WaitForExec([ - 'mysqladmin', 'ping', - '-h', '127.0.0.1', - ]) - ); - - $container->run(); - - $pdo = new \PDO( - sprintf('mysql:host=%s;port=3306', $container->getAddress()), - 'root', - 'root' - ); - - $query = $pdo->query('select version()'); - - $this->assertInstanceOf(\PDOStatement::class, $query); - - $version = $query->fetchColumn(); - - $this->assertNotEmpty($version); - - $container->stop(); - } - - public function testWaitForLog(): void - { - $container = RedisContainer::make() - ->withWait(new WaitForLog('Ready to accept connections')); - - $container->run(); - - $redis = new Client([ - 'scheme' => 'tcp', - 'host' => $container->getAddress(), - 'port' => 6379, - ]); - - $redis->set('foo', 'bar'); - - $this->assertEquals('bar', $redis->get('foo')); - - $container->stop(); - - $this->expectException(ConnectionException::class); - - $redis->get('foo'); - - $container->remove(); - } - - public function testWaitForHTTP(): void - { - $container = Container::make('nginx:alpine') - ->withWait(WaitForHttp::make(3000)) - ->withPort('3000', '80'); - - $container->run(); - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, sprintf('http://%s:%d', $container->getAddress(), $container->getPort())); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - - $response = (string) curl_exec($ch); - - curl_close($ch); - - $this->assertNotEmpty($response); - - $container->stop(); - } - - public function testWaitForTcpPortOpen(): void - { - $container = Container::make('nginx:alpine') - ->withWait(WaitForTcpPortOpen::make(80)) - ->withPort('80', '80'); - - $container->run(); - - static::assertIsResource(fsockopen($container->getAddress(), 80), 'Failed to connect to container'); - - $container->stop(); - } - - public function testWaitForHealthCheck(): void - { - $container = Container::make('nginx') - ->withHealthCheckCommand('curl --fail http://localhost') - ->withPort('80', '80') - ->withWait(new WaitForHealthCheck()); - - $container->run(); - - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, sprintf('http://%s:%d', $container->getAddress(), 80)); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - - $response = curl_exec($ch); - - $this->assertNotEmpty($response); - $this->assertIsString($response); - - $this->assertStringContainsString('Welcome to nginx!', $response); - - $container->stop(); - } -}