From de1324ed2800eff4da326d0c23d281399d006bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez=20Gonzales?= Date: Tue, 24 May 2022 23:31:37 -0500 Subject: [PATCH] Apply spotless and checkstyle (#5390) --- .github/workflows/ci-docker-wormhole.yml | 1 + build.gradle | 11 +- config/checkstyle/checkstyle.xml | 8 +- .../testcontainers/AbstractJarFileTest.java | 5 +- .../testcontainers/JarFileShadingTest.java | 24 +- .../testcontainers/PublicBinaryAPITest.java | 76 +- .../testcontainers/DockerClientFactory.java | 93 ++- .../org/testcontainers/Testcontainers.java | 15 +- .../java/org/testcontainers/UnstableAPI.java | 6 +- .../testcontainers/containers/BindMode.java | 3 +- .../ComposeServiceWaitStrategyTarget.java | 15 +- .../testcontainers/containers/Container.java | 22 +- .../containers/ContainerFetchException.java | 1 + .../containers/ContainerState.java | 42 +- .../containers/DockerComposeContainer.java | 236 ++++-- .../containers/DockerComposeFiles.java | 4 +- .../containers/ExecInContainerPattern.java | 38 +- .../FailureDetectingExternalResource.java | 16 +- .../FixedHostPortGenericContainer.java | 5 +- .../containers/FutureContainer.java | 1 + .../containers/GenericContainer.java | 323 ++++---- .../containers/InternetProtocol.java | 1 - .../testcontainers/containers/Network.java | 1 - .../containers/ParsedDockerComposeFile.java | 65 +- .../containers/PortForwardingContainer.java | 24 +- .../containers/SelinuxContext.java | 1 - .../containers/SocatContainer.java | 16 +- .../containers/VncRecordingContainer.java | 55 +- .../containers/output/BaseConsumer.java | 1 + .../output/FrameConsumerResultCallback.java | 4 +- .../containers/output/OutputFrame.java | 19 +- .../containers/output/Slf4jLogConsumer.java | 10 +- .../containers/output/ToStringConsumer.java | 1 + .../containers/output/WaitingConsumer.java | 4 +- ...finiteWaitOneShotStartupCheckStrategy.java | 1 + ...umDurationRunningStartupCheckStrategy.java | 1 - .../startupcheck/StartupCheckStrategy.java | 51 +- .../containers/traits/LinkableContainer.java | 1 - .../internal/ExternalPortListeningCheck.java | 20 +- .../InternalCommandPortListeningCheck.java | 25 +- .../wait/strategy/AbstractWaitStrategy.java | 21 +- .../DockerHealthcheckWaitStrategy.java | 7 +- .../wait/strategy/HostPortWaitStrategy.java | 98 ++- .../wait/strategy/HttpWaitStrategy.java | 207 ++--- .../wait/strategy/LogMessageWaitStrategy.java | 18 +- .../containers/wait/strategy/Wait.java | 9 +- .../wait/strategy/WaitAllStrategy.java | 29 +- .../wait/strategy/WaitStrategy.java | 1 - .../wait/strategy/WaitStrategyTarget.java | 8 +- .../AuditLoggingDockerClient.java | 127 +-- .../AuthDelegatingDockerClientConfig.java | 14 +- .../dockerclient/DockerClientConfigUtils.java | 27 +- .../DockerClientProviderStrategy.java | 139 ++-- .../DockerMachineClientProviderStrategy.java | 21 +- ...dSystemPropertyClientProviderStrategy.java | 11 +- .../HeadersAddingDockerHttpClient.java | 4 +- .../InvalidConfigurationException.java | 2 +- .../LogToStringContainerCallback.java | 1 + .../NpipeSocketClientProviderStrategy.java | 5 +- .../RootlessDockerClientProviderStrategy.java | 20 +- .../UnixSocketClientProviderStrategy.java | 11 +- .../images/AbstractImagePullPolicy.java | 3 +- .../org/testcontainers/images/ImageData.java | 7 +- .../images/ImagePullPolicy.java | 2 - .../images/LocalImagesCache.java | 8 +- .../images/LoggedPullImageResultCallback.java | 38 +- .../images/ParsedDockerfile.java | 17 +- .../org/testcontainers/images/PullPolicy.java | 5 +- .../images/RemoteDockerImage.java | 24 +- ...eLimitedLoggedPullImageResultCallback.java | 39 +- .../images/builder/ImageFromDockerfile.java | 54 +- .../images/builder/Transferable.java | 1 - .../builder/dockerfile/DockerfileBuilder.java | 5 +- .../dockerfile/statement/Statement.java | 2 +- .../dockerfile/traits/AddStatementTrait.java | 1 - .../dockerfile/traits/CmdStatementTrait.java | 1 - .../dockerfile/traits/CopyStatementTrait.java | 1 - .../traits/DockerfileBuilderTrait.java | 1 - .../traits/EntryPointStatementTrait.java | 1 - .../dockerfile/traits/EnvStatementTrait.java | 1 - .../traits/ExposeStatementTrait.java | 8 +- .../dockerfile/traits/FromStatementTrait.java | 1 - .../traits/LabelStatementTrait.java | 1 - .../dockerfile/traits/RunStatementTrait.java | 1 - .../dockerfile/traits/UserStatementTrait.java | 1 - .../traits/VolumeStatementTrait.java | 1 - .../traits/WorkdirStatementTrait.java | 1 - .../traits/BuildContextBuilderTrait.java | 1 - .../images/builder/traits/ClasspathTrait.java | 1 - .../builder/traits/DockerfileTrait.java | 38 +- .../images/builder/traits/FilesTrait.java | 1 - .../images/builder/traits/StringsTrait.java | 29 +- .../testcontainers/lifecycle/Startable.java | 1 - .../testcontainers/lifecycle/Startables.java | 36 +- .../lifecycle/TestDescription.java | 1 - .../lifecycle/TestLifecycleAware.java | 9 +- .../testcontainers/utility/AuditLogger.java | 45 +- .../utility/AuthConfigUtil.java | 9 +- .../org/testcontainers/utility/Base58.java | 3 +- .../utility/ClasspathScanner.java | 6 +- .../testcontainers/utility/CommandLine.java | 14 +- .../utility/ComparableVersion.java | 10 +- ...ConfigurationFileImageNameSubstitutor.java | 3 +- .../utility/DefaultImageNameSubstitutor.java | 13 +- .../utility/DockerImageName.java | 68 +- .../utility/DockerLoggerFactory.java | 1 - .../utility/DockerMachineClient.java | 45 +- .../testcontainers/utility/DockerStatus.java | 22 +- .../utility/DynamicPollInterval.java | 1 + .../utility/ImageNameSubstitutor.java | 40 +- .../utility/JVMHookResourceReaper.java | 21 +- .../testcontainers/utility/LazyFuture.java | 2 +- .../utility/LicenseAcceptance.java | 17 +- .../org/testcontainers/utility/LogUtils.java | 40 +- .../testcontainers/utility/MountableFile.java | 115 ++- .../org/testcontainers/utility/PathUtils.java | 34 +- .../PrefixingImageNameSubstitutor.java | 6 +- .../utility/RegistryAuthLocator.java | 141 ++-- .../utility/ResourceReaper.java | 66 +- .../testcontainers/utility/RyukContainer.java | 11 +- .../utility/RyukResourceReaper.java | 5 +- .../utility/TestEnvironment.java | 4 +- .../utility/TestcontainersConfiguration.java | 95 ++- .../utility/ThrowingFunction.java | 1 - .../testcontainers/utility/Versioning.java | 5 + .../OutOfPackageImagePullPolicyTest.java | 19 +- .../java/org/testcontainers/DaemonTest.java | 10 +- .../DockerClientFactoryTest.java | 8 +- .../DockerRegistryContainer.java | 39 +- .../containers/ContainerStateTest.java | 22 +- ...ockerComposeContainerWithServicesTest.java | 36 +- .../containers/DockerComposeFilesTest.java | 22 +- .../DockerComposeOverridesTest.java | 81 +- .../containers/ExposedHostTest.java | 36 +- .../FailureDetectingExternalResourceTest.java | 1 - .../containers/GenericContainerTest.java | 84 +- .../containers/NetworkTest.java | 73 +- ...ParsedDockerComposeFileValidationTest.java | 69 +- .../containers/ReusabilityUnitTests.java | 170 ++-- .../containers/output/ContainerLogsTest.java | 15 +- .../FrameConsumerResultCallbackTest.java | 100 ++- .../output/ToStringConsumerTest.java | 27 +- .../ExternalPortListeningCheckTest.java | 32 +- ...InternalCommandPortListeningCheckTest.java | 44 +- .../DockerHealthcheckWaitStrategyTest.java | 14 +- .../wait/strategy/WaitAllStrategyTest.java | 61 +- .../dockerclient/AmbiguousImagePullTest.java | 3 +- .../DockerClientConfigUtilsTest.java | 24 +- ...temPropertyClientProviderStrategyTest.java | 77 +- .../dockerclient/EventStreamTest.java | 30 +- .../dockerclient/ImagePullTest.java | 10 +- .../images/AgeBasedPullPolicyTest.java | 12 +- .../testcontainers/images/ImageDataTest.java | 8 +- .../images/ImagePullPolicyTest.java | 46 +- .../images/ParsedDockerfileTest.java | 90 ++- .../images/RemoteDockerImageTest.java | 10 +- .../images/builder/DockerfileBuildTest.java | 47 +- .../images/builder/DockerignoreTest.java | 30 +- .../builder/ImageFromDockerfileTest.java | 10 +- .../statement/AbstractStatementTest.java | 6 +- .../statement/KeyValuesStatementTest.java | 24 +- .../statement/MultiArgsStatementTest.java | 2 +- .../statement/RawStatementTest.java | 3 +- .../SingleArgumentStatementTest.java | 2 +- .../junit/BaseDockerComposeTest.java | 29 +- .../junit/CopyFileToContainerTest.java | 13 +- .../junit/DependenciesTest.java | 26 +- .../DockerComposeContainerScalingTest.java | 17 +- .../junit/DockerComposeContainerTest.java | 39 +- .../DockerComposeContainerWithBuildTest.java | 84 +- ...DockerComposeContainerWithOptionsTest.java | 53 +- .../junit/DockerComposeErrorHandlingTest.java | 14 +- .../junit/DockerComposeLocalImageTest.java | 4 +- .../junit/DockerComposeLogConsumerTest.java | 18 +- .../junit/DockerComposePassthroughTest.java | 20 +- .../junit/DockerComposeServiceTest.java | 13 +- .../junit/DockerComposeV2FormatTest.java | 6 +- .../junit/DockerComposeV2WithNetworkTest.java | 13 +- .../junit/DockerComposeWaitStrategyTest.java | 62 +- .../junit/DockerNetworkModeTest.java | 6 +- .../junit/DockerfileContainerTest.java | 31 +- .../testcontainers/junit/DockerfileTest.java | 68 +- .../junit/FileOperationsTest.java | 32 +- .../junit/FixedHostPortContainerTest.java | 32 +- .../junit/GenericContainerRuleTest.java | 269 ++++--- .../junit/NonExistentImagePullTest.java | 12 +- .../junit/OutputStreamTest.java | 57 +- .../junit/OutputStreamWithTTYTest.java | 43 +- .../ParameterizedDockerfileContainerTest.java | 30 +- .../junit/WorkingDirectoryTest.java | 11 +- .../strategy/AbstractWaitStrategyTest.java | 28 +- .../strategy/HostPortWaitStrategyTest.java | 3 +- .../wait/strategy/HttpWaitStrategyTest.java | 154 ++-- .../strategy/LogMessageWaitStrategyTest.java | 29 +- .../utility/AuthenticatedImagePullTest.java | 65 +- .../utility/ClasspathScannerTest.java | 83 +- .../utility/ComparableVersionTest.java | 24 +- .../DefaultImageNameSubstitutorTest.java | 2 + .../utility/DirectoryTarResourceTest.java | 81 +- .../DockerImageNameCompatibilityTest.java | 13 +- .../utility/DockerImageNameTest.java | 95 ++- .../utility/DockerStatusTest.java | 18 +- .../utility/FakeImageSubstitutor.java | 1 + .../utility/FilterRegistryTest.java | 12 +- .../utility/ImageNameSubstitutorTest.java | 12 +- .../utility/LazyFutureTest.java | 16 +- .../utility/MountableFileTest.java | 33 +- .../PrefixingImageNameSubstitutorTest.java | 51 +- .../utility/RegistryAuthLocatorTest.java | 76 +- .../utility/ResourceReaperTest.java | 27 +- .../TestcontainersConfigurationTest.java | 69 +- .../test/java/generic/CmdModifierTest.java | 15 +- .../src/test/java/generic/CommandsTest.java | 3 +- .../java/generic/ContainerCreationTest.java | 24 +- .../test/java/generic/ContainerLabelTest.java | 2 +- .../java/generic/HostPortExposedTest.java | 24 +- .../generic/ImageNameSubstitutionTest.java | 9 +- .../generic/MultiplePortsExposedTest.java | 13 +- .../test/java/generic/WaitStrategiesTest.java | 29 +- .../StartupCheckStrategyTest.java | 38 +- .../quickstart/RedisBackedCacheIntTest.java | 5 +- .../RedisBackedCacheIntTestStep0.java | 2 +- .../quickstart/RedisBackedCacheIntTest.java | 5 +- .../RedisBackedCacheIntTestStep0.java | 2 +- .../quickstart/RedisBackedCacheIntTest.groovy | 38 +- .../RedisBackedCacheIntTestStep0.groovy | 26 +- docs/modules/hivemq.md | 4 +- .../containers/CosmosDBEmulatorContainer.java | 5 +- .../containers/KeyStoreBuilder.java | 46 +- .../CosmosDBEmulatorContainerTest.java | 22 +- .../containers/CassandraContainer.java | 34 +- .../delegate/CassandraDatabaseDelegate.java | 11 +- .../wait/CassandraQueryWaitStrategy.java | 22 +- .../containers/CassandraContainerTest.java | 24 +- .../containers/ClickHouseContainer.java | 7 +- .../containers/ClickHouseProvider.java | 1 + .../clickhouse/ClickhouseJDBCDriverTest.java | 12 +- .../clickhouse/SimpleClickhouseTest.java | 4 +- .../containers/CockroachContainer.java | 32 +- .../CockroachContainerProvider.java | 1 + .../CockroachDBJDBCDriverTest.java | 12 +- .../cockroachdb/SimpleCockroachDBTest.java | 15 +- .../couchbase/BucketDefinition.java | 6 +- .../couchbase/CouchbaseContainer.java | 333 +++++--- .../couchbase/CouchbaseService.java | 2 - .../couchbase/CouchbaseContainerTest.java | 85 +- .../delegate/AbstractDatabaseDelegate.java | 7 +- .../delegate/DatabaseDelegate.java | 9 +- .../org/testcontainers/ext/ScriptUtils.java | 736 ++++++++++-------- .../ext/ScriptSplittingTest.java | 143 ++-- .../containers/Db2Container.java | 16 +- .../containers/Db2ContainerProvider.java | 1 + .../jdbc/db2/DB2JDBCDriverTest.java | 12 +- .../junit/db2/SimpleDb2Test.java | 17 +- .../dynamodb/DynaliteContainer.java | 22 +- .../dynamodb/DynaliteContainerTest.java | 30 +- .../elasticsearch/ElasticsearchContainer.java | 26 +- .../ElasticsearchContainerTest.java | 215 +++-- .../containers/BigtableEmulatorContainer.java | 9 +- .../DatastoreEmulatorContainer.java | 9 +- .../FirestoreEmulatorContainer.java | 9 +- .../containers/PubSubEmulatorContainer.java | 9 +- .../containers/SpannerEmulatorContainer.java | 9 +- .../BigtableEmulatorContainerTest.java | 61 +- .../DatastoreEmulatorContainerTest.java | 18 +- .../FirestoreEmulatorContainerTest.java | 24 +- .../PubSubEmulatorContainerTest.java | 85 +- .../SpannerEmulatorContainerTest.java | 68 +- .../hivemq/HiveMQContainer.java | 138 ++-- .../hivemq/HiveMQExtension.java | 98 ++- .../hivemq/ContainerWithControlCenterIT.java | 14 +- .../hivemq/ContainerWithCustomConfigIT.java | 25 +- ...ContainerWithExtensionFromDirectoryIT.java | 25 +- .../hivemq/ContainerWithExtensionIT.java | 22 +- .../ContainerWithExtensionSubclassIT.java | 22 +- .../ContainerWithFileInExtensionHomeIT.java | 55 +- .../hivemq/ContainerWithFileInHomeIT.java | 52 +- .../hivemq/ContainerWithLicenseIT.java | 46 +- .../ContainerWithoutPlatformExtensionsIT.java | 71 +- .../hivemq/CreateFileInCopiedDirectoryIT.java | 47 +- .../CreateFileInExtensionDirectoryIT.java | 45 +- ...DisableEnableExtensionFromDirectoryIT.java | 19 +- .../hivemq/DisableEnableExtensionIT.java | 29 +- .../hivemq/HiveMQExtensionTest.java | 5 +- .../hivemq/HiveMQTestContainerCore.java | 20 +- .../hivemq/docs/DemoDisableExtensionsIT.java | 27 +- .../hivemq/docs/DemoExtensionTestsIT.java | 32 +- .../hivemq/docs/DemoFilesIT.java | 35 +- .../hivemq/docs/DemoHiveMQContainerIT.java | 31 +- .../hivemq/util/MyExtension.java | 19 +- .../util/MyExtensionWithSubclasses.java | 19 +- .../hivemq/util/PublishModifier.java | 12 +- .../hivemq/util/TestPublishModifiedUtil.java | 31 +- .../containers/InfluxDBContainer.java | 14 +- .../containers/InfluxDBContainerTest.java | 8 +- .../InfluxDBContainerWithUserTest.java | 15 +- .../db/AbstractContainerDatabaseTest.java | 3 +- .../jdbc/AbstractJDBCDriverTest.java | 136 ++-- .../containers/JdbcDatabaseContainer.java | 49 +- .../JdbcDatabaseContainerProvider.java | 16 +- .../jdbc/ConnectionDelegate.java | 2 +- .../testcontainers/jdbc/ConnectionUrl.java | 89 +-- .../jdbc/ConnectionWrapper.java | 2 +- .../jdbc/ContainerDatabaseDriver.java | 63 +- .../jdbc/JdbcDatabaseDelegate.java | 18 +- .../testcontainers/jdbc/ext/ScriptUtils.java | 62 +- .../containers/JdbcDatabaseContainerTest.java | 5 +- .../jdbc/ConnectionUrlDriversTests.java | 109 ++- .../jdbc/ConnectionUrlTest.java | 41 +- .../jdbc/ContainerDatabaseDriverTest.java | 37 +- .../jdbc/MissingJdbcDriverTest.java | 2 +- .../FilesystemFriendlyNameGenerator.java | 10 +- .../junit/jupiter/Testcontainers.java | 1 - .../jupiter/TestcontainersExtension.java | 69 +- .../TestcontainersTestDescription.java | 2 + .../junit/jupiter/ComposeContainerTests.java | 3 +- .../FilesystemFriendlyNameGeneratorTest.java | 6 +- .../junit/jupiter/MixedLifecycleTests.java | 8 - .../junit/jupiter/PostgresContainerTests.java | 12 +- .../TestLifecycleAwareContainerMock.java | 10 +- ...tLifecycleAwareExceptionCapturingTest.java | 1 + .../jupiter/TestLifecycleAwareMethodTest.java | 17 +- .../jupiter/TestcontainersExtensionTests.java | 10 +- ...ntainersNestedRestartedContainerTests.java | 16 +- ...tcontainersNestedSharedContainerTests.java | 5 +- .../TestcontainersRestartBetweenTests.java | 10 +- .../TestcontainersSharedContainerTests.java | 6 +- .../jupiter/WrongAnnotationUsageTests.java | 3 - .../jupiter/inheritance/AbstractTestBase.java | 1 - .../org/testcontainers/k3s/K3sContainer.java | 13 +- .../k3s/Fabric8K3sContainerTest.java | 10 +- .../containers/KafkaContainer.java | 18 +- .../containers/KafkaContainerTest.java | 80 +- .../localstack/LocalStackContainer.java | 30 +- .../containers/localstack/LegacyModeTest.java | 70 +- .../localstack/LocalstackContainerTest.java | 160 ++-- .../containers/MariaDBContainer.java | 19 +- .../containers/MariaDBContainerProvider.java | 3 +- .../MariaDBR2DBCDatabaseContainer.java | 6 +- .../MariaDBR2DBCDatabaseContainerTest.java | 1 - .../jdbc/mariadb/MariaDBJDBCDriverTest.java | 49 +- .../junit/mariadb/SimpleMariaDBTest.java | 37 +- .../containers/MockServerContainer.java | 2 +- .../MockServerContainerRuleTest.java | 12 +- .../containers/MockServerContainerTest.java | 19 +- .../containers/SimpleHttpClient.java | 4 +- .../containers/MongoDBContainer.java | 45 +- .../containers/MongoDBContainerTest.java | 42 +- .../MSSQLR2DBCDatabaseContainer.java | 6 +- .../containers/MSSQLServerContainer.java | 21 +- .../MSSQLServerContainerProvider.java | 1 + .../MSSQLServerJDBCDriverTest.java | 15 +- .../CustomPasswordMSSQLServerTest.java | 60 +- .../CustomizableMSSQLServerTest.java | 9 +- .../mssqlserver/SimpleMSSQLServerTest.java | 25 +- .../containers/MySQLContainer.java | 17 +- .../containers/MySQLContainerProvider.java | 1 - .../MySQLR2DBCDatabaseContainer.java | 6 +- .../org/testcontainers/MySQLTestImages.java | 3 + .../MySQLR2DBCDatabaseContainerTest.java | 1 - .../containers/MySQLRootAccountTest.java | 7 +- .../jdbc/mysql/JDBCDriverWithPoolTest.java | 54 +- .../jdbc/mysql/MySQLJDBCDriverTest.java | 51 +- .../junit/mysql/CustomizableMysqlTest.java | 16 +- .../junit/mysql/MultiVersionMySQLTest.java | 20 +- .../junit/mysql/SimpleMySQLTest.java | 104 +-- .../neo4j/demos/plugins/HelloWorld.java | 1 - .../containers/Neo4jContainer.java | 71 +- .../Neo4jContainerJUnitIntegrationTest.java | 5 +- .../containers/Neo4jContainerTest.java | 93 +-- .../containers/NginxContainer.java | 7 +- .../testcontainers/junit/SimpleNginxTest.java | 14 +- .../containers/OracleContainer.java | 36 +- .../containers/OracleContainerProvider.java | 1 + .../containers/jdbc/OracleJDBCDriverTest.java | 24 +- .../junit/oracle/SimpleOracleTest.java | 29 +- .../containers/OrientDBContainer.java | 16 +- .../containers/OrientDBContainerTest.java | 13 +- .../containers/PostgisContainerProvider.java | 9 +- .../containers/PostgreSQLContainer.java | 29 +- .../PostgreSQLContainerProvider.java | 2 +- .../PostgreSQLR2DBCDatabaseContainer.java | 6 +- .../TimescaleDBContainerProvider.java | 9 +- .../PostgreSQLConnectionURLTest.java | 19 +- .../PostgreSQLR2DBCDatabaseContainerTest.java | 2 + .../containers/TimescaleDBContainerTest.java | 29 +- .../jdbc/DatabaseDriverShutdownTest.java | 1 + .../jdbc/DatabaseDriverTmpfsTest.java | 1 - .../jdbc/postgis/PostgisJDBCDriverTest.java | 20 +- .../postgresql/PostgreSQLJDBCDriverTest.java | 15 +- .../TimescaleDBJDBCDriverTest.java | 20 +- .../CustomizablePostgreSQLTest.java | 10 +- .../postgresql/SimplePostgreSQLTest.java | 30 +- .../containers/PrestoContainer.java | 26 +- .../containers/PrestoContainerProvider.java | 2 +- .../containers/PrestoContainerTest.java | 98 ++- .../jdbc/presto/PrestoJDBCDriverTest.java | 12 +- .../containers/PulsarContainer.java | 4 +- .../containers/PulsarContainerTest.java | 28 +- .../r2dbc/CancellableSubscription.java | 3 +- .../r2dbc/ConnectionPublisher.java | 10 +- .../r2dbc/EmptySubscription.java | 8 +- .../java/org/testcontainers/r2dbc/Hidden.java | 4 +- .../r2dbc/R2DBCDatabaseContainer.java | 1 - .../r2dbc/R2DBCDatabaseContainerProvider.java | 1 - .../TestcontainersR2DBCConnectionFactory.java | 45 +- ...tcontainersR2DBCConnectionFactoryTest.java | 19 +- .../AbstractR2DBCDatabaseContainerTest.java | 4 +- .../containers/RabbitMQContainer.java | 373 ++++++--- .../containers/RabbitMQContainerTest.java | 248 +++--- .../containers/BrowserWebDriverContainer.java | 125 ++- .../DefaultRecordingFileFactory.java | 23 +- .../containers/RecordingFileFactory.java | 15 +- .../containers/SeleniumUtils.java | 13 +- .../DefaultRecordingFileFactoryTest.java | 37 +- .../junit/BaseWebDriverContainerTest.java | 22 +- .../junit/BrowserWebDriverContainerTest.java | 18 +- ...ChromeRecordingWebDriverContainerTest.java | 102 +-- .../junit/ChromeWebDriverContainerTest.java | 2 +- .../ContainerWithoutCapabilitiesTest.java | 7 +- ...stomWaitTimeoutWebDriverContainerTest.java | 5 +- .../junit/FirefoxWebDriverContainerTest.java | 4 +- .../LocalServerWebDriverContainerTest.java | 8 +- .../junit/SeleniumStartTest.java | 14 +- .../junit/SeleniumUtilsTest.java | 2 - ...ecificImageNameWebDriverContainerTest.java | 5 +- .../containers/SolrClientUtils.java | 49 +- .../containers/SolrClientUtilsException.java | 1 + .../containers/SolrContainer.java | 23 +- .../SolrContainerConfiguration.java | 8 +- .../containers/SolrContainerTest.java | 15 +- .../spock/SpockTestDescription.groovy | 36 +- .../spock/Testcontainers.groovy | 1 - .../spock/TestcontainersExtension.groovy | 42 +- .../TestcontainersMethodInterceptor.groovy | 224 +++--- .../spock/ComposeContainerIT.groovy | 34 +- .../spock/MySqlContainerIT.groovy | 14 +- .../spock/PostgresContainerIT.groovy | 56 +- .../spock/SharedComposeContainerIT.groovy | 36 +- .../spock/SpockTestImages.groovy | 8 +- .../spock/TestHierarchyIT.groovy | 22 +- .../TestLifecycleAwareContainerMock.java | 10 +- .../spock/TestLifecycleAwareIT.groovy | 57 +- ...TestcontainersRestartBetweenTestsIT.groovy | 29 +- .../TestcontainersSharedContainerIT.groovy | 61 +- .../containers/ToxiproxyContainer.java | 50 +- .../containers/ToxiproxyTest.java | 78 +- .../containers/TrinoContainer.java | 17 +- .../containers/TrinoContainerProvider.java | 1 + .../containers/TrinoContainerTest.java | 38 +- .../jdbc/trino/TrinoJDBCDriverTest.java | 12 +- .../testcontainers/vault/VaultContainer.java | 46 +- .../testcontainers/vault/VaultLogLevel.java | 6 +- .../testcontainers/vault/VaultClientTest.java | 20 +- .../vault/VaultContainerTest.java | 74 +- .../org/testcontainers/testsupport/Flaky.java | 10 +- .../testsupport/FlakyTestJUnit4RetryRule.java | 14 +- .../testsupport/FlakyRuleTest.java | 60 +- 458 files changed, 8766 insertions(+), 5973 deletions(-) diff --git a/.github/workflows/ci-docker-wormhole.yml b/.github/workflows/ci-docker-wormhole.yml index b93d26d98bb..6d0df9a3c21 100644 --- a/.github/workflows/ci-docker-wormhole.yml +++ b/.github/workflows/ci-docker-wormhole.yml @@ -16,5 +16,6 @@ jobs: -v "$HOME:$HOME" \ -v "$PWD:$PWD" \ -w "$PWD" \ + -e AUTO_APPLY_GIT_HOOKS=false \ openjdk:8-jdk-alpine \ ./gradlew --no-daemon --continue --scan testcontainers:test --tests '*GenericContainerRuleTest' diff --git a/build.gradle b/build.gradle index adbd1a47c4a..1458b3db027 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,13 @@ buildscript { repositories { mavenCentral() + maven { url 'https://jitpack.io' } } dependencies { // https://github.com/melix/japicmp-gradle-plugin/issues/36 classpath 'com.google.guava:guava:30.1.1-jre' + classpath 'com.github.kiview:captain-hook:76a1c11a16' } } @@ -17,6 +19,12 @@ plugins { } apply from: "$rootDir/gradle/ci-support.gradle" +apply plugin: 'com.github.tjni.captainhook' + +captainHook { + autoApplyGitHooks = Boolean.valueOf(System.getenv("AUTO_APPLY_GIT_HOOKS")) + preCommit = './gradlew spotlessApply' +} subprojects { apply plugin: 'java-library' @@ -110,8 +118,8 @@ subprojects { } spotless { - enforceCheck false java { + toggleOffOn() removeUnusedImports() trimTrailingWhitespace() endWithNewline() @@ -134,6 +142,5 @@ subprojects { checkstyle { toolVersion = "9.3" configFile = rootProject.file('config/checkstyle/checkstyle.xml') - ignoreFailures = true } } diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 39598dae2e4..ccb8367404c 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -11,8 +11,12 @@ LITERAL_FOR, LITERAL_IF, LITERAL_WHILE, - LITERAL_CASE, - LITERAL_DEFAULT, + " + /> + + + diff --git a/core/src/jarFileTest/java/org/testcontainers/AbstractJarFileTest.java b/core/src/jarFileTest/java/org/testcontainers/AbstractJarFileTest.java index d6043422640..ae92aa371b0 100644 --- a/core/src/jarFileTest/java/org/testcontainers/AbstractJarFileTest.java +++ b/core/src/jarFileTest/java/org/testcontainers/AbstractJarFileTest.java @@ -5,8 +5,7 @@ import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; - -import static java.util.Collections.emptyMap; +import java.util.Collections; public abstract class AbstractJarFileTest { @@ -16,7 +15,7 @@ public abstract class AbstractJarFileTest { try { Path jarFilePath = Paths.get(System.getProperty("jarFile")); URI jarFileUri = new URI("jar", jarFilePath.toUri().toString(), null); - FileSystem fileSystem = FileSystems.newFileSystem(jarFileUri, emptyMap()); + FileSystem fileSystem = FileSystems.newFileSystem(jarFileUri, Collections.emptyMap()); root = fileSystem.getPath("/"); } catch (Exception e) { throw new RuntimeException(e); diff --git a/core/src/jarFileTest/java/org/testcontainers/JarFileShadingTest.java b/core/src/jarFileTest/java/org/testcontainers/JarFileShadingTest.java index 4cf7b3a9e9f..99fd1359c85 100644 --- a/core/src/jarFileTest/java/org/testcontainers/JarFileShadingTest.java +++ b/core/src/jarFileTest/java/org/testcontainers/JarFileShadingTest.java @@ -13,34 +13,26 @@ public class JarFileShadingTest extends AbstractJarFileTest { @Test public void testPackages() throws Exception { - assertThatFileList(root).containsOnly( - "org", - "META-INF" - ); - - assertThatFileList(root.resolve("org")).containsOnly( - "testcontainers" - ); + assertThatFileList(root).containsOnly("org", "META-INF"); + + assertThatFileList(root.resolve("org")).containsOnly("testcontainers"); } @Test public void testMetaInf() throws Exception { - assertThatFileList(root.resolve("META-INF")).containsOnly( - "MANIFEST.MF", - "services" - ); + assertThatFileList(root.resolve("META-INF")).containsOnly("MANIFEST.MF", "services"); } @Test public void testMetaInfServices() throws Exception { assertThatFileList(root.resolve("META-INF").resolve("services")) - .allMatch(it -> it.startsWith("org.testcontainers.")); + .allMatch(it -> it.startsWith("org.testcontainers.")); } private ListAssert assertThatFileList(Path path) throws IOException { return (ListAssert) assertThat(Files.list(path)) - .extracting(Path::getFileName) - .extracting(Path::toString) - .extracting(it -> it.endsWith("/") ? it.substring(0, it.length() - 1) : it); + .extracting(Path::getFileName) + .extracting(Path::toString) + .extracting(it -> it.endsWith("/") ? it.substring(0, it.length() - 1) : it); } } diff --git a/core/src/jarFileTest/java/org/testcontainers/PublicBinaryAPITest.java b/core/src/jarFileTest/java/org/testcontainers/PublicBinaryAPITest.java index 208c8702654..77156e77636 100644 --- a/core/src/jarFileTest/java/org/testcontainers/PublicBinaryAPITest.java +++ b/core/src/jarFileTest/java/org/testcontainers/PublicBinaryAPITest.java @@ -37,6 +37,7 @@ public class PublicBinaryAPITest extends AbstractJarFileTest { private static String SHADED_PACKAGE = "org.testcontainers.shaded."; + private static String SHADED_PACKAGE_PATH = SHADED_PACKAGE.replaceAll("\\.", "/"); static { @@ -49,36 +50,38 @@ public class PublicBinaryAPITest extends AbstractJarFileTest { public static List data() throws Exception { List result = new ArrayList<>(); - Files.walkFileTree(root, new SimpleFileVisitor() { - - @Override - public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { - String fileName = path.toString(); + Files.walkFileTree( + root, + new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { + String fileName = path.toString(); - if (!fileName.endsWith(".class")) { - return super.visitFile(path, attrs); - } + if (!fileName.endsWith(".class")) { + return super.visitFile(path, attrs); + } - if (!fileName.startsWith("/org/testcontainers/") ) { - return super.visitFile(path, attrs); - } + if (!fileName.startsWith("/org/testcontainers/")) { + return super.visitFile(path, attrs); + } - if (fileName.startsWith("/" + SHADED_PACKAGE_PATH)) { - return super.visitFile(path, attrs); - } + if (fileName.startsWith("/" + SHADED_PACKAGE_PATH)) { + return super.visitFile(path, attrs); + } - try(InputStream inputStream = Files.newInputStream(path)) { - ClassReader reader = new ClassReader(inputStream); - ClassNode node = new ClassNode(); - reader.accept(node, ClassReader.SKIP_CODE); - if ((node.access & Opcodes.ACC_PUBLIC) != 0) { - result.add(new Object[]{ fileName, node }); + try (InputStream inputStream = Files.newInputStream(path)) { + ClassReader reader = new ClassReader(inputStream); + ClassNode node = new ClassNode(); + reader.accept(node, ClassReader.SKIP_CODE); + if ((node.access & Opcodes.ACC_PUBLIC) != 0) { + result.add(new Object[] { fileName, node }); + } } - } - return super.visitFile(path, attrs); + return super.visitFile(path, attrs); + } } - }); + ); return result; } @@ -100,39 +103,36 @@ public void setUp() { @Test public void testSuperClass() { - assertThat(classNode.superName) - .doesNotStartWith(SHADED_PACKAGE_PATH); + assertThat(classNode.superName).doesNotStartWith(SHADED_PACKAGE_PATH); } @Test public void testInterfaces() { - assertThat(classNode.interfaces) - .allSatisfy(it -> assertThat(it).doesNotStartWith(SHADED_PACKAGE_PATH)); + assertThat(classNode.interfaces).allSatisfy(it -> assertThat(it).doesNotStartWith(SHADED_PACKAGE_PATH)); } @Test public void testMethodReturnTypes() { assertThat(classNode.methods) - .filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0) - .allSatisfy(it -> assertThat(Type.getReturnType(it.desc).getClassName()).doesNotStartWith(SHADED_PACKAGE)); + .filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0) + .allSatisfy(it -> assertThat(Type.getReturnType(it.desc).getClassName()).doesNotStartWith(SHADED_PACKAGE)); } @Test public void testMethodArguments() { assertThat(classNode.methods) - .filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0) - .allSatisfy(method -> assertThat(Arrays.asList(Type.getArgumentTypes(method.desc))) - .extracting(Type::getClassName) - .allSatisfy(it -> assertThat(it).doesNotStartWith(SHADED_PACKAGE)) - ); + .filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0) + .allSatisfy(method -> { + assertThat(Arrays.asList(Type.getArgumentTypes(method.desc))) + .extracting(Type::getClassName) + .allSatisfy(it -> assertThat(it).doesNotStartWith(SHADED_PACKAGE)); + }); } @Test public void testFields() { assertThat(classNode.fields) - .filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0) - .allSatisfy(it -> assertThat(Type.getType(it.desc).getClassName()) - .doesNotStartWith(SHADED_PACKAGE) - ); + .filteredOn(it -> (it.access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) != 0) + .allSatisfy(it -> assertThat(Type.getType(it.desc).getClassName()).doesNotStartWith(SHADED_PACKAGE)); } } diff --git a/core/src/main/java/org/testcontainers/DockerClientFactory.java b/core/src/main/java/org/testcontainers/DockerClientFactory.java index c1e999d392a..04c20236763 100644 --- a/core/src/main/java/org/testcontainers/DockerClientFactory.java +++ b/core/src/main/java/org/testcontainers/DockerClientFactory.java @@ -51,16 +51,17 @@ public class DockerClientFactory { public static final ThreadGroup TESTCONTAINERS_THREAD_GROUP = new ThreadGroup("testcontainers"); + public static final String TESTCONTAINERS_LABEL = DockerClientFactory.class.getPackage().getName(); + public static final String TESTCONTAINERS_SESSION_ID_LABEL = TESTCONTAINERS_LABEL + ".sessionId"; public static final String SESSION_ID = UUID.randomUUID().toString(); - public static final Map DEFAULT_LABELS = ImmutableMap.of( - TESTCONTAINERS_LABEL, "true" - ); + public static final Map DEFAULT_LABELS = ImmutableMap.of(TESTCONTAINERS_LABEL, "true"); private static final DockerImageName TINY_IMAGE = DockerImageName.parse("alpine:3.14"); + private static DockerClientFactory instance; // Cached client configuration @@ -79,9 +80,7 @@ public class DockerClientFactory { private final boolean fileMountingSupported = checkMountableFile(); @VisibleForTesting - DockerClientFactory() { - - } + DockerClientFactory() {} public static DockerClient lazyClient() { return new DockerClientDelegate() { @@ -102,7 +101,7 @@ public String toString() { * * @return the singleton instance of DockerClientFactory */ - public synchronized static DockerClientFactory instance() { + public static synchronized DockerClientFactory instance() { if (instance == null) { instance = new DockerClientFactory(); } @@ -112,6 +111,7 @@ public synchronized static DockerClientFactory instance() { /** * Checks whether Docker is accessible and {@link #client()} is able to produce a client. + * * @return true if Docker is available, false if not. */ public synchronized boolean isDockerAvailable() { @@ -149,16 +149,11 @@ public String getRemoteDockerUnixSocketPath() { } URI dockerHost = getTransportConfig().getDockerHost(); - String path = "unix".equals(dockerHost.getScheme()) - ? dockerHost.getRawPath() - : "/var/run/docker.sock"; - return SystemUtils.IS_OS_WINDOWS - ? "/" + path - : path; + String path = "unix".equals(dockerHost.getScheme()) ? dockerHost.getRawPath() : "/var/run/docker.sock"; + return SystemUtils.IS_OS_WINDOWS ? "/" + path : path; } /** - * * @return a new initialized Docker client */ @Synchronized @@ -175,16 +170,16 @@ public DockerClient client() { final DockerClientProviderStrategy strategy = getOrInitializeStrategy(); - client = new DockerClientDelegate() { - - @Getter - final DockerClient dockerClient = strategy.getDockerClient(); + client = + new DockerClientDelegate() { + @Getter + final DockerClient dockerClient = strategy.getDockerClient(); - @Override - public void close() { - throw new IllegalStateException("You should never close the global DockerClient!"); - } - }; + @Override + public void close() { + throw new IllegalStateException("You should never close the global DockerClient!"); + } + }; log.info("Docker host IP address is {}", strategy.getDockerHostIpAddress()); Info dockerInfo = strategy.getInfo(); @@ -192,11 +187,22 @@ public void close() { Version version = client.versionCmd().exec(); log.debug("Docker version: {}", version.getRawValues()); activeApiVersion = version.getApiVersion(); - log.info("Connected to docker: \n" + - " Server Version: " + dockerInfo.getServerVersion() + "\n" + - " API Version: " + activeApiVersion + "\n" + - " Operating System: " + dockerInfo.getOperatingSystem() + "\n" + - " Total Memory: " + dockerInfo.getMemTotal() / (1024 * 1024) + " MB"); + log.info( + "Connected to docker: \n" + + " Server Version: " + + dockerInfo.getServerVersion() + + "\n" + + " API Version: " + + activeApiVersion + + "\n" + + " Operating System: " + + dockerInfo.getOperatingSystem() + + "\n" + + " Total Memory: " + + dockerInfo.getMemTotal() / + (1024 * 1024) + + " MB" + ); try { //noinspection deprecation @@ -225,7 +231,8 @@ public void close() { } private void checkDockerVersion(String dockerVersion) { - boolean versionIsSufficient = new ComparableVersion(dockerVersion).compareTo(new ComparableVersion("1.6.0")) >= 0; + boolean versionIsSufficient = new ComparableVersion(dockerVersion).compareTo(new ComparableVersion("1.6.0")) >= + 0; check("Docker server version should be at least 1.6.0", versionIsSufficient); } @@ -241,14 +248,22 @@ private void check(String message, boolean isSuccessful) { private boolean checkMountableFile() { DockerClient dockerClient = client(); - MountableFile mountableFile = MountableFile.forClasspathResource(ResourceReaper.class.getName().replace(".", "/") + ".class"); + MountableFile mountableFile = MountableFile.forClasspathResource( + ResourceReaper.class.getName().replace(".", "/") + ".class" + ); Volume volume = new Volume("/dummy"); try { return runInsideDocker( - createContainerCmd -> createContainerCmd.withBinds(new Bind(mountableFile.getResolvedPath(), volume, AccessMode.ro)), + createContainerCmd -> { + createContainerCmd.withBinds(new Bind(mountableFile.getResolvedPath(), volume, AccessMode.ro)); + }, (__, containerId) -> { - try (InputStream stream = dockerClient.copyArchiveFromContainerCmd(containerId, volume.getPath()).exec()) { + try ( + InputStream stream = dockerClient + .copyArchiveFromContainerCmd(containerId, volume.getPath()) + .exec() + ) { stream.read(); return true; } catch (Exception e) { @@ -293,16 +308,22 @@ public String dockerHostIpAddress() { return getOrInitializeStrategy().getDockerHostIpAddress(); } - public T runInsideDocker(Consumer createContainerCmdConsumer, BiFunction block) { + public T runInsideDocker( + Consumer createContainerCmdConsumer, + BiFunction block + ) { return runInsideDocker(TINY_IMAGE, createContainerCmdConsumer, block); } - T runInsideDocker(DockerImageName imageName, Consumer createContainerCmdConsumer, BiFunction block) { + T runInsideDocker( + DockerImageName imageName, + Consumer createContainerCmdConsumer, + BiFunction block + ) { RemoteDockerImage dockerImage = new RemoteDockerImage(imageName); HashMap labels = new HashMap<>(DEFAULT_LABELS); labels.putAll(ResourceReaper.instance().getLabels()); - CreateContainerCmd createContainerCmd = client.createContainerCmd(dockerImage.get()) - .withLabels(labels); + CreateContainerCmd createContainerCmd = client.createContainerCmd(dockerImage.get()).withLabels(labels); createContainerCmdConsumer.accept(createContainerCmd); String id = createContainerCmd.exec().getId(); diff --git a/core/src/main/java/org/testcontainers/Testcontainers.java b/core/src/main/java/org/testcontainers/Testcontainers.java index 0f83725c55b..ab567e1fda7 100644 --- a/core/src/main/java/org/testcontainers/Testcontainers.java +++ b/core/src/main/java/org/testcontainers/Testcontainers.java @@ -1,12 +1,11 @@ package org.testcontainers; -import java.util.Map; -import java.util.Map.Entry; - import lombok.experimental.UtilityClass; - import org.testcontainers.containers.PortForwardingContainer; +import java.util.Map; +import java.util.Map.Entry; + @UtilityClass public class Testcontainers { @@ -15,10 +14,10 @@ public void exposeHostPorts(int... ports) { PortForwardingContainer.INSTANCE.exposeHostPort(port); } } - + public void exposeHostPorts(Map ports) { - for(Entry entry : ports.entrySet()) { - PortForwardingContainer.INSTANCE.exposeHostPort(entry.getKey(), entry.getValue()); - } + for (Entry entry : ports.entrySet()) { + PortForwardingContainer.INSTANCE.exposeHostPort(entry.getKey(), entry.getValue()); + } } } diff --git a/core/src/main/java/org/testcontainers/UnstableAPI.java b/core/src/main/java/org/testcontainers/UnstableAPI.java index 21fd2c3176c..01221738dd4 100644 --- a/core/src/main/java/org/testcontainers/UnstableAPI.java +++ b/core/src/main/java/org/testcontainers/UnstableAPI.java @@ -11,11 +11,7 @@ * a stable API. */ @Retention(RetentionPolicy.SOURCE) -@Target({ - ElementType.TYPE, - ElementType.METHOD, - ElementType.FIELD, -}) +@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) @Documented public @interface UnstableAPI { } diff --git a/core/src/main/java/org/testcontainers/containers/BindMode.java b/core/src/main/java/org/testcontainers/containers/BindMode.java index 579dc4d5eca..5fc9c610165 100644 --- a/core/src/main/java/org/testcontainers/containers/BindMode.java +++ b/core/src/main/java/org/testcontainers/containers/BindMode.java @@ -6,7 +6,8 @@ * Possible modes for binding storage volumes. */ public enum BindMode { - READ_ONLY(AccessMode.ro), READ_WRITE(AccessMode.rw); + READ_ONLY(AccessMode.ro), + READ_WRITE(AccessMode.rw); public final AccessMode accessMode; diff --git a/core/src/main/java/org/testcontainers/containers/ComposeServiceWaitStrategyTarget.java b/core/src/main/java/org/testcontainers/containers/ComposeServiceWaitStrategyTarget.java index fbb2a7cee6e..81525710700 100644 --- a/core/src/main/java/org/testcontainers/containers/ComposeServiceWaitStrategyTarget.java +++ b/core/src/main/java/org/testcontainers/containers/ComposeServiceWaitStrategyTarget.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.Map; - /** * Class to provide a wait strategy target for services started through docker-compose */ @@ -21,15 +20,23 @@ class ComposeServiceWaitStrategyTarget implements WaitStrategyTarget { private final Container container; + private final GenericContainer proxyContainer; + private final DockerClient dockerClient; + @NonNull private Map mappedPorts; - @Getter(lazy=true) + + @Getter(lazy = true) private final InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(getContainerId()).exec(); - ComposeServiceWaitStrategyTarget(DockerClient dockerClient, Container container, GenericContainer proxyContainer, - @NonNull Map mappedPorts) { + ComposeServiceWaitStrategyTarget( + DockerClient dockerClient, + Container container, + GenericContainer proxyContainer, + @NonNull Map mappedPorts + ) { this.dockerClient = dockerClient; this.container = container; this.proxyContainer = proxyContainer; diff --git a/core/src/main/java/org/testcontainers/containers/Container.java b/core/src/main/java/org/testcontainers/containers/Container.java index 88fe4802945..7e6f492c284 100644 --- a/core/src/main/java/org/testcontainers/containers/Container.java +++ b/core/src/main/java/org/testcontainers/containers/Container.java @@ -1,17 +1,15 @@ package org.testcontainers.containers; -import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.model.Bind; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NonNull; import lombok.Value; -import org.testcontainers.DockerClientFactory; -import org.testcontainers.images.ImagePullPolicy; import org.testcontainers.containers.output.OutputFrame; import org.testcontainers.containers.startupcheck.StartupCheckStrategy; import org.testcontainers.containers.traits.LinkableContainer; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.images.ImagePullPolicy; import org.testcontainers.images.builder.Transferable; import org.testcontainers.utility.LogUtils; import org.testcontainers.utility.MountableFile; @@ -25,7 +23,6 @@ import java.util.function.Function; public interface Container> extends LinkableContainer, ContainerState { - /** * @return a reference to this container instance, cast to the expected generic type. */ @@ -40,8 +37,11 @@ default SELF self() { @Value @AllArgsConstructor(access = AccessLevel.MODULE) class ExecResult { + int exitCode; + String stdout; + String stderr; } @@ -298,7 +298,11 @@ default SELF withEnv(String key, Function, String> mapper) { * @param mode access mode for the file * @return this */ - default SELF withClasspathResourceMapping(final String resourcePath, final String containerPath, final BindMode mode) { + default SELF withClasspathResourceMapping( + final String resourcePath, + final String containerPath, + final BindMode mode + ) { withClasspathResourceMapping(resourcePath, containerPath, mode, SelinuxContext.NONE); return self(); } @@ -313,7 +317,12 @@ default SELF withClasspathResourceMapping(final String resourcePath, final Strin * @param selinuxContext selinux context argument to use for this file * @return this */ - SELF withClasspathResourceMapping(String resourcePath, String containerPath, BindMode mode, SelinuxContext selinuxContext); + SELF withClasspathResourceMapping( + String resourcePath, + String containerPath, + BindMode mode, + SelinuxContext selinuxContext + ); /** * Set the duration of waiting time until container treated as started. @@ -403,7 +412,6 @@ default void followOutput(Consumer consumer, OutputFrame.OutputType LogUtils.followOutput(getDockerClient(), getContainerId(), consumer, types); } - /** * Attach an output consumer at container startup, enabling stdout and stderr to be followed, waited on, etc. *

diff --git a/core/src/main/java/org/testcontainers/containers/ContainerFetchException.java b/core/src/main/java/org/testcontainers/containers/ContainerFetchException.java index 66aa1a493b0..66414434786 100644 --- a/core/src/main/java/org/testcontainers/containers/ContainerFetchException.java +++ b/core/src/main/java/org/testcontainers/containers/ContainerFetchException.java @@ -4,6 +4,7 @@ * Created by rnorth on 15/10/2015. */ public class ContainerFetchException extends RuntimeException { + public ContainerFetchException(String s, Exception e) { super(s, e); } diff --git a/core/src/main/java/org/testcontainers/containers/ContainerState.java b/core/src/main/java/org/testcontainers/containers/ContainerState.java index 51eb4daddde..b82b5448d2f 100644 --- a/core/src/main/java/org/testcontainers/containers/ContainerState.java +++ b/core/src/main/java/org/testcontainers/containers/ContainerState.java @@ -37,7 +37,6 @@ import java.util.stream.Collectors; public interface ContainerState { - String STATE_HEALTHY = "healthy"; /** @@ -109,7 +108,9 @@ default boolean isHealthy() { InspectContainerResponse inspectContainerResponse = getCurrentContainerInfo(); HealthState health = inspectContainerResponse.getState().getHealth(); if (health == null) { - throw new RuntimeException("This container's image does not have a healthcheck declared, so health cannot be determined. Either amend the image or use another approach to determine whether containers are healthy."); + throw new RuntimeException( + "This container's image does not have a healthcheck declared, so health cannot be determined. Either amend the image or use another approach to determine whether containers are healthy." + ); } return STATE_HEALTHY.equals(health.getStatus()); @@ -145,7 +146,10 @@ default Integer getFirstMappedPort() { * @return the port that the exposed port is mapped to, or null if it is not exposed */ default Integer getMappedPort(int originalPort) { - Preconditions.checkState(this.getContainerId() != null, "Mapped port can only be obtained after the container is started"); + Preconditions.checkState( + this.getContainerId() != null, + "Mapped port can only be obtained after the container is started" + ); Ports.Binding[] binding = new Ports.Binding[0]; final InspectContainerResponse containerInfo = this.getContainerInfo(); @@ -183,7 +187,8 @@ default List getPortBindings() { * @return the bound port numbers */ default List getBoundPortNumbers() { - return getPortBindings().stream() + return getPortBindings() + .stream() .map(PortBinding::parse) .map(PortBinding::getBinding) .map(Ports.Binding::getHostPortSpec) @@ -194,7 +199,6 @@ default List getBoundPortNumbers() { .collect(Collectors.toList()); } - /** * @return all log output from the container from start until the current instant (both stdout and stderr) */ @@ -228,7 +232,8 @@ default String getContainerId() { *

* @see ExecInContainerPattern#execInContainer(com.github.dockerjava.api.command.InspectContainerResponse, String...) */ - default Container.ExecResult execInContainer(String... command) throws UnsupportedOperationException, IOException, InterruptedException { + default Container.ExecResult execInContainer(String... command) + throws UnsupportedOperationException, IOException, InterruptedException { return execInContainer(StandardCharsets.UTF_8, command); } @@ -237,7 +242,8 @@ default Container.ExecResult execInContainer(String... command) throws Unsupport *

* @see ExecInContainerPattern#execInContainer(com.github.dockerjava.api.command.InspectContainerResponse, Charset, String...) */ - default Container.ExecResult execInContainer(Charset outputCharset, String... command) throws UnsupportedOperationException, IOException, InterruptedException { + default Container.ExecResult execInContainer(Charset outputCharset, String... command) + throws UnsupportedOperationException, IOException, InterruptedException { return ExecInContainerPattern.execInContainer(getDockerClient(), getContainerInfo(), outputCharset, command); } @@ -253,7 +259,9 @@ default void copyFileToContainer(MountableFile mountableFile, String containerPa if (containerPath.endsWith("/") && sourceFile.isFile()) { final Logger logger = LoggerFactory.getLogger(GenericContainer.class); - logger.warn("folder-like containerPath in copyFileToContainer is deprecated, please explicitly specify a file path"); + logger.warn( + "folder-like containerPath in copyFileToContainer is deprecated, please explicitly specify a file path" + ); copyFileToContainer((Transferable) mountableFile, containerPath + sourceFile.getName()); } else { copyFileToContainer((Transferable) mountableFile, containerPath); @@ -299,13 +307,17 @@ default void copyFileToContainer(Transferable transferable, String containerPath * @throws IOException if there's an issue communicating with Docker or receiving entry from TarArchiveInputStream * @throws InterruptedException if the thread waiting for the response is interrupted */ - default void copyFileFromContainer(String containerPath, String destinationPath) throws IOException, InterruptedException { - copyFileFromContainer(containerPath, inputStream -> { - try(FileOutputStream output = new FileOutputStream(destinationPath)) { - IOUtils.copy(inputStream, output); - return null; + default void copyFileFromContainer(String containerPath, String destinationPath) + throws IOException, InterruptedException { + copyFileFromContainer( + containerPath, + inputStream -> { + try (FileOutputStream output = new FileOutputStream(destinationPath)) { + IOUtils.copy(inputStream, output); + return null; + } } - }); + ); } /** @@ -315,7 +327,7 @@ default void copyFileFromContainer(String containerPath, String destinationPath) * @param function function that takes InputStream of the copied file */ @SneakyThrows - default T copyFileFromContainer(String containerPath, ThrowingFunction function) { + default T copyFileFromContainer(String containerPath, ThrowingFunction function) { if (getContainerId() == null) { throw new IllegalStateException("copyFileFromContainer can only be used when the Container is created."); } diff --git a/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java b/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java index 6f0a3a086b6..86a98586c7f 100644 --- a/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java +++ b/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java @@ -6,7 +6,9 @@ import com.github.dockerjava.transport.SSLConfig; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; import com.google.common.base.Splitter; +import com.google.common.base.Strings; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Uninterruptibles; @@ -57,42 +59,52 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Strings.isNullOrEmpty; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; -import static org.testcontainers.containers.BindMode.READ_WRITE; - /** * Container which launches Docker Compose, for the purposes of launching a defined set of containers. */ @Slf4j -public class DockerComposeContainer> extends FailureDetectingExternalResource implements Startable { +public class DockerComposeContainer> + extends FailureDetectingExternalResource + implements Startable { /** * Random identifier which will become part of spawned containers names, so we can shut them down */ private final String identifier; + private final List composeFiles; + private DockerComposeFiles dockerComposeFiles; + private final Map scalingPreferences = new HashMap<>(); + private DockerClient dockerClient; + private boolean localCompose; + private boolean pull = true; + private boolean build = false; + private Set options = new HashSet<>(); + private boolean tailChildContainers; private String project; private final AtomicInteger nextAmbassadorPort = new AtomicInteger(2000); + private final Map> ambassadorPortMappings = new ConcurrentHashMap<>(); + private final Map serviceInstanceMap = new ConcurrentHashMap<>(); + private final Map waitStrategyMap = new ConcurrentHashMap<>(); + private final SocatContainer ambassadorContainer = new SocatContainer(); + private final Map>> logConsumers = new ConcurrentHashMap<>(); private static final Object MUTEX = new Object(); @@ -104,6 +116,7 @@ public class DockerComposeContainer> e * necessarily to containers that are spawned by Compose itself) */ private Map env = new HashMap<>(); + private RemoveImages removeImages; @Deprecated @@ -148,13 +161,11 @@ public void starting(Description description) { @Override @Deprecated - protected void succeeded(Description description) { - } + protected void succeeded(Description description) {} @Override @Deprecated - protected void failed(Throwable e, Description description) { - } + protected void failed(Throwable e, Description description) {} @Override @Deprecated @@ -183,15 +194,23 @@ private void pullImages() { // Pull images using our docker client rather than compose itself, // (a) as a workaround for https://github.com/docker/compose/issues/5854, which prevents authenticated image pulls being possible when credential helpers are in use // (b) so that credential helper-based auth still works when compose is running from within a container - dockerComposeFiles.getDependencyImages() + dockerComposeFiles + .getDependencyImages() .forEach(imageName -> { try { - log.info("Preemptively checking local images for '{}', referenced via a compose file or transitive Dockerfile. If not available, it will be pulled.", imageName); + log.info( + "Preemptively checking local images for '{}', referenced via a compose file or transitive Dockerfile. If not available, it will be pulled.", + imageName + ); new RemoteDockerImage(DockerImageName.parse(imageName)) .withImageNameSubstitutor(ImageNameSubstitutor.noop()) .get(); } catch (Exception e) { - log.warn("Unable to pre-fetch an image ({}) depended upon by Docker Compose build - startup will continue but may fail. Exception message was: {}", imageName, e.getMessage()); + log.warn( + "Unable to pre-fetch an image ({}) depended upon by Docker Compose build - startup will continue but may fail. Exception message was: {}", + imageName, + e.getMessage() + ); } }); } @@ -203,18 +222,21 @@ public SELF withServices(@NonNull String... services) { private void createServices() { // services that have been explicitly requested to be started. If empty, all services should be started. - final String serviceNameArgs = Stream.concat( - services.stream(), // services that have been specified with `withServices` - scalingPreferences.keySet().stream() // services that are implicitly needed via `withScaledService` - ) + final String serviceNameArgs = Stream + .concat( + services.stream(), // services that have been specified with `withServices` + scalingPreferences.keySet().stream() // services that are implicitly needed via `withScaledService` + ) .distinct() - .collect(joining(" ")); + .collect(Collectors.joining(" ")); // Apply scaling for the services specified using `withScaledService` - final String scalingOptions = scalingPreferences.entrySet().stream() + final String scalingOptions = scalingPreferences + .entrySet() + .stream() .map(entry -> "--scale " + entry.getKey() + "=" + entry.getValue()) .distinct() - .collect(joining(" ")); + .collect(Collectors.joining(" ")); String command = optionsAsString() + "up -d"; @@ -222,11 +244,11 @@ private void createServices() { command += " --build"; } - if (!isNullOrEmpty(scalingOptions)) { + if (!Strings.isNullOrEmpty(scalingOptions)) { command += " " + scalingOptions; } - if (!isNullOrEmpty(serviceNameArgs)) { + if (!Strings.isNullOrEmpty(serviceNameArgs)) { command += " " + serviceNameArgs; } @@ -235,10 +257,8 @@ private void createServices() { } private String optionsAsString() { - String optionsString = options - .stream() - .collect(joining(" ")); - if (optionsString.length() !=0 ) { + String optionsString = options.stream().collect(Collectors.joining(" ")); + if (optionsString.length() != 0) { // ensures that there is a space between the options and 'up' if options are passed. return optionsString + " "; } else { @@ -252,15 +272,17 @@ private void waitUntilServiceStarted() { Set servicesToWaitFor = waitStrategyMap.keySet(); Set instantiatedServices = serviceInstanceMap.keySet(); - Sets.SetView missingServiceInstances = - Sets.difference(servicesToWaitFor, instantiatedServices); + Sets.SetView missingServiceInstances = Sets.difference(servicesToWaitFor, instantiatedServices); if (!missingServiceInstances.isEmpty()) { throw new IllegalStateException( - "Services named " + missingServiceInstances + " " + - "do not exist, but wait conditions have been defined " + - "for them. This might mean that you misspelled " + - "the service name when defining the wait condition."); + "Services named " + + missingServiceInstances + + " " + + "do not exist, but wait conditions have been defined " + + "for them. This might mean that you misspelled " + + "the service name when defining the wait condition." + ); } serviceInstanceMap.forEach(this::waitUntilServiceStarted); @@ -268,15 +290,21 @@ private void waitUntilServiceStarted() { private void createServiceInstance(Container container) { String serviceName = getServiceNameFromContainer(container); - final ComposeServiceWaitStrategyTarget containerInstance = new ComposeServiceWaitStrategyTarget(dockerClient, container, - ambassadorContainer, ambassadorPortMappings.getOrDefault(serviceName, new HashMap<>())); + final ComposeServiceWaitStrategyTarget containerInstance = new ComposeServiceWaitStrategyTarget( + dockerClient, + container, + ambassadorContainer, + ambassadorPortMappings.getOrDefault(serviceName, new HashMap<>()) + ); String containerId = containerInstance.getContainerId(); if (tailChildContainers) { followLogs(containerId, new Slf4jLogConsumer(log).withPrefix(container.getNames()[0])); } //follow logs using registered consumers for this service - logConsumers.getOrDefault(serviceName, Collections.emptyList()).forEach(consumer -> followLogs(containerId, consumer)); + logConsumers + .getOrDefault(serviceName, Collections.emptyList()) + .forEach(consumer -> followLogs(containerId, consumer)); serviceInstanceMap.putIfAbsent(serviceName, containerInstance); } @@ -294,8 +322,8 @@ private String getServiceNameFromContainer(Container container) { } private void runWithCompose(String cmd) { - checkNotNull(composeFiles); - checkArgument(!composeFiles.isEmpty(), "No docker compose file have been provided"); + Preconditions.checkNotNull(composeFiles); + Preconditions.checkArgument(!composeFiles.isEmpty(), "No docker compose file have been provided"); final DockerCompose dockerCompose; if (localCompose) { @@ -304,26 +332,24 @@ private void runWithCompose(String cmd) { dockerCompose = new ContainerisedDockerCompose(composeFiles, project); } - dockerCompose - .withCommand(cmd) - .withEnv(env) - .invoke(); + dockerCompose.withCommand(cmd).withEnv(env).invoke(); } private void registerContainersForShutdown() { - ResourceReaper.instance().registerLabelsFilterForCleanup(Collections.singletonMap( - "com.docker.compose.project", project - )); + ResourceReaper + .instance() + .registerLabelsFilterForCleanup(Collections.singletonMap("com.docker.compose.project", project)); } @VisibleForTesting List listChildContainers() { - return dockerClient.listContainersCmd() + return dockerClient + .listContainersCmd() .withShowAll(true) - .exec().stream() - .filter(container -> Arrays.stream(container.getNames()).anyMatch(name -> - name.startsWith("/" + project))) - .collect(toList()); + .exec() + .stream() + .filter(container -> Arrays.stream(container.getNames()).anyMatch(name -> name.startsWith("/" + project))) + .collect(Collectors.toList()); } private void startAmbassadorContainers() { @@ -345,7 +371,6 @@ public void stop() { cmd += " --rmi " + removeImages.dockerRemoveImagesType(); } runWithCompose(cmd); - } finally { project = randomProjectId(); } @@ -360,12 +385,16 @@ public DockerComposeContainer withExposedService(String serviceName, int instanc return withExposedService(serviceName + "_" + instance, servicePort); } - public DockerComposeContainer withExposedService(String serviceName, int instance, int servicePort, WaitStrategy waitStrategy) { + public DockerComposeContainer withExposedService( + String serviceName, + int instance, + int servicePort, + WaitStrategy waitStrategy + ) { return withExposedService(serviceName + "_" + instance, servicePort, waitStrategy); } public SELF withExposedService(String serviceName, int servicePort, @NonNull WaitStrategy waitStrategy) { - String serviceInstanceName = getServiceInstanceName(serviceName); /* @@ -384,7 +413,9 @@ public SELF withExposedService(String serviceName, int servicePort, @NonNull Wai // Ambassador container will be started together after docker compose has started int ambassadorPort = nextAmbassadorPort.getAndIncrement(); - ambassadorPortMappings.computeIfAbsent(serviceInstanceName, __ -> new ConcurrentHashMap<>()).put(servicePort, ambassadorPort); + ambassadorPortMappings + .computeIfAbsent(serviceInstanceName, __ -> new ConcurrentHashMap<>()) + .put(servicePort, ambassadorPort); ambassadorContainer.withTarget(ambassadorPort, serviceInstanceName, servicePort); ambassadorContainer.addLink(new FutureContainer(this.project + "_" + serviceInstanceName), serviceInstanceName); addWaitStrategy(serviceInstanceName, waitStrategy); @@ -405,8 +436,13 @@ private String getServiceInstanceName(String serviceName) { * The WaitAllStrategy uses an long timeout, because timeouts should be handled by the inner strategies. */ private void addWaitStrategy(String serviceInstanceName, @NonNull WaitStrategy waitStrategy) { - final WaitAllStrategy waitAllStrategy = waitStrategyMap.computeIfAbsent(serviceInstanceName, __ -> - new WaitAllStrategy(WaitAllStrategy.Mode.WITH_MAXIMUM_OUTER_TIMEOUT).withStartupTimeout(Duration.ofMinutes(30))); + final WaitAllStrategy waitAllStrategy = waitStrategyMap.computeIfAbsent( + serviceInstanceName, + __ -> { + return new WaitAllStrategy(WaitAllStrategy.Mode.WITH_MAXIMUM_OUTER_TIMEOUT) + .withStartupTimeout(Duration.ofMinutes(30)); + } + ); waitAllStrategy.withStrategy(waitStrategy); } @@ -452,9 +488,17 @@ public Integer getServicePort(String serviceName, Integer servicePort) { Map portMap = ambassadorPortMappings.get(getServiceInstanceName(serviceName)); if (portMap == null) { - throw new IllegalArgumentException("Could not get a port for '" + serviceName + "'. " + - "Testcontainers does not have an exposed port configured for '" + serviceName + "'. " + - "To fix, please ensure that the service '" + serviceName + "' has ports exposed using .withExposedService(...)"); + throw new IllegalArgumentException( + "Could not get a port for '" + + serviceName + + "'. " + + "Testcontainers does not have an exposed port configured for '" + + serviceName + + "'. " + + "To fix, please ensure that the service '" + + serviceName + + "' has ports exposed using .withExposedService(...)" + ); } else { return ambassadorContainer.getMappedPort(portMap.get(servicePort)); } @@ -517,7 +561,8 @@ public SELF withTailChildContainers(boolean tailChildContainers) { */ public SELF withLogConsumer(String serviceName, Consumer consumer) { String serviceInstanceName = getServiceInstanceName(serviceName); - final List> consumers = this.logConsumers.getOrDefault(serviceInstanceName, new ArrayList<>()); + final List> consumers = + this.logConsumers.getOrDefault(serviceInstanceName, new ArrayList<>()); consumers.add(consumer); this.logConsumers.putIfAbsent(serviceInstanceName, consumers); return self(); @@ -609,34 +654,39 @@ interface DockerCompose { class ContainerisedDockerCompose extends GenericContainer implements DockerCompose { public static final char UNIX_PATH_SEPERATOR = ':'; + public static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("docker/compose:1.29.2"); public ContainerisedDockerCompose(List composeFiles, String identifier) { - super(DEFAULT_IMAGE_NAME); addEnv(ENV_PROJECT_NAME, identifier); // Map the docker compose file into the container final File dockerComposeBaseFile = composeFiles.get(0); final String pwd = dockerComposeBaseFile.getAbsoluteFile().getParentFile().getAbsolutePath(); - final String containerPwd = convertToUnixFilesystemPath(pwd); + final String containerPwd = convertToUnixFilesystemPath(pwd); - final List absoluteDockerComposeFiles = composeFiles.stream() + final List absoluteDockerComposeFiles = composeFiles + .stream() .map(File::getAbsolutePath) .map(MountableFile::forHostPath) .map(MountableFile::getFilesystemPath) .map(this::convertToUnixFilesystemPath) - .collect(toList()); + .collect(Collectors.toList()); final String composeFileEnvVariableValue = Joiner.on(UNIX_PATH_SEPERATOR).join(absoluteDockerComposeFiles); // we always need the UNIX path separator logger().debug("Set env COMPOSE_FILE={}", composeFileEnvVariableValue); addEnv(ENV_COMPOSE_FILE, composeFileEnvVariableValue); - addFileSystemBind(pwd, containerPwd, READ_WRITE); + addFileSystemBind(pwd, containerPwd, BindMode.READ_WRITE); // Ensure that compose can access docker. Since the container is assumed to be running on the same machine // as the docker daemon, just mapping the docker control socket is OK. // As there seems to be a problem with mapping to the /var/run directory in certain environments (e.g. CircleCI) // we map the socket file outside of /var/run, as just /docker.sock - addFileSystemBind(DockerClientFactory.instance().getRemoteDockerUnixSocketPath(), "/docker.sock", READ_WRITE); + addFileSystemBind( + DockerClientFactory.instance().getRemoteDockerUnixSocketPath(), + "/docker.sock", + BindMode.READ_WRITE + ); addEnv("DOCKER_HOST", "unix:///docker.sock"); setStartupCheckStrategy(new IndefiniteWaitOneShotStartupCheckStrategy()); setWorkingDirectory(containerPwd); @@ -649,7 +699,8 @@ public void invoke() { this.followOutput(new Slf4jLogConsumer(logger())); // wait for the compose container to stop, which should only happen after it has spawned all the service containers - logger().info("Docker Compose container is running for command: {}", Joiner.on(" ").join(this.getCommandParts())); + logger() + .info("Docker Compose container is running for command: {}", Joiner.on(" ").join(this.getCommandParts())); while (this.isRunning()) { logger().trace("Compose container is still running"); Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS); @@ -658,7 +709,8 @@ public void invoke() { AuditLogger.doComposeLog(this.getCommandParts(), this.getEnv()); - final Integer exitCode = getDockerClient().inspectContainerCmd(getContainerId()) + final Integer exitCode = getDockerClient() + .inspectContainerCmd(getContainerId()) .exec() .getState() .getExitCode(); @@ -668,14 +720,13 @@ public void invoke() { "Containerised Docker Compose exited abnormally with code " + exitCode + " whilst running command: " + - StringUtils.join(this.getCommandParts(), ' ')); + StringUtils.join(this.getCommandParts(), ' ') + ); } } private String convertToUnixFilesystemPath(String path) { - return SystemUtils.IS_OS_WINDOWS - ? PathUtils.createMinGWPath(path).substring(1) - : path; + return SystemUtils.IS_OS_WINDOWS ? PathUtils.createMinGWPath(path).substring(1) : path; } } @@ -683,14 +734,20 @@ private String convertToUnixFilesystemPath(String path) { * Use local Docker Compose binary, if present. */ class LocalDockerCompose implements DockerCompose { + /** * Executable name for Docker Compose. */ - private static final String COMPOSE_EXECUTABLE = SystemUtils.IS_OS_WINDOWS ? "docker-compose.exe" : "docker-compose"; + private static final String COMPOSE_EXECUTABLE = SystemUtils.IS_OS_WINDOWS + ? "docker-compose.exe" + : "docker-compose"; private final List composeFiles; + private final String identifier; + private String cmd = ""; + private Map env = new HashMap<>(); public LocalDockerCompose(List composeFiles, String identifier) { @@ -719,7 +776,9 @@ static boolean executableExists() { public void invoke() { // bail out early if (!executableExists()) { - throw new ContainerLaunchException("Local Docker Compose not found. Is " + COMPOSE_EXECUTABLE + " on the PATH?"); + throw new ContainerLaunchException( + "Local Docker Compose not found. Is " + COMPOSE_EXECUTABLE + " on the PATH?" + ); } final Map environment = Maps.newHashMap(env); @@ -732,18 +791,23 @@ public void invoke() { environment.put("DOCKER_CERT_PATH", ((LocalDirectorySSLConfig) sslConfig).getDockerCertPath()); environment.put("DOCKER_TLS_VERIFY", "true"); } else { - logger().warn("Couldn't set DOCKER_CERT_PATH. `sslConfig` is present but it's not LocalDirectorySSLConfig."); + logger() + .warn( + "Couldn't set DOCKER_CERT_PATH. `sslConfig` is present but it's not LocalDirectorySSLConfig." + ); } } String dockerHost = transportConfig.getDockerHost().toString(); environment.put("DOCKER_HOST", dockerHost); - final Stream absoluteDockerComposeFilePaths = composeFiles.stream() + final Stream absoluteDockerComposeFilePaths = composeFiles + .stream() .map(File::getAbsolutePath) .map(Objects::toString); final String composeFileEnvVariableValue = absoluteDockerComposeFilePaths.collect( - joining(File.pathSeparator + "")); + Collectors.joining(File.pathSeparator + "") + ); logger().debug("Set env COMPOSE_FILE={}", composeFileEnvVariableValue); final File pwd = composeFiles.get(0).getAbsoluteFile().getParentFile().getAbsoluteFile(); @@ -751,12 +815,14 @@ public void invoke() { logger().info("Local Docker Compose is running command: {}", cmd); - final List command = Splitter.onPattern(" ") + final List command = Splitter + .onPattern(" ") .omitEmptyStrings() .splitToList(COMPOSE_EXECUTABLE + " " + cmd); try { - new ProcessExecutor().command(command) + new ProcessExecutor() + .command(command) .redirectOutput(Slf4jStream.of(logger()).asInfo()) .redirectError(Slf4jStream.of(logger()).asInfo()) // docker-compose will log pull information to stderr .environment(environment) @@ -765,11 +831,13 @@ public void invoke() { .executeNoTimeout(); logger().info("Docker Compose has finished running"); - } catch (InvalidExitValueException e) { - throw new ContainerLaunchException("Local Docker Compose exited abnormally with code " + - e.getExitValue() + " whilst running command: " + cmd); - + throw new ContainerLaunchException( + "Local Docker Compose exited abnormally with code " + + e.getExitValue() + + " whilst running command: " + + cmd + ); } catch (Exception e) { throw new ContainerLaunchException("Error running local Docker Compose command: " + cmd, e); } diff --git a/core/src/main/java/org/testcontainers/containers/DockerComposeFiles.java b/core/src/main/java/org/testcontainers/containers/DockerComposeFiles.java index 76754df5118..b96ebfb005e 100644 --- a/core/src/main/java/org/testcontainers/containers/DockerComposeFiles.java +++ b/core/src/main/java/org/testcontainers/containers/DockerComposeFiles.java @@ -33,7 +33,9 @@ private Map> mergeServiceDependencyImageNames() { } private Set getImageNames(Map> serviceToImageNames) { - return serviceToImageNames.values().stream() + return serviceToImageNames + .values() + .stream() .flatMap(Collection::stream) // Pass through DockerImageName to convert image names to canonical form (e.g. making implicit latest tag explicit) .map(DockerImageName::parse) diff --git a/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java b/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java index 0858476880f..fe641618cc4 100644 --- a/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java +++ b/core/src/main/java/org/testcontainers/containers/ExecInContainerPattern.java @@ -23,7 +23,6 @@ @Slf4j public class ExecInContainerPattern { - /** * * @deprecated use {@link #execInContainer(DockerClient, InspectContainerResponse, String...)} @@ -40,8 +39,11 @@ public Container.ExecResult execInContainer(InspectContainerResponse containerIn * @deprecated use {@link #execInContainer(DockerClient, InspectContainerResponse, Charset, String...)} */ @Deprecated - public Container.ExecResult execInContainer(InspectContainerResponse containerInfo, Charset outputCharset, String... command) - throws UnsupportedOperationException, IOException, InterruptedException { + public Container.ExecResult execInContainer( + InspectContainerResponse containerInfo, + Charset outputCharset, + String... command + ) throws UnsupportedOperationException, IOException, InterruptedException { DockerClient dockerClient = DockerClientFactory.instance().client(); return execInContainer(dockerClient, containerInfo, outputCharset, command); } @@ -55,8 +57,11 @@ public Container.ExecResult execInContainer(InspectContainerResponse containerIn * @param command the command to execute * @see #execInContainer(DockerClient, InspectContainerResponse, Charset, String...) */ - public Container.ExecResult execInContainer(DockerClient dockerClient, InspectContainerResponse containerInfo, String... command) - throws UnsupportedOperationException, IOException, InterruptedException { + public Container.ExecResult execInContainer( + DockerClient dockerClient, + InspectContainerResponse containerInfo, + String... command + ) throws UnsupportedOperationException, IOException, InterruptedException { return execInContainer(dockerClient, containerInfo, StandardCharsets.UTF_8, command); } @@ -74,13 +79,17 @@ public Container.ExecResult execInContainer(DockerClient dockerClient, InspectCo * @throws InterruptedException if the thread waiting for the response is interrupted * @throws UnsupportedOperationException if the docker daemon you're connecting to doesn't support "exec". */ - public Container.ExecResult execInContainer(DockerClient dockerClient, InspectContainerResponse containerInfo, Charset outputCharset, String... command) - throws UnsupportedOperationException, IOException, InterruptedException { + public Container.ExecResult execInContainer( + DockerClient dockerClient, + InspectContainerResponse containerInfo, + Charset outputCharset, + String... command + ) throws UnsupportedOperationException, IOException, InterruptedException { if (!TestEnvironment.dockerExecutionDriverSupportsExec()) { // at time of writing, this is the expected result in CircleCI. throw new UnsupportedOperationException( - "Your docker daemon is running the \"lxc\" driver, which doesn't support \"docker exec\"."); - + "Your docker daemon is running the \"lxc\" driver, which doesn't support \"docker exec\"." + ); } if (!isRunning(containerInfo)) { @@ -91,8 +100,12 @@ public Container.ExecResult execInContainer(DockerClient dockerClient, InspectCo String containerName = containerInfo.getName(); log.debug("{}: Running \"exec\" command: {}", containerName, String.join(" ", command)); - final ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId) - .withAttachStdout(true).withAttachStderr(true).withCmd(command).exec(); + final ExecCreateCmdResponse execCreateCmdResponse = dockerClient + .execCreateCmd(containerId) + .withAttachStdout(true) + .withAttachStderr(true) + .withCmd(command) + .exec(); final ToStringConsumer stdoutConsumer = new ToStringConsumer(); final ToStringConsumer stderrConsumer = new ToStringConsumer(); @@ -108,7 +121,8 @@ public Container.ExecResult execInContainer(DockerClient dockerClient, InspectCo final Container.ExecResult result = new Container.ExecResult( exitCode, stdoutConsumer.toString(outputCharset), - stderrConsumer.toString(outputCharset)); + stderrConsumer.toString(outputCharset) + ); log.trace("{}: stdout: {}", containerName, result.getStdout()); log.trace("{}: stderr: {}", containerName, result.getStderr()); diff --git a/core/src/main/java/org/testcontainers/containers/FailureDetectingExternalResource.java b/core/src/main/java/org/testcontainers/containers/FailureDetectingExternalResource.java index 29a032d320b..71344267d32 100644 --- a/core/src/main/java/org/testcontainers/containers/FailureDetectingExternalResource.java +++ b/core/src/main/java/org/testcontainers/containers/FailureDetectingExternalResource.java @@ -16,13 +16,12 @@ * figures). */ public class FailureDetectingExternalResource implements TestRule { + @Override public Statement apply(Statement base, Description description) { - return new Statement() { @Override public void evaluate() throws Throwable { - List errors = new ArrayList(); try { @@ -41,16 +40,11 @@ public void evaluate() throws Throwable { }; } - protected void starting(Description description) { - - } + protected void starting(Description description) {} - protected void succeeded(Description description) { - } + protected void succeeded(Description description) {} - protected void failed(Throwable e, Description description) { - } + protected void failed(Throwable e, Description description) {} - protected void finished(Description description) { - } + protected void finished(Description description) {} } diff --git a/core/src/main/java/org/testcontainers/containers/FixedHostPortGenericContainer.java b/core/src/main/java/org/testcontainers/containers/FixedHostPortGenericContainer.java index 6477c28042e..db610ad57c2 100644 --- a/core/src/main/java/org/testcontainers/containers/FixedHostPortGenericContainer.java +++ b/core/src/main/java/org/testcontainers/containers/FixedHostPortGenericContainer.java @@ -11,7 +11,8 @@ *

Callers are responsible for ensuring that this fixed port is actually available; failure will occur if it is * not available - which could manifest as flaky or unstable tests.

*/ -public class FixedHostPortGenericContainer> extends GenericContainer { +public class FixedHostPortGenericContainer> + extends GenericContainer { /** * @deprecated it is highly recommended that {@link FixedHostPortGenericContainer} not be used, as it risks port conflicts. @@ -28,7 +29,6 @@ public FixedHostPortGenericContainer(@NotNull String dockerImageName) { * @return this container */ public SELF withFixedExposedPort(int hostPort, int containerPort) { - return withFixedExposedPort(hostPort, containerPort, InternetProtocol.TCP); } @@ -40,7 +40,6 @@ public SELF withFixedExposedPort(int hostPort, int containerPort) { * @return this container */ public SELF withFixedExposedPort(int hostPort, int containerPort, InternetProtocol protocol) { - super.addFixedExposedPort(hostPort, containerPort, protocol); return self(); diff --git a/core/src/main/java/org/testcontainers/containers/FutureContainer.java b/core/src/main/java/org/testcontainers/containers/FutureContainer.java index b2269b534c1..28cfbfff6c9 100644 --- a/core/src/main/java/org/testcontainers/containers/FutureContainer.java +++ b/core/src/main/java/org/testcontainers/containers/FutureContainer.java @@ -8,5 +8,6 @@ */ @Data public class FutureContainer implements LinkableContainer { + private final String containerName; } diff --git a/core/src/main/java/org/testcontainers/containers/GenericContainer.java b/core/src/main/java/org/testcontainers/containers/GenericContainer.java index 4e5e682738d..7163ea40a93 100644 --- a/core/src/main/java/org/testcontainers/containers/GenericContainer.java +++ b/core/src/main/java/org/testcontainers/containers/GenericContainer.java @@ -20,6 +20,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; import com.google.common.hash.Hashing; import lombok.AccessLevel; import lombok.Data; @@ -27,7 +28,6 @@ import lombok.NonNull; import lombok.Setter; import lombok.SneakyThrows; -import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.jetbrains.annotations.NotNull; @@ -56,6 +56,7 @@ import org.testcontainers.lifecycle.TestDescription; import org.testcontainers.lifecycle.TestLifecycleAware; import org.testcontainers.utility.Base58; +import org.testcontainers.utility.CommandLine; import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.DockerLoggerFactory; import org.testcontainers.utility.DockerMachineClient; @@ -66,12 +67,10 @@ import org.testcontainers.utility.TestcontainersConfiguration; import java.io.File; -import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.UndeclaredThrowableException; import java.nio.charset.Charset; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; @@ -101,17 +100,15 @@ import java.util.zip.Adler32; import java.util.zip.Checksum; -import static com.google.common.collect.Lists.newArrayList; import static org.awaitility.Awaitility.await; -import static org.testcontainers.utility.CommandLine.runShellCommand; /** * Base class for that allows a container to be launched and controlled. */ @Data public class GenericContainer> - extends FailureDetectingExternalResource - implements Container, AutoCloseable, WaitStrategyTarget, Startable { + extends FailureDetectingExternalResource + implements Container, AutoCloseable, WaitStrategyTarget, Startable { private static final Charset UTF8 = Charset.forName("UTF-8"); @@ -142,9 +139,7 @@ public class GenericContainer> private Network network; @NonNull - private List networkAliases = new ArrayList<>(Arrays.asList( - "tc-" + Base58.randomString(8) - )); + private List networkAliases = new ArrayList<>(Arrays.asList("tc-" + Base58.randomString(8))); @NonNull private RemoteDockerImage image; @@ -228,6 +223,7 @@ public class GenericContainer> private final Set> createContainerCmdModifiers = new LinkedHashSet<>(); private static final Set AVAILABLE_IMAGE_NAME_CACHE = new HashSet<>(); + private static final RateLimiter DOCKER_CLIENT_RATE_LIMITER = RateLimiterBuilder .newBuilder() .withRate(1, TimeUnit.SECONDS) @@ -315,7 +311,7 @@ public String getContainerId() { * Starts the container using docker, pulling an image if necessary. */ @Override - @SneakyThrows({InterruptedException.class, ExecutionException.class}) + @SneakyThrows({ InterruptedException.class, ExecutionException.class }) public void start() { if (containerId != null) { return; @@ -335,12 +331,20 @@ protected void doStart() { logger().debug("Starting container: {}", getDockerImageName()); AtomicInteger attempt = new AtomicInteger(0); - Unreliables.retryUntilSuccess(startupAttempts, () -> { - logger().debug("Trying to start container: {} (attempt {}/{})", getDockerImageName(), attempt.incrementAndGet(), startupAttempts); - tryStart(startedAt); - return true; - }); - + Unreliables.retryUntilSuccess( + startupAttempts, + () -> { + logger() + .debug( + "Trying to start container: {} (attempt {}/{})", + getDockerImageName(), + attempt.incrementAndGet(), + startupAttempts + ); + tryStart(startedAt); + return true; + } + ); } catch (Exception e) { throw new ContainerLaunchException("Container startup failed", e); } @@ -383,10 +387,9 @@ private void tryStart(Instant startedAt) { } if (TestcontainersConfiguration.getInstance().environmentSupportsReuse()) { - createCommand.getLabels().put( - COPIED_FILES_HASH_LABEL, - Long.toHexString(hashCopiedFiles().getValue()) - ); + createCommand + .getLabels() + .put(COPIED_FILES_HASH_LABEL, Long.toHexString(hashCopiedFiles().getValue())); String hash = hash(createCommand); @@ -402,12 +405,13 @@ private void tryStart(Instant startedAt) { } reusable = true; } else { - logger().warn( - "" + + logger() + .warn( + "" + "Reuse was requested but the environment does not support the reuse of containers\n" + "To enable reuse of containers, you must set 'testcontainers.reuse.enable=true' in a file located at {}", - Paths.get(System.getProperty("user.home"), ".testcontainers.properties") - ); + Paths.get(System.getProperty("user.home"), ".testcontainers.properties") + ); reusable = false; } } else { @@ -443,27 +447,28 @@ private void tryStart(Instant startedAt) { this.logConsumers.forEach(this::followOutput); // Wait until inspect container returns the mapped ports - containerInfo = await() - .atMost(5, TimeUnit.SECONDS) - .pollInterval(DynamicPollInterval.ofMillis(50)) - .pollInSameThread() - .until( - () -> dockerClient.inspectContainerCmd(containerId).exec(), - inspectContainerResponse -> { - Set exposedAndMappedPorts = inspectContainerResponse - .getNetworkSettings() - .getPorts() - .getBindings() - .entrySet() - .stream() - .filter(it -> Objects.nonNull(it.getValue())) // filter out exposed but not yet mapped - .map(Entry::getKey) - .map(ExposedPort::getPort) - .collect(Collectors.toSet()); - - return exposedAndMappedPorts.containsAll(exposedPorts); - } - ); + containerInfo = + await() + .atMost(5, TimeUnit.SECONDS) + .pollInterval(DynamicPollInterval.ofMillis(50)) + .pollInSameThread() + .until( + () -> dockerClient.inspectContainerCmd(containerId).exec(), + inspectContainerResponse -> { + Set exposedAndMappedPorts = inspectContainerResponse + .getNetworkSettings() + .getPorts() + .getBindings() + .entrySet() + .stream() + .filter(it -> Objects.nonNull(it.getValue())) // filter out exposed but not yet mapped + .map(Entry::getKey) + .map(ExposedPort::getPort) + .collect(Collectors.toSet()); + + return exposedAndMappedPorts.containsAll(exposedPorts); + } + ); // Tell subclasses that we're starting containerIsStarting(containerInfo, reused); @@ -541,9 +546,11 @@ private void tryStart(Instant startedAt) { @VisibleForTesting Checksum hashCopiedFiles() { Checksum checksum = new Adler32(); - Stream.of(copyToFileContainerPathMap, copyToTransferableContainerPathMap) + Stream + .of(copyToFileContainerPathMap, copyToTransferableContainerPathMap) .flatMap(it -> it.entrySet().stream()) - .sorted(Entry.comparingByValue()).forEach(entry -> { + .sorted(Entry.comparingByValue()) + .forEach(entry -> { byte[] pathBytes = entry.getValue().getBytes(); // Add path to the hash checksum.update(pathBytes, 0, pathBytes.length); @@ -558,7 +565,8 @@ Checksum hashCopiedFiles() { final String hash(CreateContainerCmd createCommand) { DefaultDockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder().build(); - byte[] commandJson = dockerClientConfig.getObjectMapper() + byte[] commandJson = dockerClientConfig + .getObjectMapper() .copy() .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY) .enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS) @@ -571,7 +579,8 @@ final String hash(CreateContainerCmd createCommand) { @VisibleForTesting Optional findContainerForReuse(String hash) { // TODO locking - return dockerClient.listContainersCmd() + return dockerClient + .listContainersCmd() .withLabelFilter(ImmutableMap.of(HASH_LABEL, hash)) .withLimit(1) .withStatusFilter(Arrays.asList("running")) @@ -596,11 +605,14 @@ private HostConfig buildHostConfig() { } private void connectToPortForwardingNetwork(String networkMode) { - PortForwardingContainer.INSTANCE.getNetwork().map(ContainerNetwork::getNetworkID).ifPresent(networkId -> { - if (!Arrays.asList(networkId, "none", "host").contains(networkMode)) { - dockerClient.connectToNetworkCmd().withContainerId(containerId).withNetworkId(networkId).exec(); - } - }); + PortForwardingContainer.INSTANCE + .getNetwork() + .map(ContainerNetwork::getNetworkID) + .ifPresent(networkId -> { + if (!Arrays.asList(networkId, "none", "host").contains(networkMode)) { + dockerClient.connectToNetworkCmd().withContainerId(containerId).withNetworkId(networkId).exec(); + } + }); } /** @@ -608,7 +620,6 @@ private void connectToPortForwardingNetwork(String networkMode) { */ @Override public void stop() { - if (containerId == null) { return; } @@ -651,35 +662,40 @@ protected Path createVolumeDirectory(boolean temporary) { Path directory = new File(".tmp-volume-" + UUID.randomUUID()).toPath(); PathUtils.mkdirp(directory); - if (temporary) Runtime.getRuntime().addShutdownHook(new Thread(DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, () -> { - PathUtils.recursiveDeleteDir(directory); - })); + if (temporary) { + Runtime + .getRuntime() + .addShutdownHook( + new Thread( + DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, + () -> { + PathUtils.recursiveDeleteDir(directory); + } + ) + ); + } return directory; } - protected void configure() { - } + protected void configure() {} - @SuppressWarnings({"EmptyMethod", "UnusedParameters"}) - protected void containerIsCreated(String containerId) { - } + @SuppressWarnings({ "EmptyMethod", "UnusedParameters" }) + protected void containerIsCreated(String containerId) {} - @SuppressWarnings({"EmptyMethod", "UnusedParameters"}) - protected void containerIsStarting(InspectContainerResponse containerInfo) { - } + @SuppressWarnings({ "EmptyMethod", "UnusedParameters" }) + protected void containerIsStarting(InspectContainerResponse containerInfo) {} - @SuppressWarnings({"EmptyMethod", "UnusedParameters"}) + @SuppressWarnings({ "EmptyMethod", "UnusedParameters" }) @UnstableAPI protected void containerIsStarting(InspectContainerResponse containerInfo, boolean reused) { containerIsStarting(containerInfo); } - @SuppressWarnings({"EmptyMethod", "UnusedParameters"}) - protected void containerIsStarted(InspectContainerResponse containerInfo) { - } + @SuppressWarnings({ "EmptyMethod", "UnusedParameters" }) + protected void containerIsStarted(InspectContainerResponse containerInfo) {} - @SuppressWarnings({"EmptyMethod", "UnusedParameters"}) + @SuppressWarnings({ "EmptyMethod", "UnusedParameters" }) @UnstableAPI protected void containerIsStarted(InspectContainerResponse containerInfo, boolean reused) { containerIsStarted(containerInfo); @@ -690,18 +706,16 @@ protected void containerIsStarted(InspectContainerResponse containerInfo, boolea * Warning! This hook won't be executed if the container is terminated during * the JVM's shutdown hook or by Ryuk. */ - @SuppressWarnings({"EmptyMethod", "UnusedParameters"}) - protected void containerIsStopping(InspectContainerResponse containerInfo) { - } + @SuppressWarnings({ "EmptyMethod", "UnusedParameters" }) + protected void containerIsStopping(InspectContainerResponse containerInfo) {} /** * A hook that is executed after the container is stopped with {@link #stop()}. * Warning! This hook won't be executed if the container is terminated during * the JVM's shutdown hook or by Ryuk. */ - @SuppressWarnings({"EmptyMethod", "UnusedParameters"}) - protected void containerIsStopped(InspectContainerResponse containerInfo) { - } + @SuppressWarnings({ "EmptyMethod", "UnusedParameters" }) + protected void containerIsStopped(InspectContainerResponse containerInfo) {} /** * @return the port on which to check if the container is ready @@ -772,35 +786,36 @@ private void applyConfiguration(CreateContainerCmd createCommand) { createCommand.withCmd(commandParts); } - String[] envArray = env.entrySet().stream() - .filter(it -> it.getValue() != null) - .map(it -> it.getKey() + "=" + it.getValue()) - .toArray(String[]::new); + String[] envArray = env + .entrySet() + .stream() + .filter(it -> it.getValue() != null) + .map(it -> it.getKey() + "=" + it.getValue()) + .toArray(String[]::new); createCommand.withEnv(envArray); - boolean shouldCheckFileMountingSupport = binds.size() > 0 && !TestcontainersConfiguration.getInstance().isDisableChecks(); + boolean shouldCheckFileMountingSupport = + binds.size() > 0 && !TestcontainersConfiguration.getInstance().isDisableChecks(); if (shouldCheckFileMountingSupport) { if (!DockerClientFactory.instance().isFileMountingSupported()) { - logger().warn( - "Unable to mount a file from test host into a running container. " + + logger() + .warn( + "Unable to mount a file from test host into a running container. " + "This may be a misconfiguration or limitation of your Docker environment. " + "Some features might not work." - ); + ); } } - Bind[] bindsArray = binds.stream() - .toArray(Bind[]::new); + Bind[] bindsArray = binds.stream().toArray(Bind[]::new); createCommand.withBinds(bindsArray); - VolumesFrom[] volumesFromsArray = volumesFroms.stream() - .toArray(VolumesFrom[]::new); + VolumesFrom[] volumesFromsArray = volumesFroms.stream().toArray(VolumesFrom[]::new); createCommand.withVolumesFrom(volumesFromsArray); Set allLinks = new HashSet<>(); Set allLinkedContainerNetworks = new HashSet<>(); for (Entry linkEntries : linkedContainers.entrySet()) { - String alias = linkEntries.getKey(); LinkableContainer linkableContainer = linkEntries.getValue(); @@ -808,9 +823,11 @@ private void applyConfiguration(CreateContainerCmd createCommand) { allLinks.addAll(links); if (allLinks.size() == 0) { - throw new ContainerLaunchException("Aborting attempt to link to container " + - linkableContainer.getContainerName() + - " as it is not running"); + throw new ContainerLaunchException( + "Aborting attempt to link to container " + + linkableContainer.getContainerName() + + " as it is not running" + ); } Set linkedContainerNetworks = findAllNetworksForLinkedContainers(linkableContainer); @@ -821,9 +838,12 @@ private void applyConfiguration(CreateContainerCmd createCommand) { allLinkedContainerNetworks.remove("bridge"); if (allLinkedContainerNetworks.size() > 1) { - logger().warn("Container needs to be on more than one custom network to link to other " + - "containers - this is not currently supported. Required networks are: {}", - allLinkedContainerNetworks); + logger() + .warn( + "Container needs to be on more than one custom network to link to other " + + "containers - this is not currently supported. Required networks are: {}", + allLinkedContainerNetworks + ); } Optional networkForLinks = allLinkedContainerNetworks.stream().findFirst(); @@ -835,12 +855,13 @@ private void applyConfiguration(CreateContainerCmd createCommand) { if (hostAccessible) { PortForwardingContainer.INSTANCE.start(); } - PortForwardingContainer.INSTANCE.getNetwork().ifPresent(it -> { - withExtraHost(INTERNAL_HOST_HOSTNAME, it.getIpAddress()); - }); + PortForwardingContainer.INSTANCE + .getNetwork() + .ifPresent(it -> { + withExtraHost(INTERNAL_HOST_HOSTNAME, it.getIpAddress()); + }); - String[] extraHostsArray = extraHosts.stream() - .toArray(String[]::new); + String[] extraHostsArray = extraHosts.stream().toArray(String[]::new); createCommand.withExtraHosts(extraHostsArray); if (network != null) { @@ -870,23 +891,29 @@ private void applyConfiguration(CreateContainerCmd createCommand) { } private Set findLinksFromThisContainer(String alias, LinkableContainer linkableContainer) { - return dockerClient.listContainersCmd() - .withStatusFilter(Arrays.asList("running")) - .exec().stream() - .flatMap(container -> Stream.of(container.getNames())) - .filter(name -> name.endsWith(linkableContainer.getContainerName())) - .map(name -> new Link(name, alias)) - .collect(Collectors.toSet()); + return dockerClient + .listContainersCmd() + .withStatusFilter(Arrays.asList("running")) + .exec() + .stream() + .flatMap(container -> Stream.of(container.getNames())) + .filter(name -> name.endsWith(linkableContainer.getContainerName())) + .map(name -> new Link(name, alias)) + .collect(Collectors.toSet()); } private Set findAllNetworksForLinkedContainers(LinkableContainer linkableContainer) { - return dockerClient.listContainersCmd().exec().stream() - .filter(container -> container.getNames()[0].endsWith(linkableContainer.getContainerName())) - .filter(container -> container.getNetworkSettings() != null && - container.getNetworkSettings().getNetworks() != null) - .flatMap(container -> container.getNetworkSettings().getNetworks().keySet().stream()) - .distinct() - .collect(Collectors.toSet()); + return dockerClient + .listContainersCmd() + .exec() + .stream() + .filter(container -> container.getNames()[0].endsWith(linkableContainer.getContainerName())) + .filter(container -> { + return container.getNetworkSettings() != null && container.getNetworkSettings().getNetworks() != null; + }) + .flatMap(container -> container.getNetworkSettings().getNetworks().keySet().stream()) + .distinct() + .collect(Collectors.toSet()); } /** @@ -953,19 +980,12 @@ public Map getEnvMap() { */ @Override public List getEnv() { - return env.entrySet().stream() - .map(it -> it.getKey() + "=" + it.getValue()) - .collect(Collectors.toList()); + return env.entrySet().stream().map(it -> it.getKey() + "=" + it.getValue()).collect(Collectors.toList()); } @Override public void setEnv(List env) { - this.env = env.stream() - .map(it -> it.split("=")) - .collect(Collectors.toMap( - it -> it[0], - it -> it[1] - )); + this.env = env.stream().map(it -> it.split("=")).collect(Collectors.toMap(it -> it[0], it -> it[1])); } /** @@ -980,14 +1000,25 @@ public void addEnv(String key, String value) { * {@inheritDoc} */ @Override - public void addFileSystemBind(final String hostPath, final String containerPath, final BindMode mode, final SelinuxContext selinuxContext) { + public void addFileSystemBind( + final String hostPath, + final String containerPath, + final BindMode mode, + final SelinuxContext selinuxContext + ) { if (SystemUtils.IS_OS_WINDOWS && hostPath.startsWith("/")) { // e.g. Docker socket mount binds.add(new Bind(hostPath, new Volume(containerPath), mode.accessMode, selinuxContext.selContext)); - } else { final MountableFile mountableFile = MountableFile.forHostPath(hostPath); - binds.add(new Bind(mountableFile.getResolvedPath(), new Volume(containerPath), mode.accessMode, selinuxContext.selContext)); + binds.add( + new Bind( + mountableFile.getResolvedPath(), + new Volume(containerPath), + mode.accessMode, + selinuxContext.selContext + ) + ); } } @@ -1090,9 +1121,8 @@ protected void finished(Description description) { */ @Override public SELF withExposedPorts(Integer... ports) { - this.setExposedPorts(newArrayList(ports)); + this.setExposedPorts(Lists.newArrayList(ports)); return self(); - } /** @@ -1218,7 +1248,11 @@ public SELF withImagePullPolicy(ImagePullPolicy imagePullPolicy) { * {@inheritDoc} */ @Override - public SELF withClasspathResourceMapping(final String resourcePath, final String containerPath, final BindMode mode) { + public SELF withClasspathResourceMapping( + final String resourcePath, + final String containerPath, + final BindMode mode + ) { return withClasspathResourceMapping(resourcePath, containerPath, mode, SelinuxContext.NONE); } @@ -1226,7 +1260,12 @@ public SELF withClasspathResourceMapping(final String resourcePath, final String * {@inheritDoc} */ @Override - public SELF withClasspathResourceMapping(final String resourcePath, final String containerPath, final BindMode mode, final SelinuxContext selinuxContext) { + public SELF withClasspathResourceMapping( + final String resourcePath, + final String containerPath, + final BindMode mode, + final SelinuxContext selinuxContext + ) { final MountableFile mountableFile = MountableFile.forClasspathResource(resourcePath); if (mode == BindMode.READ_ONLY && selinuxContext == SelinuxContext.NONE) { @@ -1346,23 +1385,33 @@ public String getTestHostIpAddress() { throw new IllegalStateException("Could not find a default docker-machine instance"); } - String sshConnectionString = runShellCommand("docker-machine", "ssh", defaultMachine.get(), "echo $SSH_CONNECTION").trim(); + String sshConnectionString = CommandLine + .runShellCommand("docker-machine", "ssh", defaultMachine.get(), "echo $SSH_CONNECTION") + .trim(); if (Strings.isNullOrEmpty(sshConnectionString)) { - throw new IllegalStateException("Could not obtain SSH_CONNECTION environment variable for docker machine " + defaultMachine.get()); + throw new IllegalStateException( + "Could not obtain SSH_CONNECTION environment variable for docker machine " + + defaultMachine.get() + ); } String[] sshConnectionParts = sshConnectionString.split("\\s"); if (sshConnectionParts.length != 4) { - throw new IllegalStateException("Unexpected pattern for SSH_CONNECTION for docker machine - expected 'IP PORT IP PORT' pattern but found '" + sshConnectionString + "'"); + throw new IllegalStateException( + "Unexpected pattern for SSH_CONNECTION for docker machine - expected 'IP PORT IP PORT' pattern but found '" + + sshConnectionString + + "'" + ); } return sshConnectionParts[0]; } catch (Exception e) { throw new RuntimeException(e); } - } else { - throw new UnsupportedOperationException("getTestHostIpAddress() is only implemented for docker-machine right now"); + throw new UnsupportedOperationException( + "getTestHostIpAddress() is only implemented for docker-machine right now" + ); } } diff --git a/core/src/main/java/org/testcontainers/containers/InternetProtocol.java b/core/src/main/java/org/testcontainers/containers/InternetProtocol.java index 0df0480a1bf..6574a517cdf 100644 --- a/core/src/main/java/org/testcontainers/containers/InternetProtocol.java +++ b/core/src/main/java/org/testcontainers/containers/InternetProtocol.java @@ -4,7 +4,6 @@ * The IP protocols supported by Docker. */ public enum InternetProtocol { - TCP, UDP; diff --git a/core/src/main/java/org/testcontainers/containers/Network.java b/core/src/main/java/org/testcontainers/containers/Network.java index 046133815b6..fac7beff638 100644 --- a/core/src/main/java/org/testcontainers/containers/Network.java +++ b/core/src/main/java/org/testcontainers/containers/Network.java @@ -18,7 +18,6 @@ import java.util.function.Consumer; public interface Network extends AutoCloseable, TestRule { - Network SHARED = new NetworkImpl(false, null, Collections.emptySet(), null) { @Override public void close() { diff --git a/core/src/main/java/org/testcontainers/containers/ParsedDockerComposeFile.java b/core/src/main/java/org/testcontainers/containers/ParsedDockerComposeFile.java index e9457ba92bd..abb6deaab3d 100644 --- a/core/src/main/java/org/testcontainers/containers/ParsedDockerComposeFile.java +++ b/core/src/main/java/org/testcontainers/containers/ParsedDockerComposeFile.java @@ -26,7 +26,9 @@ class ParsedDockerComposeFile { private final Map composeFileContent; + private final String composeFileName; + private final File composeFile; @Getter @@ -57,14 +59,20 @@ private void parseAndValidate() { final Map servicesMap; if (composeFileContent.containsKey("version")) { if ("2.0".equals(composeFileContent.get("version"))) { - log.warn("Testcontainers may not be able to clean up networks spawned using Docker Compose v2.0 files. " + + log.warn( + "Testcontainers may not be able to clean up networks spawned using Docker Compose v2.0 files. " + "Please see https://github.com/testcontainers/moby-ryuk/issues/2, and specify 'version: \"2.1\"' or " + - "higher in {}", composeFileName); + "higher in {}", + composeFileName + ); } final Object servicesElement = composeFileContent.get("services"); if (servicesElement == null) { - log.debug("Compose file {} has an unknown format: 'version' is set but 'services' is not defined", composeFileName); + log.debug( + "Compose file {} has an unknown format: 'version' is set but 'services' is not defined", + composeFileName + ); return; } if (!(servicesElement instanceof Map)) { @@ -81,7 +89,11 @@ private void parseAndValidate() { String serviceName = entry.getKey(); Object serviceDefinition = entry.getValue(); if (!(serviceDefinition instanceof Map)) { - log.debug("Compose file {} has an unknown format: service '{}' is not Map", composeFileName, serviceName); + log.debug( + "Compose file {} has an unknown format: service '{}' is not Map", + composeFileName, + serviceName + ); break; } @@ -95,11 +107,13 @@ private void parseAndValidate() { private void validateNoContainerNameSpecified(String serviceName, Map serviceDefinitionMap) { if (serviceDefinitionMap.containsKey("container_name")) { - throw new IllegalStateException(String.format( - "Compose file %s has 'container_name' property set for service '%s' but this property is not supported by Testcontainers, consider removing it", - composeFileName, - serviceName - )); + throw new IllegalStateException( + String.format( + "Compose file %s has 'container_name' property set for service '%s' but this property is not supported by Testcontainers, consider removing it", + composeFileName, + serviceName + ) + ); } } @@ -120,28 +134,35 @@ private void findImageNamesInDockerfile(String serviceName, Map serviceDefinitio final Object dockerfileRelativePath = buildElement.get("dockerfile"); final Object contextRelativePath = buildElement.get("context"); if (dockerfileRelativePath instanceof String && contextRelativePath instanceof String) { - dockerfilePath = composeFile + dockerfilePath = + composeFile + .getAbsoluteFile() + .getParentFile() + .toPath() + .resolve((String) contextRelativePath) + .resolve((String) dockerfileRelativePath) + .normalize(); + } + } else if (buildNode instanceof String) { + dockerfilePath = + composeFile .getAbsoluteFile() .getParentFile() .toPath() - .resolve((String) contextRelativePath) - .resolve((String) dockerfileRelativePath) + .resolve((String) buildNode) + .resolve("./Dockerfile") .normalize(); - } - } else if (buildNode instanceof String) { - dockerfilePath = composeFile - .getAbsoluteFile() - .getParentFile() - .toPath() - .resolve((String) buildNode) - .resolve("./Dockerfile") - .normalize(); } if (dockerfilePath != null && Files.exists(dockerfilePath)) { Set resolvedImageNames = new ParsedDockerfile(dockerfilePath).getDependencyImageNames(); if (!resolvedImageNames.isEmpty()) { - log.debug("Resolved Dockerfile dependency images for Docker Compose in {} -> {}: {}", composeFileName, dockerfilePath, resolvedImageNames); + log.debug( + "Resolved Dockerfile dependency images for Docker Compose in {} -> {}: {}", + composeFileName, + dockerfilePath, + resolvedImageNames + ); this.serviceNameToImageNames.put(serviceName, resolvedImageNames); } } diff --git a/core/src/main/java/org/testcontainers/containers/PortForwardingContainer.java b/core/src/main/java/org/testcontainers/containers/PortForwardingContainer.java index a854b1e55c3..22d364c0762 100644 --- a/core/src/main/java/org/testcontainers/containers/PortForwardingContainer.java +++ b/core/src/main/java/org/testcontainers/containers/PortForwardingContainer.java @@ -30,15 +30,16 @@ public enum PortForwardingContainer { @SneakyThrows private Connection createSSHSession() { String password = UUID.randomUUID().toString(); - container = new GenericContainer<>(DockerImageName.parse("testcontainers/sshd:1.0.0")) - .withExposedPorts(22) - .withEnv("PASSWORD", password) - .withCommand( - "sh", - "-c", - // Disable ipv6 & Make it listen on all interfaces, not just localhost - "echo \"root:$PASSWORD\" | chpasswd && /usr/sbin/sshd -D -o PermitRootLogin=yes -o AddressFamily=inet -o GatewayPorts=yes" - ); + container = + new GenericContainer<>(DockerImageName.parse("testcontainers/sshd:1.0.0")) + .withExposedPorts(22) + .withEnv("PASSWORD", password) + .withCommand( + "sh", + "-c", + // Disable ipv6 & Make it listen on all interfaces, not just localhost + "echo \"root:$PASSWORD\" | chpasswd && /usr/sbin/sshd -D -o PermitRootLogin=yes -o AddressFamily=inet -o GatewayPorts=yes" + ); container.start(); Connection connection = new Connection(container.getHost(), container.getMappedPort(22)); @@ -64,7 +65,7 @@ public void exposeHostPort(int port) { @SneakyThrows public void exposeHostPort(int hostPort, int containerPort) { - if (exposedPorts.add(new AbstractMap.SimpleEntry<>(hostPort, containerPort))) { + if (exposedPorts.add(new AbstractMap.SimpleEntry<>(hostPort, containerPort))) { getSshConnection().requestRemotePortForwarding("", containerPort, "localhost", hostPort); } } @@ -74,7 +75,8 @@ void start() { } Optional getNetwork() { - return Optional.ofNullable(container) + return Optional + .ofNullable(container) .map(GenericContainer::getContainerInfo) .flatMap(it -> it.getNetworkSettings().getNetworks().values().stream().findFirst()); } diff --git a/core/src/main/java/org/testcontainers/containers/SelinuxContext.java b/core/src/main/java/org/testcontainers/containers/SelinuxContext.java index 735d3e3a277..ec814d5640a 100644 --- a/core/src/main/java/org/testcontainers/containers/SelinuxContext.java +++ b/core/src/main/java/org/testcontainers/containers/SelinuxContext.java @@ -13,5 +13,4 @@ public enum SelinuxContext { NONE(SELContext.none); public final SELContext selContext; - } diff --git a/core/src/main/java/org/testcontainers/containers/SocatContainer.java b/core/src/main/java/org/testcontainers/containers/SocatContainer.java index bc9ced57845..9455ac77227 100644 --- a/core/src/main/java/org/testcontainers/containers/SocatContainer.java +++ b/core/src/main/java/org/testcontainers/containers/SocatContainer.java @@ -1,10 +1,11 @@ package org.testcontainers.containers; +import org.testcontainers.utility.Base58; +import org.testcontainers.utility.DockerImageName; + import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.testcontainers.utility.Base58; -import org.testcontainers.utility.DockerImageName; /** * A socat container is used as a TCP proxy, enabling any TCP port of another container to be exposed @@ -36,10 +37,13 @@ public SocatContainer withTarget(int exposedPort, String host, int internalPort) @Override protected void configure() { - withCommand("-c", - targets.entrySet().stream() - .map(entry -> "socat TCP-LISTEN:" + entry.getKey() + ",fork,reuseaddr TCP:" + entry.getValue()) - .collect(Collectors.joining(" & ")) + withCommand( + "-c", + targets + .entrySet() + .stream() + .map(entry -> "socat TCP-LISTEN:" + entry.getKey() + ",fork,reuseaddr TCP:" + entry.getValue()) + .collect(Collectors.joining(" & ")) ); } } diff --git a/core/src/main/java/org/testcontainers/containers/VncRecordingContainer.java b/core/src/main/java/org/testcontainers/containers/VncRecordingContainer.java index be8a4ed735f..f629a141357 100644 --- a/core/src/main/java/org/testcontainers/containers/VncRecordingContainer.java +++ b/core/src/main/java/org/testcontainers/containers/VncRecordingContainer.java @@ -15,10 +15,9 @@ import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.Base64; -import static java.time.temporal.ChronoUnit.SECONDS; - /** * 'Sidekick container' with the sole purpose of recording the VNC screen output from another container. * @@ -48,7 +47,9 @@ public class VncRecordingContainer extends GenericContainer targetContainer) { this( targetContainer.getNetwork(), - targetContainer.getNetworkAliases().stream() + targetContainer + .getNetworkAliases() + .stream() .findFirst() .orElseThrow(() -> new IllegalStateException("Target container must have a network alias")) ); @@ -57,14 +58,16 @@ public VncRecordingContainer(@NonNull GenericContainer targetContainer) { /** * Create a sidekick container and attach it to another container. The VNC output of that container will be recorded. */ - public VncRecordingContainer(@NonNull Network network, @NonNull String targetNetworkAlias) throws IllegalStateException { + public VncRecordingContainer(@NonNull Network network, @NonNull String targetNetworkAlias) + throws IllegalStateException { super(DockerImageName.parse("testcontainers/vnc-recorder:1.2.0")); - this.targetNetworkAlias = targetNetworkAlias; withNetwork(network); - waitingFor(new LogMessageWaitStrategy() - .withRegEx(".*Connected.*") - .withStartupTimeout(Duration.of(15, SECONDS))); + waitingFor( + new LogMessageWaitStrategy() + .withRegEx(".*Connected.*") + .withStartupTimeout(Duration.of(15, ChronoUnit.SECONDS)) + ); } public VncRecordingContainer withVncPassword(@NonNull String vncPassword) { @@ -95,8 +98,17 @@ protected void configure() { String encodedPassword = Base64.getEncoder().encodeToString(vncPassword.getBytes()); setCommand( "-c", - "echo '" + encodedPassword + "' | base64 -d > /vnc_password && " + - "flvrec.py -o " + ORIGINAL_RECORDING_FILE_NAME + " -d -r " + frameRate + " -P /vnc_password " + targetNetworkAlias + " " + vncPort + "echo '" + + encodedPassword + + "' | base64 -d > /vnc_password && " + + "flvrec.py -o " + + ORIGINAL_RECORDING_FILE_NAME + + " -d -r " + + frameRate + + " -P /vnc_password " + + targetNetworkAlias + + " " + + vncPort ); } @@ -122,7 +134,8 @@ public void saveRecordingToFile(@NonNull File file) { public enum VncRecordingFormat { FLV("flv") { @Override - String reencodeRecording(@NonNull VncRecordingContainer container, @NonNull String source) throws IOException, InterruptedException { + String reencodeRecording(@NonNull VncRecordingContainer container, @NonNull String source) + throws IOException, InterruptedException { String newFileOutput = "/newScreen.flv"; container.execInContainer("ffmpeg", "-i", source, "-vcodec", "libx264", newFileOutput); return newFileOutput; @@ -130,17 +143,29 @@ String reencodeRecording(@NonNull VncRecordingContainer container, @NonNull Stri }, MP4("mp4") { @Override - String reencodeRecording(@NonNull VncRecordingContainer container, @NonNull String source) throws IOException, InterruptedException { + String reencodeRecording(@NonNull VncRecordingContainer container, @NonNull String source) + throws IOException, InterruptedException { String newFileOutput = "/newScreen.mp4"; - container.execInContainer("ffmpeg", "-i", source, "-vcodec", "libx264", "-movflags", "faststart", "-pix_fmt", "yuv420p", newFileOutput); + container.execInContainer( + "ffmpeg", + "-i", + source, + "-vcodec", + "libx264", + "-movflags", + "faststart", + "-pix_fmt", + "yuv420p", + newFileOutput + ); return newFileOutput; } }; - abstract String reencodeRecording(VncRecordingContainer container, String source) throws IOException, InterruptedException; + abstract String reencodeRecording(VncRecordingContainer container, String source) + throws IOException, InterruptedException; @Getter private final String filenameExtension; } - } diff --git a/core/src/main/java/org/testcontainers/containers/output/BaseConsumer.java b/core/src/main/java/org/testcontainers/containers/output/BaseConsumer.java index 2967eb4d33a..7679ee8ab57 100644 --- a/core/src/main/java/org/testcontainers/containers/output/BaseConsumer.java +++ b/core/src/main/java/org/testcontainers/containers/output/BaseConsumer.java @@ -6,6 +6,7 @@ import java.util.function.Consumer; public abstract class BaseConsumer> implements Consumer { + @Getter @Setter private boolean removeColorCodes = true; diff --git a/core/src/main/java/org/testcontainers/containers/output/FrameConsumerResultCallback.java b/core/src/main/java/org/testcontainers/containers/output/FrameConsumerResultCallback.java index 8c7480320a8..75c24d1ac1d 100644 --- a/core/src/main/java/org/testcontainers/containers/output/FrameConsumerResultCallback.java +++ b/core/src/main/java/org/testcontainers/containers/output/FrameConsumerResultCallback.java @@ -1,6 +1,5 @@ package org.testcontainers.containers.output; - import com.github.dockerjava.api.async.ResultCallbackTemplate; import com.github.dockerjava.api.model.Frame; import com.github.dockerjava.api.model.StreamType; @@ -79,7 +78,7 @@ public void onError(Throwable throwable) { // Sink any errors try { close(); - } catch (IOException ignored) { } + } catch (IOException ignored) {} } @Override @@ -169,7 +168,6 @@ private String processAnsiColorCodes(String utf8String, Consumer co return utf8String; } - private byte[] merge(byte[] str1, byte[] str2) { byte[] mergedString = new byte[str1.length + str2.length]; System.arraycopy(str1, 0, mergedString, 0, str1.length); diff --git a/core/src/main/java/org/testcontainers/containers/output/OutputFrame.java b/core/src/main/java/org/testcontainers/containers/output/OutputFrame.java index d5ddcada8c8..f6eb5c18cbc 100644 --- a/core/src/main/java/org/testcontainers/containers/output/OutputFrame.java +++ b/core/src/main/java/org/testcontainers/containers/output/OutputFrame.java @@ -12,6 +12,7 @@ public class OutputFrame { public static final OutputFrame END = new OutputFrame(OutputType.END, null); private final OutputType type; + private final byte[] bytes; public OutputFrame(OutputType type, byte[] bytes) { @@ -28,7 +29,6 @@ public byte[] getBytes() { } public String getUtf8String() { - if (bytes == null) { return ""; } @@ -37,14 +37,20 @@ public String getUtf8String() { } public enum OutputType { - STDOUT, STDERR, END; + STDOUT, + STDERR, + END; public static OutputType forStreamType(StreamType streamType) { switch (streamType) { - case RAW: return STDOUT; - case STDOUT: return STDOUT; - case STDERR: return STDERR; - default: return null; + case RAW: + return STDOUT; + case STDOUT: + return STDOUT; + case STDERR: + return STDERR; + default: + return null; } } } @@ -56,5 +62,4 @@ public static OutputFrame forFrame(Frame frame) { } return new OutputFrame(outputType, frame.getPayload()); } - } diff --git a/core/src/main/java/org/testcontainers/containers/output/Slf4jLogConsumer.java b/core/src/main/java/org/testcontainers/containers/output/Slf4jLogConsumer.java index a274cd63004..ece7ab0e5b7 100644 --- a/core/src/main/java/org/testcontainers/containers/output/Slf4jLogConsumer.java +++ b/core/src/main/java/org/testcontainers/containers/output/Slf4jLogConsumer.java @@ -1,18 +1,22 @@ package org.testcontainers.containers.output; -import java.util.HashMap; -import java.util.Map; - import org.slf4j.Logger; import org.slf4j.MDC; +import java.util.HashMap; +import java.util.Map; + /** * A consumer for container output that logs output to an SLF4J logger. */ public class Slf4jLogConsumer extends BaseConsumer { + private final Logger logger; + private final Map mdc = new HashMap<>(); + private boolean separateOutputStreams; + private String prefix = ""; public Slf4jLogConsumer(Logger logger) { diff --git a/core/src/main/java/org/testcontainers/containers/output/ToStringConsumer.java b/core/src/main/java/org/testcontainers/containers/output/ToStringConsumer.java index 40ec60fb744..444434fa702 100644 --- a/core/src/main/java/org/testcontainers/containers/output/ToStringConsumer.java +++ b/core/src/main/java/org/testcontainers/containers/output/ToStringConsumer.java @@ -10,6 +10,7 @@ * Created by rnorth on 26/03/2016. */ public class ToStringConsumer extends BaseConsumer { + private ByteArrayOutputStream stringBuffer = new ByteArrayOutputStream(); @Override diff --git a/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java b/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java index 858f5a4b487..e9b34692319 100644 --- a/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java +++ b/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java @@ -71,14 +71,14 @@ public void waitUntil(Predicate predicate, int limit, TimeUnit limi * @param limitUnit maximum time to wait (units) * @param times number of times the predicate has to match */ - public void waitUntil(Predicate predicate, long limit, TimeUnit limitUnit, int times) throws TimeoutException { + public void waitUntil(Predicate predicate, long limit, TimeUnit limitUnit, int times) + throws TimeoutException { long expiry = limitUnit.toMillis(limit) + System.currentTimeMillis(); waitUntil(predicate, expiry, times); } private void waitUntil(Predicate predicate, long expiry, int times) throws TimeoutException { - int numberOfMatches = 0; while (System.currentTimeMillis() < expiry) { try { diff --git a/core/src/main/java/org/testcontainers/containers/startupcheck/IndefiniteWaitOneShotStartupCheckStrategy.java b/core/src/main/java/org/testcontainers/containers/startupcheck/IndefiniteWaitOneShotStartupCheckStrategy.java index f719cb1d476..a547b7885e3 100644 --- a/core/src/main/java/org/testcontainers/containers/startupcheck/IndefiniteWaitOneShotStartupCheckStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/startupcheck/IndefiniteWaitOneShotStartupCheckStrategy.java @@ -12,6 +12,7 @@ * It has to be assumed that the container will stop of its own accord, either with a success or failure exit code. */ public class IndefiniteWaitOneShotStartupCheckStrategy extends OneShotStartupCheckStrategy { + @Override public boolean waitUntilStartupSuccessful(DockerClient dockerClient, String containerId) { while (checkStartupState(dockerClient, containerId) == StartupStatus.NOT_YET_KNOWN) { diff --git a/core/src/main/java/org/testcontainers/containers/startupcheck/MinimumDurationRunningStartupCheckStrategy.java b/core/src/main/java/org/testcontainers/containers/startupcheck/MinimumDurationRunningStartupCheckStrategy.java index 3ce50446b77..ce29e0104e1 100644 --- a/core/src/main/java/org/testcontainers/containers/startupcheck/MinimumDurationRunningStartupCheckStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/startupcheck/MinimumDurationRunningStartupCheckStrategy.java @@ -35,5 +35,4 @@ public StartupStatus checkStartupState(DockerClient dockerClient, String contain } return StartupStatus.NOT_YET_KNOWN; } - } diff --git a/core/src/main/java/org/testcontainers/containers/startupcheck/StartupCheckStrategy.java b/core/src/main/java/org/testcontainers/containers/startupcheck/StartupCheckStrategy.java index d5931454212..50fdcdb8b9b 100644 --- a/core/src/main/java/org/testcontainers/containers/startupcheck/StartupCheckStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/startupcheck/StartupCheckStrategy.java @@ -10,20 +10,18 @@ import java.time.Duration; import java.util.concurrent.TimeUnit; -import static org.testcontainers.containers.GenericContainer.CONTAINER_RUNNING_TIMEOUT_SEC; - /** * Approach to determine whether a container has 'started up' correctly. */ public abstract class StartupCheckStrategy { private static final RateLimiter DOCKER_CLIENT_RATE_LIMITER = RateLimiterBuilder - .newBuilder() - .withRate(1, TimeUnit.SECONDS) - .withConstantThroughput() - .build(); + .newBuilder() + .withRate(1, TimeUnit.SECONDS) + .withConstantThroughput() + .build(); - private Duration timeout = Duration.ofSeconds(CONTAINER_RUNNING_TIMEOUT_SEC); + private Duration timeout = Duration.ofSeconds(GenericContainer.CONTAINER_RUNNING_TIMEOUT_SEC); @SuppressWarnings("unchecked") public SELF withTimeout(Duration timeout) { @@ -41,20 +39,27 @@ public boolean waitUntilStartupSuccessful(GenericContainer container) { } public boolean waitUntilStartupSuccessful(DockerClient dockerClient, String containerId) { - final Boolean[] startedOK = {null}; - Unreliables.retryUntilTrue((int) timeout.toMillis(), TimeUnit.MILLISECONDS, () -> { - //noinspection CodeBlock2Expr - return DOCKER_CLIENT_RATE_LIMITER.getWhenReady(() -> { - StartupStatus state = checkStartupState(dockerClient, containerId); - switch (state) { - case SUCCESSFUL: startedOK[0] = true; - return true; - case FAILED: startedOK[0] = false; - return true; - default: return false; - } - }); - }); + final Boolean[] startedOK = { null }; + Unreliables.retryUntilTrue( + (int) timeout.toMillis(), + TimeUnit.MILLISECONDS, + () -> { + //noinspection CodeBlock2Expr + return DOCKER_CLIENT_RATE_LIMITER.getWhenReady(() -> { + StartupStatus state = checkStartupState(dockerClient, containerId); + switch (state) { + case SUCCESSFUL: + startedOK[0] = true; + return true; + case FAILED: + startedOK[0] = false; + return true; + default: + return false; + } + }); + } + ); return startedOK[0]; } @@ -65,6 +70,8 @@ protected InspectContainerResponse.ContainerState getCurrentState(DockerClient d } public enum StartupStatus { - NOT_YET_KNOWN, SUCCESSFUL, FAILED + NOT_YET_KNOWN, + SUCCESSFUL, + FAILED, } } diff --git a/core/src/main/java/org/testcontainers/containers/traits/LinkableContainer.java b/core/src/main/java/org/testcontainers/containers/traits/LinkableContainer.java index 76e71378969..4973c4dc9c1 100644 --- a/core/src/main/java/org/testcontainers/containers/traits/LinkableContainer.java +++ b/core/src/main/java/org/testcontainers/containers/traits/LinkableContainer.java @@ -7,6 +7,5 @@ */ @Deprecated public interface LinkableContainer { - String getContainerName(); } diff --git a/core/src/main/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheck.java b/core/src/main/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheck.java index d543d952bbd..fbee9c2f9f4 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheck.java +++ b/core/src/main/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheck.java @@ -14,21 +14,25 @@ */ @RequiredArgsConstructor public class ExternalPortListeningCheck implements Callable { + private final ContainerState containerState; + private final Set externalLivenessCheckPorts; @Override public Boolean call() { String address = containerState.getHost(); - externalLivenessCheckPorts.parallelStream().forEach(externalPort -> { - try (Socket socket = new Socket()) { - InetSocketAddress inetSocketAddress = new InetSocketAddress(address, externalPort); - socket.connect(inetSocketAddress, 1000); - } catch (IOException e) { - throw new IllegalStateException("Socket not listening yet: " + externalPort); - } - }); + externalLivenessCheckPorts + .parallelStream() + .forEach(externalPort -> { + try (Socket socket = new Socket()) { + InetSocketAddress inetSocketAddress = new InetSocketAddress(address, externalPort); + socket.connect(inetSocketAddress, 1000); + } catch (IOException e) { + throw new IllegalStateException("Socket not listening yet: " + externalPort); + } + }); return true; } } diff --git a/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java b/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java index 1eba8acbbd1..aeedbea1e3f 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java +++ b/core/src/main/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheck.java @@ -10,8 +10,6 @@ import java.time.Instant; import java.util.Set; -import static java.lang.String.format; - /** * Mechanism for testing that a socket is listening when run from the container being checked. */ @@ -20,6 +18,7 @@ public class InternalCommandPortListeningCheck implements java.util.concurrent.Callable { private final WaitStrategyTarget waitStrategyTarget; + private final Set internalPorts; @Override @@ -29,19 +28,31 @@ public Boolean call() { for (int internalPort : internalPorts) { command.append(" && "); command.append(" ("); - command.append(format("grep -i ':0*%x' /proc/net/tcp*", internalPort)); + command.append(String.format("grep -i ':0*%x' /proc/net/tcp*", internalPort)); command.append(" || "); - command.append(format("nc -vz -w 1 localhost %d", internalPort)); + command.append(String.format("nc -vz -w 1 localhost %d", internalPort)); command.append(" || "); - command.append(format("/bin/bash -c ' externalLivenessCheckPorts = getLivenessCheckPorts(); if (externalLivenessCheckPorts.isEmpty()) { if (log.isDebugEnabled()) { - log.debug("Liveness check ports of {} is empty. Not waiting.", waitStrategyTarget.getContainerInfo().getName()); + log.debug( + "Liveness check ports of {} is empty. Not waiting.", + waitStrategyTarget.getContainerInfo().getName() + ); } return; } @@ -45,58 +48,69 @@ protected void waitUntilReady() { Callable internalCheck = new InternalCommandPortListeningCheck(waitStrategyTarget, internalPorts); - Callable externalCheck = new ExternalPortListeningCheck(waitStrategyTarget, externalLivenessCheckPorts); + Callable externalCheck = new ExternalPortListeningCheck( + waitStrategyTarget, + externalLivenessCheckPorts + ); try { - List> futures = EXECUTOR.invokeAll(Arrays.asList( - // Blocking - () -> { - Instant now = Instant.now(); - Boolean result = internalCheck.call(); - log.debug( - "Internal port check {} for {} in {}", - Boolean.TRUE.equals(result) ? "passed" : "failed", - internalPorts, - Duration.between(now, Instant.now()) - ); - return result; - }, - // Polling - () -> { - Instant now = Instant.now(); - Awaitility.await() - .pollInSameThread() - .pollInterval(Duration.ofMillis(100)) - .pollDelay(Duration.ZERO) - .ignoreExceptions() - .forever() - .until(externalCheck); + List> futures = EXECUTOR.invokeAll( + Arrays.asList( + // Blocking + () -> { + Instant now = Instant.now(); + Boolean result = internalCheck.call(); + log.debug( + "Internal port check {} for {} in {}", + Boolean.TRUE.equals(result) ? "passed" : "failed", + internalPorts, + Duration.between(now, Instant.now()) + ); + return result; + }, + // Polling + () -> { + Instant now = Instant.now(); + Awaitility + .await() + .pollInSameThread() + .pollInterval(Duration.ofMillis(100)) + .pollDelay(Duration.ZERO) + .ignoreExceptions() + .forever() + .until(externalCheck); - log.debug( - "External port check passed for {} mapped as {} in {}", - internalPorts, - externalLivenessCheckPorts, - Duration.between(now, Instant.now()) - ); - return true; - } - ), startupTimeout.getSeconds(), TimeUnit.SECONDS); + log.debug( + "External port check passed for {} mapped as {} in {}", + internalPorts, + externalLivenessCheckPorts, + Duration.between(now, Instant.now()) + ); + return true; + } + ), + startupTimeout.getSeconds(), + TimeUnit.SECONDS + ); for (Future future : futures) { future.get(0, TimeUnit.SECONDS); } } catch (CancellationException | ExecutionException | TimeoutException e) { - throw new ContainerLaunchException("Timed out waiting for container port to open (" + - waitStrategyTarget.getHost() + - " ports: " + - externalLivenessCheckPorts + - " should be listening)"); + throw new ContainerLaunchException( + "Timed out waiting for container port to open (" + + waitStrategyTarget.getHost() + + " ports: " + + externalLivenessCheckPorts + + " should be listening)" + ); } } private Set getInternalPorts(Set externalLivenessCheckPorts, List exposedPorts) { - return exposedPorts.stream() - .filter(it -> externalLivenessCheckPorts.contains(waitStrategyTarget.getMappedPort(it))) - .collect(Collectors.toSet()); + return exposedPorts + .stream() + .filter(it -> externalLivenessCheckPorts.contains(waitStrategyTarget.getMappedPort(it))) + .collect(Collectors.toSet()); } } diff --git a/core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java b/core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java index d5d08ce6fd0..ccaef47a821 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java @@ -2,8 +2,6 @@ import com.google.common.base.Strings; import com.google.common.io.BaseEncoding; -import java.util.HashMap; -import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.rnorth.ducttape.TimeoutException; import org.testcontainers.containers.ContainerLaunchException; @@ -15,12 +13,14 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import java.time.Duration; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; +import java.time.Duration; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -48,16 +48,27 @@ public class HttpWaitStrategy extends AbstractWaitStrategy { private static final String AUTH_BASIC = "Basic "; private String path = "/"; + private String method = "GET"; + private Set statusCodes = new HashSet<>(); + private boolean tlsEnabled; + private String username; + private String password; + private final Map headers = new HashMap<>(); + private Predicate responsePredicate; + private Predicate statusCodePredicate = null; + private Optional livenessPort = Optional.empty(); + private Duration readTimeout = Duration.ofSeconds(1); + private boolean allowInsecure; /** @@ -196,14 +207,16 @@ public HttpWaitStrategy forResponsePredicate(Predicate responsePredicate protected void waitUntilReady() { final String containerName = waitStrategyTarget.getContainerInfo().getName(); - final Integer livenessCheckPort = livenessPort.map(waitStrategyTarget::getMappedPort).orElseGet(() -> { - final Set livenessCheckPorts = getLivenessCheckPorts(); - if (livenessCheckPorts == null || livenessCheckPorts.isEmpty()) { - log.warn("{}: No exposed ports or mapped ports - cannot wait for status", containerName); - return -1; - } - return livenessCheckPorts.iterator().next(); - }); + final Integer livenessCheckPort = livenessPort + .map(waitStrategyTarget::getMappedPort) + .orElseGet(() -> { + final Set livenessCheckPorts = getLivenessCheckPorts(); + if (livenessCheckPorts == null || livenessCheckPorts.isEmpty()) { + log.warn("{}: No exposed ports or mapped ports - cannot wait for status", containerName); + return -1; + } + return livenessCheckPorts.iterator().next(); + }); if (null == livenessCheckPort || -1 == livenessCheckPort) { return; @@ -213,11 +226,20 @@ protected void waitUntilReady() { try { // Un-map the port for logging - int originalPort = waitStrategyTarget.getExposedPorts().stream() + int originalPort = waitStrategyTarget + .getExposedPorts() + .stream() .filter(exposedPort -> rawUri.getPort() == waitStrategyTarget.getMappedPort(exposedPort)) .findFirst() .orElseThrow(() -> new IllegalStateException("Target port " + rawUri.getPort() + " is not exposed")); - log.info("{}: Waiting for {} seconds for URL: {} (where port {} maps to container port {})", containerName, startupTimeout.getSeconds(), uri, rawUri.getPort(), originalPort); + log.info( + "{}: Waiting for {} seconds for URL: {} (where port {} maps to container port {})", + containerName, + startupTimeout.getSeconds(), + uri, + rawUri.getPort(), + originalPort + ); } catch (RuntimeException e) { // do not allow a failure in logging to prevent progress, but log for diagnosis log.warn("Unexpected error occurred - will proceed to try to wait anyway", e); @@ -225,103 +247,114 @@ protected void waitUntilReady() { // try to connect to the URL try { - retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { - getRateLimiter().doWhenReady(() -> { - try { - final HttpURLConnection connection = openConnection(uri); - connection.setReadTimeout(Math.toIntExact(readTimeout.toMillis())); - - // authenticate - if (!Strings.isNullOrEmpty(username)) { - connection.setRequestProperty(HEADER_AUTHORIZATION, buildAuthString(username, password)); - connection.setUseCaches(false); - } - - // Add user configured headers - this.headers.forEach(connection::setRequestProperty); - connection.setRequestMethod(method); - connection.connect(); - - log.trace("Get response code {}", connection.getResponseCode()); - - // Choose the statusCodePredicate strategy depending on what we defined. - Predicate predicate; - if (statusCodes.isEmpty() && statusCodePredicate == null) { - // We have no status code and no predicate so we expect a 200 OK response code - predicate = responseCode -> HttpURLConnection.HTTP_OK == responseCode; - } else if (!statusCodes.isEmpty() && statusCodePredicate == null) { - // We use the default status predicate checker when we only have status codes - predicate = responseCode -> statusCodes.contains(responseCode); - } else if (statusCodes.isEmpty()) { - // We only have a predicate - predicate = statusCodePredicate; - } else { - // We have both predicate and status code - predicate = statusCodePredicate.or(responseCode -> statusCodes.contains(responseCode)); - } - if (!predicate.test(connection.getResponseCode())) { - throw new RuntimeException(String.format("HTTP response code was: %s", - connection.getResponseCode())); - } - - if(responsePredicate != null) { - String responseBody = getResponseBody(connection); - - log.trace("Get response {}", responseBody); - - if(!responsePredicate.test(responseBody)) { - throw new RuntimeException(String.format("Response: %s did not match predicate", - responseBody)); + retryUntilSuccess( + (int) startupTimeout.getSeconds(), + TimeUnit.SECONDS, + () -> { + getRateLimiter() + .doWhenReady(() -> { + try { + final HttpURLConnection connection = openConnection(uri); + connection.setReadTimeout(Math.toIntExact(readTimeout.toMillis())); + + // authenticate + if (!Strings.isNullOrEmpty(username)) { + connection.setRequestProperty( + HEADER_AUTHORIZATION, + buildAuthString(username, password) + ); + connection.setUseCaches(false); + } + + // Add user configured headers + this.headers.forEach(connection::setRequestProperty); + connection.setRequestMethod(method); + connection.connect(); + + log.trace("Get response code {}", connection.getResponseCode()); + + // Choose the statusCodePredicate strategy depending on what we defined. + Predicate predicate; + if (statusCodes.isEmpty() && statusCodePredicate == null) { + // We have no status code and no predicate so we expect a 200 OK response code + predicate = responseCode -> HttpURLConnection.HTTP_OK == responseCode; + } else if (!statusCodes.isEmpty() && statusCodePredicate == null) { + // We use the default status predicate checker when we only have status codes + predicate = responseCode -> statusCodes.contains(responseCode); + } else if (statusCodes.isEmpty()) { + // We only have a predicate + predicate = statusCodePredicate; + } else { + // We have both predicate and status code + predicate = + statusCodePredicate.or(responseCode -> statusCodes.contains(responseCode)); + } + if (!predicate.test(connection.getResponseCode())) { + throw new RuntimeException( + String.format("HTTP response code was: %s", connection.getResponseCode()) + ); + } + + if (responsePredicate != null) { + String responseBody = getResponseBody(connection); + + log.trace("Get response {}", responseBody); + + if (!responsePredicate.test(responseBody)) { + throw new RuntimeException( + String.format("Response: %s did not match predicate", responseBody) + ); + } + } + } catch (IOException e) { + throw new RuntimeException(e); } - } - - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - return true; - }); - + }); + return true; + } + ); } catch (TimeoutException e) { - throw new ContainerLaunchException(String.format( - "Timed out waiting for URL to be accessible (%s should return HTTP %s)", uri, statusCodes.isEmpty() ? - HttpURLConnection.HTTP_OK : statusCodes)); + throw new ContainerLaunchException( + String.format( + "Timed out waiting for URL to be accessible (%s should return HTTP %s)", + uri, + statusCodes.isEmpty() ? HttpURLConnection.HTTP_OK : statusCodes + ) + ); } } private HttpURLConnection openConnection(final String uri) throws IOException, MalformedURLException { if (tlsEnabled) { - final HttpsURLConnection connection = (HttpsURLConnection)new URL(uri).openConnection(); + final HttpsURLConnection connection = (HttpsURLConnection) new URL(uri).openConnection(); if (allowInsecure) { - // Create a trust manager that does not validate certificate chains + // Create a trust manager that does not validate certificate chains // and trust all certificates - final TrustManager[] trustAllCerts = new TrustManager[] { + final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override - public X509Certificate[] getAcceptedIssuers() { + public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } - + @Override - public void checkClientTrusted(final X509Certificate[] certs, final String authType) { - } - + public void checkClientTrusted(final X509Certificate[] certs, final String authType) {} + @Override - public void checkServerTrusted(final X509Certificate[] certs, final String authType) { - } - } - }; + public void checkServerTrusted(final X509Certificate[] certs, final String authType) {} + }, + }; try { // Create custom SSL context and set the "trust all certificates" trust manager - final SSLContext sc = SSLContext.getInstance("SSL"); - sc.init(new KeyManager[0], trustAllCerts, new SecureRandom()); + final SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(new KeyManager[0], trustAllCerts, new SecureRandom()); connection.setSSLSocketFactory(sc.getSocketFactory()); } catch (final NoSuchAlgorithmException | KeyManagementException ex) { throw new IOException("Unable to create custom SSL factory instance", ex); } } - + return connection; } else { return (HttpURLConnection) new URL(uri).openConnection(); diff --git a/core/src/main/java/org/testcontainers/containers/wait/strategy/LogMessageWaitStrategy.java b/core/src/main/java/org/testcontainers/containers/wait/strategy/LogMessageWaitStrategy.java index 65370e51bfa..7a095d888f2 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/strategy/LogMessageWaitStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/wait/strategy/LogMessageWaitStrategy.java @@ -2,7 +2,6 @@ import com.github.dockerjava.api.command.LogContainerCmd; import lombok.SneakyThrows; -import org.testcontainers.DockerClientFactory; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.output.FrameConsumerResultCallback; import org.testcontainers.containers.output.OutputFrame; @@ -13,9 +12,6 @@ import java.util.concurrent.TimeoutException; import java.util.function.Predicate; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDERR; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; - public class LogMessageWaitStrategy extends AbstractWaitStrategy { private String regEx; @@ -27,22 +23,24 @@ public class LogMessageWaitStrategy extends AbstractWaitStrategy { protected void waitUntilReady() { WaitingConsumer waitingConsumer = new WaitingConsumer(); - LogContainerCmd cmd = waitStrategyTarget.getDockerClient().logContainerCmd(waitStrategyTarget.getContainerId()) + LogContainerCmd cmd = waitStrategyTarget + .getDockerClient() + .logContainerCmd(waitStrategyTarget.getContainerId()) .withFollowStream(true) .withSince(0) .withStdOut(true) .withStdErr(true); try (FrameConsumerResultCallback callback = new FrameConsumerResultCallback()) { - callback.addConsumer(STDOUT, waitingConsumer); - callback.addConsumer(STDERR, waitingConsumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, waitingConsumer); + callback.addConsumer(OutputFrame.OutputType.STDERR, waitingConsumer); cmd.exec(callback); - Predicate waitPredicate = outputFrame -> + Predicate waitPredicate = outputFrame -> { // (?s) enables line terminator matching (equivalent to Pattern.DOTALL) - outputFrame.getUtf8String().matches("(?s)" + regEx); - + return outputFrame.getUtf8String().matches("(?s)" + regEx); + }; try { waitingConsumer.waitUntil(waitPredicate, startupTimeout.getSeconds(), TimeUnit.SECONDS, times); } catch (TimeoutException e) { diff --git a/core/src/main/java/org/testcontainers/containers/wait/strategy/Wait.java b/core/src/main/java/org/testcontainers/containers/wait/strategy/Wait.java index 034a83a2949..6c3b9e86aec 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/strategy/Wait.java +++ b/core/src/main/java/org/testcontainers/containers/wait/strategy/Wait.java @@ -1,12 +1,11 @@ package org.testcontainers.containers.wait.strategy; -import java.net.HttpURLConnection; - /** * Convenience class with logic for building common {@link WaitStrategy} instances. * */ public class Wait { + /** * Convenience method to return the default WaitStrategy. * @@ -34,8 +33,7 @@ public static HostPortWaitStrategy forListeningPort() { * @see HttpWaitStrategy */ public static HttpWaitStrategy forHttp(String path) { - return new HttpWaitStrategy() - .forPath(path); + return new HttpWaitStrategy().forPath(path); } /** @@ -46,8 +44,7 @@ public static HttpWaitStrategy forHttp(String path) { * @see HttpWaitStrategy */ public static HttpWaitStrategy forHttps(String path) { - return forHttp(path) - .usingTls(); + return forHttp(path).usingTls(); } /** diff --git a/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitAllStrategy.java b/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitAllStrategy.java index cebacb375b6..5c7530fc67f 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitAllStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitAllStrategy.java @@ -1,16 +1,15 @@ package org.testcontainers.containers.wait.strategy; +import org.rnorth.ducttape.timeouts.Timeouts; + import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; -import org.rnorth.ducttape.timeouts.Timeouts; - public class WaitAllStrategy implements WaitStrategy { public enum Mode { - /** * This is the default mode: The timeout of the {@link WaitAllStrategy strategy} is applied to each individual * strategy, so that the container waits maximum for @@ -30,11 +29,13 @@ public enum Mode { * This is the original mode of this strategy: The inner strategies wait with their preconfigured timeout * individually and the wait all strategy kills them, if the outer limit is reached. */ - WITH_MAXIMUM_OUTER_TIMEOUT + WITH_MAXIMUM_OUTER_TIMEOUT, } private final Mode mode; + private final List strategies = new ArrayList<>(); + private Duration timeout = Duration.ofSeconds(30); public WaitAllStrategy() { @@ -50,9 +51,13 @@ public void waitUntilReady(WaitStrategyTarget waitStrategyTarget) { if (mode == Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY) { waitUntilNestedStrategiesAreReady(waitStrategyTarget); } else { - Timeouts.doWithTimeout((int) timeout.toMillis(), TimeUnit.MILLISECONDS, () -> { - waitUntilNestedStrategiesAreReady(waitStrategyTarget); - }); + Timeouts.doWithTimeout( + (int) timeout.toMillis(), + TimeUnit.MILLISECONDS, + () -> { + waitUntilNestedStrategiesAreReady(waitStrategyTarget); + } + ); } } @@ -63,7 +68,6 @@ private void waitUntilNestedStrategiesAreReady(WaitStrategyTarget waitStrategyTa } public WaitAllStrategy withStrategy(WaitStrategy strategy) { - if (mode == Mode.WITH_OUTER_TIMEOUT) { applyStartupTimeout(strategy); } @@ -74,10 +78,13 @@ public WaitAllStrategy withStrategy(WaitStrategy strategy) { @Override public WaitAllStrategy withStartupTimeout(Duration startupTimeout) { - if (mode == Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY) { - throw new IllegalStateException(String.format( - "Changing startup timeout is not supported with mode %s", Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY)); + throw new IllegalStateException( + String.format( + "Changing startup timeout is not supported with mode %s", + Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY + ) + ); } this.timeout = startupTimeout; diff --git a/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategy.java b/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategy.java index 25703174502..ff371cf775f 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategy.java +++ b/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategy.java @@ -3,7 +3,6 @@ import java.time.Duration; public interface WaitStrategy { - void waitUntilReady(WaitStrategyTarget waitStrategyTarget); WaitStrategy withStartupTimeout(Duration startupTimeout); diff --git a/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategyTarget.java b/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategyTarget.java index 49f88fb7711..778c252009b 100644 --- a/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategyTarget.java +++ b/core/src/main/java/org/testcontainers/containers/wait/strategy/WaitStrategyTarget.java @@ -6,13 +6,15 @@ import java.util.stream.Collectors; public interface WaitStrategyTarget extends ContainerState { - /** * @return the ports on which to check if the container is ready */ default Set getLivenessCheckPortNumbers() { - final Set result = getExposedPorts().stream() - .map(this::getMappedPort).distinct().collect(Collectors.toSet()); + final Set result = getExposedPorts() + .stream() + .map(this::getMappedPort) + .distinct() + .collect(Collectors.toSet()); result.addAll(getBoundPortNumbers()); return result; } diff --git a/core/src/main/java/org/testcontainers/dockerclient/AuditLoggingDockerClient.java b/core/src/main/java/org/testcontainers/dockerclient/AuditLoggingDockerClient.java index 2dc88cad313..2b413aafaed 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/AuditLoggingDockerClient.java +++ b/core/src/main/java/org/testcontainers/dockerclient/AuditLoggingDockerClient.java @@ -5,13 +5,12 @@ import lombok.experimental.Delegate; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; +import org.testcontainers.utility.AuditLogger; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; import java.util.function.BiConsumer; -import static org.testcontainers.utility.AuditLogger.doLog; - /** * Wrapper for {@link DockerClient} to facilitate 'audit logging' of potentially destruction actions using * {@link org.testcontainers.utility.AuditLogger}. @@ -30,97 +29,117 @@ public AuditLoggingDockerClient(DockerClient wrappedClient) { @Override public CreateContainerCmd createContainerCmd(@NotNull String image) { - return wrappedCommand(CreateContainerCmd.class, - wrappedClient.createContainerCmd(image), - (cmd, res) -> doLog("CREATE", image, res.getId(), cmd), - (cmd, e) -> doLog("CREATE", image, null, cmd, e)); - + return wrappedCommand( + CreateContainerCmd.class, + wrappedClient.createContainerCmd(image), + (cmd, res) -> AuditLogger.doLog("CREATE", image, res.getId(), cmd), + (cmd, e) -> AuditLogger.doLog("CREATE", image, null, cmd, e) + ); } @Override public StartContainerCmd startContainerCmd(@NotNull String containerId) { - return wrappedCommand(StartContainerCmd.class, - wrappedClient.startContainerCmd(containerId), - (cmd, res) -> doLog("START", null, containerId, cmd), - (cmd, e) -> doLog("START", null, containerId, cmd, e)); + return wrappedCommand( + StartContainerCmd.class, + wrappedClient.startContainerCmd(containerId), + (cmd, res) -> AuditLogger.doLog("START", null, containerId, cmd), + (cmd, e) -> AuditLogger.doLog("START", null, containerId, cmd, e) + ); } @Override public RemoveContainerCmd removeContainerCmd(@NotNull String containerId) { - return wrappedCommand(RemoveContainerCmd.class, - wrappedClient.removeContainerCmd(containerId), - (cmd, res) -> doLog("REMOVE", null, containerId, cmd), - (cmd, e) -> doLog("REMOVE", null, containerId, cmd, e)); + return wrappedCommand( + RemoveContainerCmd.class, + wrappedClient.removeContainerCmd(containerId), + (cmd, res) -> AuditLogger.doLog("REMOVE", null, containerId, cmd), + (cmd, e) -> AuditLogger.doLog("REMOVE", null, containerId, cmd, e) + ); } @Override public StopContainerCmd stopContainerCmd(@NotNull String containerId) { - return wrappedCommand(StopContainerCmd.class, - wrappedClient.stopContainerCmd(containerId), - (cmd, res) -> doLog("STOP", null, containerId, cmd), - (cmd, e) -> doLog("STOP", null, containerId, cmd, e)); + return wrappedCommand( + StopContainerCmd.class, + wrappedClient.stopContainerCmd(containerId), + (cmd, res) -> AuditLogger.doLog("STOP", null, containerId, cmd), + (cmd, e) -> AuditLogger.doLog("STOP", null, containerId, cmd, e) + ); } @Override public KillContainerCmd killContainerCmd(@NotNull String containerId) { - return wrappedCommand(KillContainerCmd.class, - wrappedClient.killContainerCmd(containerId), - (cmd, res) -> doLog("KILL", null, containerId, cmd), - (cmd, e) -> doLog("KILL", null, containerId, cmd, e)); + return wrappedCommand( + KillContainerCmd.class, + wrappedClient.killContainerCmd(containerId), + (cmd, res) -> AuditLogger.doLog("KILL", null, containerId, cmd), + (cmd, e) -> AuditLogger.doLog("KILL", null, containerId, cmd, e) + ); } @Override public CreateNetworkCmd createNetworkCmd() { - return wrappedCommand(CreateNetworkCmd.class, - wrappedClient.createNetworkCmd(), - (cmd, res) -> doLog("CREATE_NETWORK", null, null, cmd), - (cmd, e) -> doLog("CREATE_NETWORK", null, null, cmd, e)); + return wrappedCommand( + CreateNetworkCmd.class, + wrappedClient.createNetworkCmd(), + (cmd, res) -> AuditLogger.doLog("CREATE_NETWORK", null, null, cmd), + (cmd, e) -> AuditLogger.doLog("CREATE_NETWORK", null, null, cmd, e) + ); } @Override public RemoveNetworkCmd removeNetworkCmd(@NotNull String networkId) { - return wrappedCommand(RemoveNetworkCmd.class, - wrappedClient.removeNetworkCmd(networkId), - (cmd, res) -> doLog("REMOVE_NETWORK", null, null, cmd), - (cmd, e) -> doLog("REMOVE_NETWORK", null, null, cmd, e)); + return wrappedCommand( + RemoveNetworkCmd.class, + wrappedClient.removeNetworkCmd(networkId), + (cmd, res) -> AuditLogger.doLog("REMOVE_NETWORK", null, null, cmd), + (cmd, e) -> AuditLogger.doLog("REMOVE_NETWORK", null, null, cmd, e) + ); } - private , R> T wrappedCommand(Class clazz, - T cmd, - BiConsumer successConsumer, - BiConsumer failureConsumer) { - + private , R> T wrappedCommand( + Class clazz, + T cmd, + BiConsumer successConsumer, + BiConsumer failureConsumer + ) { return (T) Proxy.newProxyInstance( - clazz.getClassLoader(), - new Class[]{clazz}, - (proxy, method, args) -> { - - if (method.getName().equals("exec")) { - try { - R r = (R) method.invoke(cmd, args); - successConsumer.accept(cmd, r); - return r; - } catch (Exception e) { - if (e instanceof InvocationTargetException && e.getCause() instanceof Exception) { - e = (Exception) e.getCause(); - } - failureConsumer.accept(cmd, e); - throw e; + clazz.getClassLoader(), + new Class[] { clazz }, + (proxy, method, args) -> { + if (method.getName().equals("exec")) { + try { + R r = (R) method.invoke(cmd, args); + successConsumer.accept(cmd, r); + return r; + } catch (Exception e) { + if (e instanceof InvocationTargetException && e.getCause() instanceof Exception) { + e = (Exception) e.getCause(); } - } else { - return method.invoke(cmd, args); + failureConsumer.accept(cmd, e); + throw e; } - }); + } else { + return method.invoke(cmd, args); + } + } + ); } @SuppressWarnings("unused") private interface InterceptedMethods { CreateContainerCmd createContainerCmd(String image); + StartContainerCmd startContainerCmd(String containerId); + RemoveContainerCmd removeContainerCmd(String containerId); + StopContainerCmd stopContainerCmd(String containerId); + KillContainerCmd killContainerCmd(String containerId); + CreateNetworkCmd createNetworkCmd(); + RemoveNetworkCmd removeNetworkCmd(String networkId); } } diff --git a/core/src/main/java/org/testcontainers/dockerclient/AuthDelegatingDockerClientConfig.java b/core/src/main/java/org/testcontainers/dockerclient/AuthDelegatingDockerClientConfig.java index 1f534eb59e5..5713d054e13 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/AuthDelegatingDockerClientConfig.java +++ b/core/src/main/java/org/testcontainers/dockerclient/AuthDelegatingDockerClientConfig.java @@ -4,11 +4,10 @@ import com.github.dockerjava.core.DockerClientConfig; import com.github.dockerjava.core.DockerClientConfigDelegate; import lombok.extern.slf4j.Slf4j; +import org.testcontainers.utility.AuthConfigUtil; import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.RegistryAuthLocator; -import static org.testcontainers.utility.AuthConfigUtil.toSafeString; - /** * Facade implementation for {@link DockerClientConfig} which overrides how authentication * configuration is obtained. A delegate {@link DockerClientConfig} will be called first @@ -31,18 +30,21 @@ public AuthConfig effectiveAuthConfig(String imageName) { try { fallbackAuthConfig = super.effectiveAuthConfig(imageName); } catch (Exception e) { - log.debug("Delegate call to effectiveAuthConfig failed with cause: '{}'. " + + log.debug( + "Delegate call to effectiveAuthConfig failed with cause: '{}'. " + "Resolution of auth config will continue using RegistryAuthLocator.", - e.getMessage()); + e.getMessage() + ); fallbackAuthConfig = new AuthConfig(); } // try and obtain more accurate auth config using our resolution final DockerImageName parsed = DockerImageName.parse(imageName); - final AuthConfig effectiveAuthConfig = RegistryAuthLocator.instance() + final AuthConfig effectiveAuthConfig = RegistryAuthLocator + .instance() .lookupAuthConfig(parsed, fallbackAuthConfig); - log.debug("Effective auth config [{}]", toSafeString(effectiveAuthConfig)); + log.debug("Effective auth config [{}]", AuthConfigUtil.toSafeString(effectiveAuthConfig)); return effectiveAuthConfig; } } diff --git a/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java b/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java index e393e59419f..7206a7e1452 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java +++ b/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java @@ -8,8 +8,7 @@ import java.io.File; import java.net.URI; import java.util.Optional; - -import static java.util.concurrent.TimeUnit.SECONDS; +import java.util.concurrent.TimeUnit; @Slf4j public class DockerClientConfigUtils { @@ -19,25 +18,31 @@ public class DockerClientConfigUtils { @Getter(lazy = true) private static final Optional defaultGateway = Optional - .ofNullable(DockerClientFactory.instance().runInsideDocker( + .ofNullable( + DockerClientFactory + .instance() + .runInsideDocker( cmd -> cmd.withCmd("sh", "-c", "ip route|awk '/default/ { print $3 }'"), (client, id) -> { try { LogToStringContainerCallback loggingCallback = new LogToStringContainerCallback(); - client.logContainerCmd(id).withStdOut(true) - .withFollowStream(true) - .exec(loggingCallback) - .awaitStarted(); - loggingCallback.awaitCompletion(3, SECONDS); + client + .logContainerCmd(id) + .withStdOut(true) + .withFollowStream(true) + .exec(loggingCallback) + .awaitStarted(); + loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); return loggingCallback.toString(); } catch (Exception e) { log.warn("Can't parse the default gateway IP", e); return null; } } - )) - .map(StringUtils::trimToEmpty) - .filter(StringUtils::isNotBlank); + ) + ) + .map(StringUtils::trimToEmpty) + .filter(StringUtils::isNotBlank); /** * @deprecated use {@link DockerClientProviderStrategy#getDockerHostIpAddress()} diff --git a/core/src/main/java/org/testcontainers/dockerclient/DockerClientProviderStrategy.java b/core/src/main/java/org/testcontainers/dockerclient/DockerClientProviderStrategy.java index 834e670438a..0d2aa3d08ed 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/DockerClientProviderStrategy.java +++ b/core/src/main/java/org/testcontainers/dockerclient/DockerClientProviderStrategy.java @@ -27,7 +27,6 @@ import org.testcontainers.UnstableAPI; import org.testcontainers.utility.TestcontainersConfiguration; -import javax.net.SocketFactory; import java.io.File; import java.net.InetSocketAddress; import java.net.Socket; @@ -54,6 +53,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.net.SocketFactory; + /** * Mechanism to find a viable Docker client configuration according to the host system environment. */ @@ -68,10 +69,11 @@ public abstract class DockerClientProviderStrategy { @Getter private Info info; - private final RateLimiter PING_RATE_LIMITER = RateLimiterBuilder.newBuilder() - .withRate(10, TimeUnit.SECONDS) - .withConstantThroughput() - .build(); + private final RateLimiter PING_RATE_LIMITER = RateLimiterBuilder + .newBuilder() + .withRate(10, TimeUnit.SECONDS) + .withConstantThroughput() + .build(); private static final AtomicBoolean FAIL_FAST_ALWAYS = new AtomicBoolean(false); @@ -109,14 +111,18 @@ protected int getPriority() { public DockerClient getClient() { DockerClient dockerClient = getDockerClient(); try { - Unreliables.retryUntilSuccess(30, TimeUnit.SECONDS, () -> { - return PING_RATE_LIMITER.getWhenReady(() -> { - log.debug("Pinging docker daemon..."); - dockerClient.pingCmd().exec(); - log.debug("Pinged"); - return true; - }); - }); + Unreliables.retryUntilSuccess( + 30, + TimeUnit.SECONDS, + () -> { + return PING_RATE_LIMITER.getWhenReady(() -> { + log.debug("Pinging docker daemon..."); + dockerClient.pingCmd().exec(); + log.debug("Pinged"); + return true; + }); + } + ); } catch (TimeoutException e) { IOUtils.closeQuietly(dockerClient); throw e; @@ -143,7 +149,12 @@ protected boolean test() { if (sslConfig != null) { try { socketFactory = sslConfig.getSSLContext().getSocketFactory(); - } catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) { + } catch ( + KeyManagementException + | UnrecoverableKeyException + | NoSuchAlgorithmException + | KeyStoreException e + ) { log.warn("Exception while creating SSLSocketFactory", e); return false; } @@ -157,16 +168,17 @@ protected boolean test() { log.debug("DOCKER_HOST socket file '{}' does not exist", dockerHost.getPath()); return false; } - socketProvider = () -> { - switch (dockerHost.getScheme()) { - case "unix": - return UnixSocket.get(dockerHost.getPath()); - case "npipe": - return new NamedPipeSocket(dockerHost.getPath()); - default: - throw new IllegalStateException("Unexpected scheme " + dockerHost.getScheme()); - } - }; + socketProvider = + () -> { + switch (dockerHost.getScheme()) { + case "unix": + return UnixSocket.get(dockerHost.getPath()); + case "npipe": + return new NamedPipeSocket(dockerHost.getPath()); + default: + throw new IllegalStateException("Unexpected scheme " + dockerHost.getScheme()); + } + }; socketAddress = new InetSocketAddress("localhost", 2375); break; default: @@ -176,7 +188,8 @@ protected boolean test() { try (Socket socket = socketProvider.call()) { Duration timeout = Duration.ofMillis(200); - Awaitility.await() + Awaitility + .await() .atMost(TestcontainersConfiguration.getInstance().getClientPingTimeout(), TimeUnit.SECONDS) .pollInterval(timeout) .pollDelay(Duration.ofSeconds(0)) // start checking immediately @@ -195,9 +208,10 @@ protected boolean test() { * @return a working DockerClientConfig, as determined by successful execution of a ping command */ public static DockerClientProviderStrategy getFirstValidStrategy(List strategies) { - if (FAIL_FAST_ALWAYS.get()) { - throw new IllegalStateException("Previous attempts to find a Docker environment failed. Will not retry. Please see logs and check configuration"); + throw new IllegalStateException( + "Previous attempts to find a Docker environment failed. Will not retry. Please see logs and check configuration" + ); } List configurationFailures = new ArrayList<>(); @@ -215,7 +229,6 @@ public static DockerClientProviderStrategy getFirstValidStrategy(List allStrategies)); - Predicate distinctStrategyClassPredicate = new Predicate() { final Set> classes = new HashSet<>(); @@ -232,14 +245,18 @@ public boolean test(DockerClientProviderStrategy dockerClientProviderStrategy) { .filter(strategy -> tryOutStrategy(configurationFailures, strategy)) .findFirst() .orElseThrow(() -> { - log.error("Could not find a valid Docker environment. Please check configuration. Attempted configurations were:"); + log.error( + "Could not find a valid Docker environment. Please check configuration. Attempted configurations were:" + ); for (String failureMessage : configurationFailures) { log.error(" " + failureMessage); } log.error("As no valid configuration was found, execution cannot continue"); FAIL_FAST_ALWAYS.set(true); - return new IllegalStateException("Could not find a valid Docker environment. Please see logs and check configuration"); + return new IllegalStateException( + "Could not find a valid Docker environment. Please see logs and check configuration" + ); }); } @@ -270,30 +287,39 @@ private static boolean tryOutStrategy(List configurationFailures, Docker } if (strategy.isPersistable()) { - TestcontainersConfiguration.getInstance().updateUserConfig("docker.client.strategy", strategy.getClass().getName()); + TestcontainersConfiguration + .getInstance() + .updateUserConfig("docker.client.strategy", strategy.getClass().getName()); } return true; } catch (Exception | ExceptionInInitializerError | NoClassDefFoundError e) { - @Nullable String throwableMessage = e.getMessage(); + @Nullable + String throwableMessage = e.getMessage(); @SuppressWarnings("ThrowableResultOfMethodCallIgnored") Throwable rootCause = Throwables.getRootCause(e); - @Nullable String rootCauseMessage = rootCause.getMessage(); + @Nullable + String rootCauseMessage = rootCause.getMessage(); String failureDescription; if (throwableMessage != null && throwableMessage.equals(rootCauseMessage)) { - failureDescription = String.format("%s: failed with exception %s (%s)", + failureDescription = + String.format( + "%s: failed with exception %s (%s)", strategy.getClass().getSimpleName(), e.getClass().getSimpleName(), - throwableMessage); + throwableMessage + ); } else { - failureDescription = String.format("%s: failed with exception %s (%s). Root cause %s (%s)", + failureDescription = + String.format( + "%s: failed with exception %s (%s). Root cause %s (%s)", strategy.getClass().getSimpleName(), e.getClass().getSimpleName(), throwableMessage, rootCause.getClass().getSimpleName(), rootCauseMessage - ); + ); } configurationFailures.add(failureDescription); @@ -303,20 +329,28 @@ private static boolean tryOutStrategy(List configurationFailures, Docker } private static Optional loadConfiguredStrategy() { - String configuredDockerClientStrategyClassName = TestcontainersConfiguration.getInstance().getDockerClientStrategyClassName(); + String configuredDockerClientStrategyClassName = TestcontainersConfiguration + .getInstance() + .getDockerClientStrategyClassName(); return Stream .of(configuredDockerClientStrategyClassName) .filter(Objects::nonNull) .flatMap(it -> { try { - Class strategyClass = (Class) Thread.currentThread().getContextClassLoader().loadClass(it); + Class strategyClass = (Class) Thread + .currentThread() + .getContextClassLoader() + .loadClass(it); return Stream.of(strategyClass.newInstance()); } catch (ClassNotFoundException e) { - log.warn("Can't instantiate a strategy from {} (ClassNotFoundException). " + + log.warn( + "Can't instantiate a strategy from {} (ClassNotFoundException). " + "This probably means that cached configuration refers to a client provider " + "class that is not available in this version of Testcontainers. Other " + - "strategies will be tried instead.", it); + "strategies will be tried instead.", + it + ); return Stream.empty(); } catch (InstantiationException | IllegalAccessException e) { log.warn("Can't instantiate a strategy from {}", it, e); @@ -325,7 +359,12 @@ private static Optional loadConfiguredSt }) // Ignore persisted strategy if it's not persistable anymore .filter(DockerClientProviderStrategy::isPersistable) - .peek(strategy -> log.info("Loaded {} from ~/.testcontainers.properties, will try it first", strategy.getClass().getName())) + .peek(strategy -> { + log.info( + "Loaded {} from ~/.testcontainers.properties, will try it first", + strategy.getClass().getName() + ); + }) .findFirst(); } @@ -335,10 +374,11 @@ public static DockerClient getClientForConfig(TransportConfig transportConfig) { String transportType = TestcontainersConfiguration.getInstance().getTransportType(); switch (transportType) { case "httpclient5": - dockerHttpClient = new ZerodepDockerHttpClient.Builder() - .dockerHost(transportConfig.getDockerHost()) - .sslConfig(transportConfig.getSslConfig()) - .build(); + dockerHttpClient = + new ZerodepDockerHttpClient.Builder() + .dockerHost(transportConfig.getDockerHost()) + .sslConfig(transportConfig.getSslConfig()) + .build(); break; default: throw new IllegalArgumentException("Unknown transport type '" + transportType + "'"); @@ -351,9 +391,7 @@ public static DockerClient getClientForConfig(TransportConfig transportConfig) { } return DockerClientImpl.getInstance( new AuthDelegatingDockerClientConfig( - configBuilder - .withDockerHost(transportConfig.getDockerHost().toString()) - .build() + configBuilder.withDockerHost(transportConfig.getDockerHost().toString()).build() ), new HeadersAddingDockerHttpClient( dockerHttpClient, @@ -384,7 +422,8 @@ static String resolveDockerHostIpAddress(DockerClient client, URI dockerHost) { case "unix": case "npipe": if (DockerClientConfigUtils.IN_A_CONTAINER) { - return client.inspectNetworkCmd() + return client + .inspectNetworkCmd() .withNetworkId("bridge") .exec() .getIpam() diff --git a/core/src/main/java/org/testcontainers/dockerclient/DockerMachineClientProviderStrategy.java b/core/src/main/java/org/testcontainers/dockerclient/DockerMachineClientProviderStrategy.java index 4de508ea808..7c05a11c198 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/DockerMachineClientProviderStrategy.java +++ b/core/src/main/java/org/testcontainers/dockerclient/DockerMachineClientProviderStrategy.java @@ -1,6 +1,7 @@ package org.testcontainers.dockerclient; import com.github.dockerjava.core.LocalDirectorySSLConfig; +import com.google.common.base.Preconditions; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.testcontainers.utility.CommandLine; @@ -11,8 +12,6 @@ import java.util.Arrays; import java.util.Optional; -import static com.google.common.base.Preconditions.checkArgument; - /** * Use Docker machine (if available on the PATH) to locate a Docker environment. * @@ -27,10 +26,16 @@ public final class DockerMachineClientProviderStrategy extends DockerClientProvi private TransportConfig resolveTransportConfig() throws InvalidConfigurationException { boolean installed = DockerMachineClient.instance().isInstalled(); - checkArgument(installed, "docker-machine executable was not found on PATH (" + Arrays.toString(CommandLine.getSystemPath()) + ")"); + Preconditions.checkArgument( + installed, + "docker-machine executable was not found on PATH (" + Arrays.toString(CommandLine.getSystemPath()) + ")" + ); Optional machineNameOptional = DockerMachineClient.instance().getDefaultMachine(); - checkArgument(machineNameOptional.isPresent(), "docker-machine is installed but no default machine could be found"); + Preconditions.checkArgument( + machineNameOptional.isPresent(), + "docker-machine is installed but no default machine could be found" + ); String machineName = machineNameOptional.get(); log.info("Found docker-machine, and will use machine named {}", machineName); @@ -41,7 +46,8 @@ private TransportConfig resolveTransportConfig() throws InvalidConfigurationExce log.info("Docker daemon URL for docker machine {} is {}", machineName, dockerDaemonUrl); - return TransportConfig.builder() + return TransportConfig + .builder() .dockerHost(URI.create(dockerDaemonUrl)) .sslConfig( new LocalDirectorySSLConfig( @@ -55,7 +61,10 @@ private TransportConfig resolveTransportConfig() throws InvalidConfigurationExce protected boolean isApplicable() { boolean installed = DockerMachineClient.instance().isInstalled(); if (!installed) { - log.info("docker-machine executable was not found on PATH ({})", Arrays.toString(CommandLine.getSystemPath())); + log.info( + "docker-machine executable was not found on PATH ({})", + Arrays.toString(CommandLine.getSystemPath()) + ); return false; } diff --git a/core/src/main/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategy.java b/core/src/main/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategy.java index 06fdf387d6a..969610373d1 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategy.java +++ b/core/src/main/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategy.java @@ -35,7 +35,8 @@ public EnvironmentAndSystemPropertyClientProviderStrategy() { } EnvironmentAndSystemPropertyClientProviderStrategy(DefaultDockerClientConfig.Builder configBuilder) { - String dockerConfigSource = TestcontainersConfiguration.getInstance() + String dockerConfigSource = TestcontainersConfiguration + .getInstance() .getEnvVarOrProperty("dockerconfig.source", "auto"); switch (dockerConfigSource) { @@ -62,7 +63,8 @@ private Optional getSetting(final String name) { @Override public TransportConfig getTransportConfig() { - return TransportConfig.builder() + return TransportConfig + .builder() .dockerHost(dockerClientConfig.getDockerHost()) .sslConfig(dockerClientConfig.getSSLConfig()) .build(); @@ -75,7 +77,10 @@ protected int getPriority() { @Override public String getDescription() { - return "Environment variables, system properties and defaults. Resolved dockerHost=" + dockerClientConfig.getDockerHost(); + return ( + "Environment variables, system properties and defaults. Resolved dockerHost=" + + dockerClientConfig.getDockerHost() + ); } @Override diff --git a/core/src/main/java/org/testcontainers/dockerclient/HeadersAddingDockerHttpClient.java b/core/src/main/java/org/testcontainers/dockerclient/HeadersAddingDockerHttpClient.java index 59a51e19a80..7ff1b0b620c 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/HeadersAddingDockerHttpClient.java +++ b/core/src/main/java/org/testcontainers/dockerclient/HeadersAddingDockerHttpClient.java @@ -19,9 +19,7 @@ class HeadersAddingDockerHttpClient implements DockerHttpClient { @Override public Response execute(Request request) { - request = Request.builder().from(request) - .putAllHeaders(headers) - .build(); + request = Request.builder().from(request).putAllHeaders(headers).build(); return delegate.execute(request); } } diff --git a/core/src/main/java/org/testcontainers/dockerclient/InvalidConfigurationException.java b/core/src/main/java/org/testcontainers/dockerclient/InvalidConfigurationException.java index ef834c9cec5..504378cb17e 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/InvalidConfigurationException.java +++ b/core/src/main/java/org/testcontainers/dockerclient/InvalidConfigurationException.java @@ -12,4 +12,4 @@ public InvalidConfigurationException(String s) { public InvalidConfigurationException(String message, Throwable cause) { super(message, cause); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/testcontainers/dockerclient/LogToStringContainerCallback.java b/core/src/main/java/org/testcontainers/dockerclient/LogToStringContainerCallback.java index d376b685a91..2c0716b65f0 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/LogToStringContainerCallback.java +++ b/core/src/main/java/org/testcontainers/dockerclient/LogToStringContainerCallback.java @@ -9,6 +9,7 @@ */ @Deprecated public class LogToStringContainerCallback extends ResultCallback.Adapter { + private final StringBuffer log = new StringBuffer(); @Override diff --git a/core/src/main/java/org/testcontainers/dockerclient/NpipeSocketClientProviderStrategy.java b/core/src/main/java/org/testcontainers/dockerclient/NpipeSocketClientProviderStrategy.java index 7f73e1d7675..0e1f641fe8a 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/NpipeSocketClientProviderStrategy.java +++ b/core/src/main/java/org/testcontainers/dockerclient/NpipeSocketClientProviderStrategy.java @@ -12,15 +12,14 @@ public final class NpipeSocketClientProviderStrategy extends DockerClientProviderStrategy { protected static final String DOCKER_SOCK_PATH = "//./pipe/docker_engine"; + private static final String SOCKET_LOCATION = "npipe://" + DOCKER_SOCK_PATH; public static final int PRIORITY = EnvironmentAndSystemPropertyClientProviderStrategy.PRIORITY - 20; @Override public TransportConfig getTransportConfig() { - return TransportConfig.builder() - .dockerHost(URI.create(SOCKET_LOCATION)) - .build(); + return TransportConfig.builder().dockerHost(URI.create(SOCKET_LOCATION)).build(); } @Override diff --git a/core/src/main/java/org/testcontainers/dockerclient/RootlessDockerClientProviderStrategy.java b/core/src/main/java/org/testcontainers/dockerclient/RootlessDockerClientProviderStrategy.java index 36d6b5f6123..a032c2b324d 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/RootlessDockerClientProviderStrategy.java +++ b/core/src/main/java/org/testcontainers/dockerclient/RootlessDockerClientProviderStrategy.java @@ -29,13 +29,15 @@ public final class RootlessDockerClientProviderStrategy extends DockerClientProv private final Path socketPath = resolveSocketPath(); private Path resolveSocketPath() { - return tryEnv().orElseGet(() -> { - Path homePath = Paths.get(System.getProperty("user.home")).resolve(".docker").resolve("run"); - return tryFolder(homePath).orElseGet(() -> { - Path implicitPath = Paths.get("/run/user/" + LibC.INSTANCE.getuid()); - return tryFolder(implicitPath).orElse(null); + return tryEnv() + .orElseGet(() -> { + Path homePath = Paths.get(System.getProperty("user.home")).resolve(".docker").resolve("run"); + return tryFolder(homePath) + .orElseGet(() -> { + Path implicitPath = Paths.get("/run/user/" + LibC.INSTANCE.getuid()); + return tryFolder(implicitPath).orElse(null); + }); }); - }); } private Optional tryEnv() { @@ -72,9 +74,7 @@ private Optional tryFolder(Path path) { @Override public TransportConfig getTransportConfig() throws InvalidConfigurationException { - return TransportConfig.builder() - .dockerHost(URI.create("unix://" + getSocketPath().toString())) - .build(); + return TransportConfig.builder().dockerHost(URI.create("unix://" + getSocketPath().toString())).build(); } @Override @@ -93,10 +93,8 @@ protected int getPriority() { } private interface LibC extends Library { - LibC INSTANCE = Native.loadLibrary("c", LibC.class); int getuid(); } - } diff --git a/core/src/main/java/org/testcontainers/dockerclient/UnixSocketClientProviderStrategy.java b/core/src/main/java/org/testcontainers/dockerclient/UnixSocketClientProviderStrategy.java index 4a85394155d..c262bda1db5 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/UnixSocketClientProviderStrategy.java +++ b/core/src/main/java/org/testcontainers/dockerclient/UnixSocketClientProviderStrategy.java @@ -14,8 +14,11 @@ */ @Deprecated public final class UnixSocketClientProviderStrategy extends DockerClientProviderStrategy { + protected static final String DOCKER_SOCK_PATH = "/var/run/docker.sock"; + private static final String SOCKET_LOCATION = "unix://" + DOCKER_SOCK_PATH; + private static final int SOCKET_FILE_MODE_MASK = 0xc000; public static final int PRIORITY = EnvironmentAndSystemPropertyClientProviderStrategy.PRIORITY - 20; @@ -31,12 +34,12 @@ public TransportConfig getTransportConfig() throws InvalidConfigurationException } if ((mode & 0xc000) != SOCKET_FILE_MODE_MASK) { - throw new InvalidConfigurationException("Found docker unix domain socket but file mode was not as expected (expected: srwxr-xr-x). This problem is possibly due to occurrence of this issue in the past: https://github.com/docker/docker/issues/13121"); + throw new InvalidConfigurationException( + "Found docker unix domain socket but file mode was not as expected (expected: srwxr-xr-x). This problem is possibly due to occurrence of this issue in the past: https://github.com/docker/docker/issues/13121" + ); } - return TransportConfig.builder() - .dockerHost(URI.create(SOCKET_LOCATION)) - .build(); + return TransportConfig.builder().dockerHost(URI.create(SOCKET_LOCATION)).build(); } @Override diff --git a/core/src/main/java/org/testcontainers/images/AbstractImagePullPolicy.java b/core/src/main/java/org/testcontainers/images/AbstractImagePullPolicy.java index f5d75ad9617..1f9583ef4cf 100644 --- a/core/src/main/java/org/testcontainers/images/AbstractImagePullPolicy.java +++ b/core/src/main/java/org/testcontainers/images/AbstractImagePullPolicy.java @@ -36,7 +36,6 @@ public boolean shouldPull(DockerImageName imageName) { log.debug("Using locally available and not pulling image: {}", imageName); return false; } - } /** @@ -45,5 +44,5 @@ public boolean shouldPull(DockerImageName imageName) { * * @return {@code true} to update the locally available image, {@code false} to use local instead */ - abstract protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData); + protected abstract boolean shouldPullCached(DockerImageName imageName, ImageData localImageData); } diff --git a/core/src/main/java/org/testcontainers/images/ImageData.java b/core/src/main/java/org/testcontainers/images/ImageData.java index 345b5939268..e57be2dbbbd 100644 --- a/core/src/main/java/org/testcontainers/images/ImageData.java +++ b/core/src/main/java/org/testcontainers/images/ImageData.java @@ -17,14 +17,13 @@ public class ImageData { Instant createdAt; static ImageData from(InspectImageResponse inspectImageResponse) { - return ImageData.builder() + return ImageData + .builder() .createdAt(ZonedDateTime.parse(inspectImageResponse.getCreated()).toInstant()) .build(); } static ImageData from(Image image) { - return ImageData.builder() - .createdAt(Instant.ofEpochMilli(image.getCreated())) - .build(); + return ImageData.builder().createdAt(Instant.ofEpochMilli(image.getCreated())).build(); } } diff --git a/core/src/main/java/org/testcontainers/images/ImagePullPolicy.java b/core/src/main/java/org/testcontainers/images/ImagePullPolicy.java index e821e511795..a090c3f7b9c 100644 --- a/core/src/main/java/org/testcontainers/images/ImagePullPolicy.java +++ b/core/src/main/java/org/testcontainers/images/ImagePullPolicy.java @@ -3,7 +3,5 @@ import org.testcontainers.utility.DockerImageName; public interface ImagePullPolicy { - boolean shouldPull(DockerImageName imageName); - } diff --git a/core/src/main/java/org/testcontainers/images/LocalImagesCache.java b/core/src/main/java/org/testcontainers/images/LocalImagesCache.java index 8791ecb6986..c98339e9f4c 100644 --- a/core/src/main/java/org/testcontainers/images/LocalImagesCache.java +++ b/core/src/main/java/org/testcontainers/images/LocalImagesCache.java @@ -79,14 +79,12 @@ private void populateFromList(List images) { } cache.putAll( - Stream.of(repoTags) + Stream + .of(repoTags) // Protection against some edge case where local image repository tags end up with duplicates // making toMap crash at merge time. .distinct() - .collect(Collectors.toMap( - DockerImageName::new, - it -> ImageData.from(image) - )) + .collect(Collectors.toMap(DockerImageName::new, it -> ImageData.from(image))) ); } } diff --git a/core/src/main/java/org/testcontainers/images/LoggedPullImageResultCallback.java b/core/src/main/java/org/testcontainers/images/LoggedPullImageResultCallback.java index 2ba8ba6df11..32e19090b5c 100644 --- a/core/src/main/java/org/testcontainers/images/LoggedPullImageResultCallback.java +++ b/core/src/main/java/org/testcontainers/images/LoggedPullImageResultCallback.java @@ -2,6 +2,7 @@ import com.github.dockerjava.api.command.PullImageResultCallback; import com.github.dockerjava.api.model.PullResponseItem; +import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import java.io.Closeable; @@ -9,21 +10,25 @@ import java.time.Instant; import java.util.*; -import static java.lang.String.format; -import static org.apache.commons.io.FileUtils.byteCountToDisplaySize; - /** * {@link PullImageResultCallback} with improved logging of pull progress. */ class LoggedPullImageResultCallback extends PullImageResultCallback { + private final Logger logger; private final Set allLayers = new HashSet<>(); + private final Set downloadedLayers = new HashSet<>(); + private final Set pulledLayers = new HashSet<>(); + private final Map totalSizes = new HashMap<>(); + private final Map currentSizes = new HashMap<>(); + private boolean completed; + private Instant start; LoggedPullImageResultCallback(final Logger logger) { @@ -69,8 +74,7 @@ public void onNext(final PullResponseItem item) { } } - if (statusLowercase.startsWith("pulling from" ) || statusLowercase.contains("complete" )) { - + if (statusLowercase.startsWith("pulling from") || statusLowercase.contains("complete")) { long totalSize = totalLayerSize(); long currentSize = downloadedLayerSize(); @@ -79,15 +83,17 @@ public void onNext(final PullResponseItem item) { if (pendingCount > 0) { friendlyTotalSize = "? MB"; } else { - friendlyTotalSize = byteCountToDisplaySize(totalSize); + friendlyTotalSize = FileUtils.byteCountToDisplaySize(totalSize); } - logger.info("Pulling image layers: {} pending, {} downloaded, {} extracted, ({}/{})", - format("%2d", pendingCount), - format("%2d", downloadedLayers.size()), - format("%2d", pulledLayers.size()), - byteCountToDisplaySize(currentSize), - friendlyTotalSize); + logger.info( + "Pulling image layers: {} pending, {} downloaded, {} extracted, ({}/{})", + String.format("%2d", pendingCount), + String.format("%2d", downloadedLayers.size()), + String.format("%2d", pulledLayers.size()), + FileUtils.byteCountToDisplaySize(currentSize), + friendlyTotalSize + ); } if (statusLowercase.contains("complete")) { @@ -103,11 +109,13 @@ public void onComplete() { final long duration = Duration.between(start, Instant.now()).getSeconds(); if (completed) { - logger.info("Pull complete. {} layers, pulled in {}s (downloaded {} at {}/s)", + logger.info( + "Pull complete. {} layers, pulled in {}s (downloaded {} at {}/s)", allLayers.size(), duration, - byteCountToDisplaySize(downloadedLayerSize), - byteCountToDisplaySize(downloadedLayerSize / duration)); + FileUtils.byteCountToDisplaySize(downloadedLayerSize), + FileUtils.byteCountToDisplaySize(downloadedLayerSize / duration) + ); } } diff --git a/core/src/main/java/org/testcontainers/images/ParsedDockerfile.java b/core/src/main/java/org/testcontainers/images/ParsedDockerfile.java index d4574d17c34..ed88c1a85ff 100644 --- a/core/src/main/java/org/testcontainers/images/ParsedDockerfile.java +++ b/core/src/main/java/org/testcontainers/images/ParsedDockerfile.java @@ -21,7 +21,10 @@ @Slf4j public class ParsedDockerfile { - private static final Pattern FROM_LINE_PATTERN = Pattern.compile("FROM (?--[^\\s]+\\s)*(?[^\\s]+).*", Pattern.CASE_INSENSITIVE); + private static final Pattern FROM_LINE_PATTERN = Pattern.compile( + "FROM (?--[^\\s]+\\s)*(?[^\\s]+).*", + Pattern.CASE_INSENSITIVE + ); private final Path dockerFilePath; @@ -54,11 +57,13 @@ private List read() { } private void parse(List lines) { - dependencyImageNames = lines.stream() - .map(FROM_LINE_PATTERN::matcher) - .filter(Matcher::matches) - .map(matcher -> matcher.group("image")) - .collect(Collectors.toSet()); + dependencyImageNames = + lines + .stream() + .map(FROM_LINE_PATTERN::matcher) + .filter(Matcher::matches) + .map(matcher -> matcher.group("image")) + .collect(Collectors.toSet()); if (!dependencyImageNames.isEmpty()) { log.debug("Found dependency images in Dockerfile {}: {}", dockerFilePath, dependencyImageNames); diff --git a/core/src/main/java/org/testcontainers/images/PullPolicy.java b/core/src/main/java/org/testcontainers/images/PullPolicy.java index 3dc2e452b8d..a8b8344a8c2 100644 --- a/core/src/main/java/org/testcontainers/images/PullPolicy.java +++ b/core/src/main/java/org/testcontainers/images/PullPolicy.java @@ -1,9 +1,9 @@ package org.testcontainers.images; -import java.time.Duration; - import lombok.experimental.UtilityClass; +import java.time.Duration; + /** * Convenience class with logic for building common {@link ImagePullPolicy} instances. * @@ -34,5 +34,4 @@ public static ImagePullPolicy alwaysPull() { public static ImagePullPolicy ageBased(Duration maxAge) { return new AgeBasedPullPolicy(maxAge); } - } diff --git a/core/src/main/java/org/testcontainers/images/RemoteDockerImage.java b/core/src/main/java/org/testcontainers/images/RemoteDockerImage.java index 3bf2243549a..7dbd7adec0b 100644 --- a/core/src/main/java/org/testcontainers/images/RemoteDockerImage.java +++ b/core/src/main/java/org/testcontainers/images/RemoteDockerImage.java @@ -62,7 +62,7 @@ public RemoteDockerImage(@NonNull Future imageFuture) { } @Override - @SneakyThrows({InterruptedException.class, ExecutionException.class}) + @SneakyThrows({ InterruptedException.class, ExecutionException.class }) protected final String resolve() { final DockerImageName imageName = getImageName(); Logger logger = DockerLoggerFactory.getLogger(imageName.toString()); @@ -72,7 +72,10 @@ protected final String resolve() { } // The image is not available locally - pull it - logger.info("Pulling docker image: {}. Please be patient; this may take some time but only needs to be done once.", imageName); + logger.info( + "Pulling docker image: {}. Please be patient; this may take some time but only needs to be done once.", + imageName + ); Exception lastFailure = null; final Instant lastRetryAllowed = Instant.now().plus(PULL_RETRY_TIME_LIMIT); @@ -84,9 +87,7 @@ protected final String resolve() { .withTag(imageName.getVersionPart()); try { - pullImageCmd - .exec(new TimeLimitedLoggedPullImageResultCallback(logger)) - .awaitCompletion(); + pullImageCmd.exec(new TimeLimitedLoggedPullImageResultCallback(logger)).awaitCompletion(); } catch (DockerClientException e) { // Try to fallback to x86 pullImageCmd @@ -101,12 +102,19 @@ protected final String resolve() { } catch (InterruptedException | InternalServerErrorException e) { // these classes of exception often relate to timeout/connection errors so should be retried lastFailure = e; - logger.warn("Retrying pull for image: {} ({}s remaining)", + logger.warn( + "Retrying pull for image: {} ({}s remaining)", imageName, - Duration.between(Instant.now(), lastRetryAllowed).getSeconds()); + Duration.between(Instant.now(), lastRetryAllowed).getSeconds() + ); } } - logger.error("Failed to pull image: {}. Please check output of `docker pull {}`", imageName, imageName, lastFailure); + logger.error( + "Failed to pull image: {}. Please check output of `docker pull {}`", + imageName, + imageName, + lastFailure + ); throw new ContainerFetchException("Failed to pull image: " + imageName, lastFailure); } catch (DockerClientException e) { diff --git a/core/src/main/java/org/testcontainers/images/TimeLimitedLoggedPullImageResultCallback.java b/core/src/main/java/org/testcontainers/images/TimeLimitedLoggedPullImageResultCallback.java index b6d8539c3e8..88b8804dd8a 100644 --- a/core/src/main/java/org/testcontainers/images/TimeLimitedLoggedPullImageResultCallback.java +++ b/core/src/main/java/org/testcontainers/images/TimeLimitedLoggedPullImageResultCallback.java @@ -3,6 +3,7 @@ import com.github.dockerjava.api.command.PullImageResultCallback; import com.github.dockerjava.api.model.PullResponseItem; import org.slf4j.Logger; +import org.testcontainers.DockerClientFactory; import org.testcontainers.utility.TestcontainersConfiguration; import java.io.Closeable; @@ -16,8 +17,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import static org.testcontainers.DockerClientFactory.TESTCONTAINERS_THREAD_GROUP; - /** * {@link PullImageResultCallback} with improved logging of pull progress and a 'watchdog' which will abort the pull * if progress is not being made, to prevent a hanging test @@ -25,14 +24,21 @@ public class TimeLimitedLoggedPullImageResultCallback extends LoggedPullImageResultCallback { private static final AtomicInteger THREAD_ID = new AtomicInteger(0); - private static final ScheduledExecutorService PROGRESS_WATCHDOG_EXECUTOR = - Executors.newScheduledThreadPool(0, runnable -> { - Thread t = new Thread(TESTCONTAINERS_THREAD_GROUP, runnable); + + private static final ScheduledExecutorService PROGRESS_WATCHDOG_EXECUTOR = Executors.newScheduledThreadPool( + 0, + runnable -> { + Thread t = new Thread(DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, runnable); t.setDaemon(true); t.setName("testcontainers-pull-watchdog-" + THREAD_ID.incrementAndGet()); return t; - }); - private static final Duration PULL_PAUSE_TOLERANCE = Duration.ofSeconds(TestcontainersConfiguration.getInstance().getImagePullPauseTimeout()); + } + ); + + private static final Duration PULL_PAUSE_TOLERANCE = Duration.ofSeconds( + TestcontainersConfiguration.getInstance().getImagePullPauseTimeout() + ); + private final Logger logger; // A future which, if it ever fires, will kill the pull @@ -85,27 +91,30 @@ public void onComplete() { super.onComplete(); } - /* * This method schedules a future task which will interrupt the waiting waiting threads if ever fired. * Every time this method is called (from onStart or onNext), the task is cancelled and recreated 30s in the future, * ensuring that it will only fire if the method stops being called regularly (e.g. if the pull has hung). */ private void resetProgressWatchdog(boolean isFinished) { - if (nextCheckForProgress != null && ! nextCheckForProgress.isCancelled()) { + if (nextCheckForProgress != null && !nextCheckForProgress.isCancelled()) { nextCheckForProgress.cancel(false); } if (!isFinished) { - nextCheckForProgress = PROGRESS_WATCHDOG_EXECUTOR.schedule( - this::abortPull, - PULL_PAUSE_TOLERANCE.getSeconds(), - TimeUnit.SECONDS - ); + nextCheckForProgress = + PROGRESS_WATCHDOG_EXECUTOR.schedule( + this::abortPull, + PULL_PAUSE_TOLERANCE.getSeconds(), + TimeUnit.SECONDS + ); } } private void abortPull() { - logger.error("Docker image pull has not made progress in {}s - aborting pull", PULL_PAUSE_TOLERANCE.getSeconds()); + logger.error( + "Docker image pull has not made progress in {}s - aborting pull", + PULL_PAUSE_TOLERANCE.getSeconds() + ); // Interrupt any threads that are waiting, before closing streams, because the stream can take // an indeterminate amount of time to close waitingThreads.forEach(Thread::interrupt); diff --git a/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java b/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java index 000487bfa4d..201cf0fd058 100644 --- a/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java +++ b/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java @@ -39,7 +39,9 @@ @Slf4j @Getter -public class ImageFromDockerfile extends LazyFuture implements +public class ImageFromDockerfile + extends LazyFuture + implements BuildContextBuilderTrait, ClasspathTrait, FilesTrait, @@ -51,9 +53,13 @@ public class ImageFromDockerfile extends LazyFuture implements private boolean deleteOnExit = true; private final Map transferables = new HashMap<>(); + private final Map buildArgs = new HashMap<>(); + private Optional dockerFilePath = Optional.empty(); + private Optional dockerfile = Optional.empty(); + private Set dependencyImageNames = Collections.emptySet(); public ImageFromDockerfile() { @@ -87,7 +93,6 @@ protected final String resolve() { DockerClient dockerClient = DockerClientFactory.instance().client(); try { - BuildImageResultCallback resultCallback = new BuildImageResultCallback() { @Override public void onNext(BuildResponseItem item) { @@ -102,8 +107,10 @@ public void onNext(BuildResponseItem item) { }; // We have to use pipes to avoid high memory consumption since users might want to build really big images - @Cleanup PipedInputStream in = new PipedInputStream(); - @Cleanup PipedOutputStream out = new PipedOutputStream(in); + @Cleanup + PipedInputStream in = new PipedInputStream(); + @Cleanup + PipedOutputStream out = new PipedOutputStream(in); BuildImageCmd buildImageCmd = dockerClient.buildImageCmd(in); configure(buildImageCmd); @@ -140,14 +147,17 @@ public void onNext(BuildResponseItem item) { } log.info("Transferred {} to Docker daemon", FileUtils.byteCountToDisplaySize(bytesToDockerDaemon)); - if (bytesToDockerDaemon > FileUtils.ONE_MB * 50) // warn if >50MB sent to docker daemon - log.warn("A large amount of data was sent to the Docker daemon ({}). Consider using a .dockerignore file for better performance.", - FileUtils.byteCountToDisplaySize(bytesToDockerDaemon)); + if (bytesToDockerDaemon > FileUtils.ONE_MB * 50) { + log.warn( // warn if >50MB sent to docker daemon + "A large amount of data was sent to the Docker daemon ({}). Consider using a .dockerignore file for better performance.", + FileUtils.byteCountToDisplaySize(bytesToDockerDaemon) + ); + } exec.awaitImageId(); return dockerImageName; - } catch(IOException e) { + } catch (IOException e) { throw new RuntimeException("Can't close DockerClient", e); } } @@ -156,15 +166,15 @@ protected void configure(BuildImageCmd buildImageCmd) { buildImageCmd.withTag(this.getDockerImageName()); this.dockerFilePath.ifPresent(buildImageCmd::withDockerfilePath); this.dockerfile.ifPresent(p -> { - buildImageCmd.withDockerfile(p.toFile()); - dependencyImageNames = new ParsedDockerfile(p).getDependencyImageNames(); + buildImageCmd.withDockerfile(p.toFile()); + dependencyImageNames = new ParsedDockerfile(p).getDependencyImageNames(); - if (dependencyImageNames.size() > 0) { - // if we'll be pre-pulling images, disable the built-in pull as it is not necessary and will fail for - // authenticated registries - buildImageCmd.withPull(false); - } - }); + if (dependencyImageNames.size() > 0) { + // if we'll be pre-pulling images, disable the built-in pull as it is not necessary and will fail for + // authenticated registries + buildImageCmd.withPull(false); + } + }); this.buildArgs.forEach(buildImageCmd::withBuildArg); } @@ -174,12 +184,19 @@ private void prePullDependencyImages(Set imagesToPull) { imagesToPull.forEach(imageName -> { try { - log.info("Pre-emptively checking local images for '{}', referenced via a Dockerfile. If not available, it will be pulled.", imageName); + log.info( + "Pre-emptively checking local images for '{}', referenced via a Dockerfile. If not available, it will be pulled.", + imageName + ); new RemoteDockerImage(DockerImageName.parse(imageName)) .withImageNameSubstitutor(ImageNameSubstitutor.noop()) .get(); } catch (Exception e) { - log.warn("Unable to pre-fetch an image ({}) depended upon by Dockerfile - image build will continue but may fail. Exception message was: {}", imageName, e.getMessage()); + log.warn( + "Unable to pre-fetch an image ({}) depended upon by Dockerfile - image build will continue but may fail. Exception message was: {}", + imageName, + e.getMessage() + ); } }); } @@ -218,5 +235,4 @@ public ImageFromDockerfile withDockerfile(Path dockerfile) { this.dockerfile = Optional.of(dockerfile); return this; } - } diff --git a/core/src/main/java/org/testcontainers/images/builder/Transferable.java b/core/src/main/java/org/testcontainers/images/builder/Transferable.java index 8ec26c8c3da..e98dbc2ad11 100644 --- a/core/src/main/java/org/testcontainers/images/builder/Transferable.java +++ b/core/src/main/java/org/testcontainers/images/builder/Transferable.java @@ -9,7 +9,6 @@ import java.util.zip.Checksum; public interface Transferable { - int DEFAULT_FILE_MODE = 0100644; int DEFAULT_DIR_MODE = 040755; diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/DockerfileBuilder.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/DockerfileBuilder.java index 17b13b3bac0..0ce794e778f 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/DockerfileBuilder.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/DockerfileBuilder.java @@ -10,7 +10,9 @@ @Data @Slf4j -public class DockerfileBuilder implements DockerfileBuilderTrait, +public class DockerfileBuilder + implements + DockerfileBuilderTrait, FromStatementTrait, AddStatementTrait, CopyStatementTrait, @@ -27,7 +29,6 @@ public class DockerfileBuilder implements DockerfileBuilderTrait statements = new ArrayList<>(); public String build() { - StringBuilder builder = new StringBuilder(); for (Statement statement : statements) { diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/statement/Statement.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/statement/Statement.java index b36811a974d..2b9b005a579 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/statement/Statement.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/statement/Statement.java @@ -7,5 +7,5 @@ public abstract class Statement { final String type; - abstract public void appendArguments(StringBuilder dockerfileStringBuilder); + public abstract void appendArguments(StringBuilder dockerfileStringBuilder); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/AddStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/AddStatementTrait.java index 44a35d68ba2..85b6b9ad6ea 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/AddStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/AddStatementTrait.java @@ -3,7 +3,6 @@ import org.testcontainers.images.builder.dockerfile.statement.MultiArgsStatement; public interface AddStatementTrait & DockerfileBuilderTrait> { - default SELF add(String source, String destination) { return ((SELF) this).withStatement(new MultiArgsStatement("ADD", source, destination)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CmdStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CmdStatementTrait.java index 054656af4d1..c9cc93c96c1 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CmdStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CmdStatementTrait.java @@ -4,7 +4,6 @@ import org.testcontainers.images.builder.dockerfile.statement.SingleArgumentStatement; public interface CmdStatementTrait & DockerfileBuilderTrait> { - default SELF cmd(String command) { return ((SELF) this).withStatement(new SingleArgumentStatement("CMD", command)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CopyStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CopyStatementTrait.java index 03e0cc7b461..0bdb2ef29ab 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CopyStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/CopyStatementTrait.java @@ -3,7 +3,6 @@ import org.testcontainers.images.builder.dockerfile.statement.MultiArgsStatement; public interface CopyStatementTrait & DockerfileBuilderTrait> { - default SELF copy(String source, String destination) { return ((SELF) this).withStatement(new MultiArgsStatement("COPY", source, destination)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/DockerfileBuilderTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/DockerfileBuilderTrait.java index 7a422da27d5..5fdc74ce1de 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/DockerfileBuilderTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/DockerfileBuilderTrait.java @@ -5,7 +5,6 @@ import java.util.List; public interface DockerfileBuilderTrait> { - List getStatements(); default SELF withStatement(Statement statement) { diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EntryPointStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EntryPointStatementTrait.java index c974e58e384..79a6e6315a0 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EntryPointStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EntryPointStatementTrait.java @@ -4,7 +4,6 @@ import org.testcontainers.images.builder.dockerfile.statement.SingleArgumentStatement; public interface EntryPointStatementTrait & DockerfileBuilderTrait> { - default SELF entryPoint(String command) { return ((SELF) this).withStatement(new SingleArgumentStatement("ENTRYPOINT", command)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EnvStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EnvStatementTrait.java index b02c8e71ec7..c1380304a34 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EnvStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/EnvStatementTrait.java @@ -6,7 +6,6 @@ import java.util.Map; public interface EnvStatementTrait & DockerfileBuilderTrait> { - default SELF env(String key, String value) { return env(Collections.singletonMap(key, value)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/ExposeStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/ExposeStatementTrait.java index bebe243c8de..22dcbeee32b 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/ExposeStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/ExposeStatementTrait.java @@ -6,8 +6,12 @@ import java.util.stream.Stream; public interface ExposeStatementTrait & DockerfileBuilderTrait> { - default SELF expose(Integer... ports) { - return ((SELF) this).withStatement(new SingleArgumentStatement("EXPOSE", Stream.of(ports).map(Object::toString).collect(Collectors.joining(" ")))); + return ((SELF) this).withStatement( + new SingleArgumentStatement( + "EXPOSE", + Stream.of(ports).map(Object::toString).collect(Collectors.joining(" ")) + ) + ); } } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/FromStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/FromStatementTrait.java index 07077259df8..1ea411d206e 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/FromStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/FromStatementTrait.java @@ -4,7 +4,6 @@ import org.testcontainers.utility.DockerImageName; public interface FromStatementTrait & DockerfileBuilderTrait> { - default SELF from(String dockerImageName) { DockerImageName.parse(dockerImageName).assertValid(); diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/LabelStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/LabelStatementTrait.java index 0b423453b33..4ed527051dd 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/LabelStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/LabelStatementTrait.java @@ -6,7 +6,6 @@ import java.util.Map; public interface LabelStatementTrait & DockerfileBuilderTrait> { - default SELF label(String key, String value) { return label(Collections.singletonMap(key, value)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/RunStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/RunStatementTrait.java index 74dfe1b00ab..f8fb064fb32 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/RunStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/RunStatementTrait.java @@ -4,7 +4,6 @@ import org.testcontainers.images.builder.dockerfile.statement.SingleArgumentStatement; public interface RunStatementTrait & DockerfileBuilderTrait> { - default SELF run(String... commandParts) { return ((SELF) this).withStatement(new MultiArgsStatement("RUN", commandParts)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/UserStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/UserStatementTrait.java index 57419ad7c5d..ca44d2d03be 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/UserStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/UserStatementTrait.java @@ -3,7 +3,6 @@ import org.testcontainers.images.builder.dockerfile.statement.SingleArgumentStatement; public interface UserStatementTrait & DockerfileBuilderTrait> { - default SELF user(String user) { return ((SELF) this).withStatement(new SingleArgumentStatement("USER", user)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/VolumeStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/VolumeStatementTrait.java index 2709adf32da..a8cd8621ee6 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/VolumeStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/VolumeStatementTrait.java @@ -3,7 +3,6 @@ import org.testcontainers.images.builder.dockerfile.statement.MultiArgsStatement; public interface VolumeStatementTrait & DockerfileBuilderTrait> { - default SELF volume(String... volumes) { return ((SELF) this).withStatement(new MultiArgsStatement("VOLUME", volumes)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/WorkdirStatementTrait.java b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/WorkdirStatementTrait.java index c4fd5386af8..ea2aaa1412c 100644 --- a/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/WorkdirStatementTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/dockerfile/traits/WorkdirStatementTrait.java @@ -3,7 +3,6 @@ import org.testcontainers.images.builder.dockerfile.statement.SingleArgumentStatement; public interface WorkdirStatementTrait & DockerfileBuilderTrait> { - default SELF workDir(String workdir) { return ((SELF) this).withStatement(new SingleArgumentStatement("WORKDIR", workdir)); } diff --git a/core/src/main/java/org/testcontainers/images/builder/traits/BuildContextBuilderTrait.java b/core/src/main/java/org/testcontainers/images/builder/traits/BuildContextBuilderTrait.java index 5ddee327cee..74ddf68b365 100644 --- a/core/src/main/java/org/testcontainers/images/builder/traits/BuildContextBuilderTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/traits/BuildContextBuilderTrait.java @@ -7,6 +7,5 @@ * */ public interface BuildContextBuilderTrait> { - SELF withFileFromTransferable(String path, Transferable transferable); } diff --git a/core/src/main/java/org/testcontainers/images/builder/traits/ClasspathTrait.java b/core/src/main/java/org/testcontainers/images/builder/traits/ClasspathTrait.java index 5617365f2cd..aadc3ccf7b9 100644 --- a/core/src/main/java/org/testcontainers/images/builder/traits/ClasspathTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/traits/ClasspathTrait.java @@ -9,7 +9,6 @@ * */ public interface ClasspathTrait & BuildContextBuilderTrait & FilesTrait> { - default SELF withFileFromClasspath(String path, String resourcePath) { final MountableFile mountableFile = MountableFile.forClasspathResource(resourcePath); diff --git a/core/src/main/java/org/testcontainers/images/builder/traits/DockerfileTrait.java b/core/src/main/java/org/testcontainers/images/builder/traits/DockerfileTrait.java index 07ed13ed0fb..293b76a7c5c 100644 --- a/core/src/main/java/org/testcontainers/images/builder/traits/DockerfileTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/traits/DockerfileTrait.java @@ -10,29 +10,31 @@ * BuildContextBuilder's trait for Dockerfile-based resources. * */ -public interface DockerfileTrait & BuildContextBuilderTrait & StringsTrait> { - +public interface DockerfileTrait< + SELF extends DockerfileTrait & BuildContextBuilderTrait & StringsTrait +> { default SELF withDockerfileFromBuilder(Consumer builderConsumer) { - DockerfileBuilder builder = new DockerfileBuilder(); builderConsumer.accept(builder); // return Transferable because we want to build Dockerfile's content lazily - return ((SELF) this).withFileFromTransferable("Dockerfile", new Transferable() { - - @Getter(lazy = true) - private final byte[] bytes = builder.build().getBytes(); - - @Override - public long getSize() { - return getBytes().length; - } - - @Override - public String getDescription() { - return "Dockerfile: " + builder; - } - }); + return ((SELF) this).withFileFromTransferable( + "Dockerfile", + new Transferable() { + @Getter(lazy = true) + private final byte[] bytes = builder.build().getBytes(); + + @Override + public long getSize() { + return getBytes().length; + } + + @Override + public String getDescription() { + return "Dockerfile: " + builder; + } + } + ); } } diff --git a/core/src/main/java/org/testcontainers/images/builder/traits/FilesTrait.java b/core/src/main/java/org/testcontainers/images/builder/traits/FilesTrait.java index 61524b59f8a..4c1204f752a 100644 --- a/core/src/main/java/org/testcontainers/images/builder/traits/FilesTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/traits/FilesTrait.java @@ -10,7 +10,6 @@ * */ public interface FilesTrait & BuildContextBuilderTrait> { - /** * Adds file to tarball copied into container. * @param path in tarball diff --git a/core/src/main/java/org/testcontainers/images/builder/traits/StringsTrait.java b/core/src/main/java/org/testcontainers/images/builder/traits/StringsTrait.java index 2b23551ee58..68de3d67c14 100644 --- a/core/src/main/java/org/testcontainers/images/builder/traits/StringsTrait.java +++ b/core/src/main/java/org/testcontainers/images/builder/traits/StringsTrait.java @@ -9,22 +9,23 @@ * */ public interface StringsTrait & BuildContextBuilderTrait> { - default SELF withFileFromString(String path, String content) { - return ((SELF) this).withFileFromTransferable(path, new Transferable() { - - @Getter - byte[] bytes = content.getBytes(); + return ((SELF) this).withFileFromTransferable( + path, + new Transferable() { + @Getter + byte[] bytes = content.getBytes(); - @Override - public long getSize() { - return bytes.length; - } + @Override + public long getSize() { + return bytes.length; + } - @Override - public String getDescription() { - return "String: " + StringUtils.abbreviate(content, 100); - } - }); + @Override + public String getDescription() { + return "String: " + StringUtils.abbreviate(content, 100); + } + } + ); } } diff --git a/core/src/main/java/org/testcontainers/lifecycle/Startable.java b/core/src/main/java/org/testcontainers/lifecycle/Startable.java index 3e73968d06e..2ffa423d2e3 100644 --- a/core/src/main/java/org/testcontainers/lifecycle/Startable.java +++ b/core/src/main/java/org/testcontainers/lifecycle/Startable.java @@ -4,7 +4,6 @@ import java.util.Set; public interface Startable extends AutoCloseable { - default Set getDependencies() { return Collections.emptySet(); } diff --git a/core/src/main/java/org/testcontainers/lifecycle/Startables.java b/core/src/main/java/org/testcontainers/lifecycle/Startables.java index 5ec46f1edb9..daa63931a88 100644 --- a/core/src/main/java/org/testcontainers/lifecycle/Startables.java +++ b/core/src/main/java/org/testcontainers/lifecycle/Startables.java @@ -1,8 +1,8 @@ package org.testcontainers.lifecycle; -import java.util.Arrays; import lombok.experimental.UtilityClass; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -17,17 +17,18 @@ @UtilityClass public class Startables { - private static final Executor EXECUTOR = Executors.newCachedThreadPool(new ThreadFactory() { - - private final AtomicLong COUNTER = new AtomicLong(0); + private static final Executor EXECUTOR = Executors.newCachedThreadPool( + new ThreadFactory() { + private final AtomicLong COUNTER = new AtomicLong(0); - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r, "testcontainers-lifecycle-" + COUNTER.getAndIncrement()); - thread.setDaemon(true); - return thread; + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, "testcontainers-lifecycle-" + COUNTER.getAndIncrement()); + thread.setDaemon(true); + return thread; + } } - }); + ); /** * @see #deepStart(Stream) @@ -77,15 +78,22 @@ public CompletableFuture deepStart(Stream startables) * @param started an intermediate storage for already started {@link Startable}s to prevent multiple starts. * @param startables a {@link Stream} of {@link Startable}s to start and scan for transitive dependencies. */ - private CompletableFuture deepStart(Map> started, Stream startables) { + private CompletableFuture deepStart( + Map> started, + Stream startables + ) { CompletableFuture[] futures = startables .sequential() .map(it -> { // avoid a recursive update in `computeIfAbsent` Map> subStarted = new HashMap<>(started); - CompletableFuture future = started.computeIfAbsent(it, startable -> { - return deepStart(subStarted, startable.getDependencies().stream()).thenRunAsync(startable::start, EXECUTOR); - }); + CompletableFuture future = started.computeIfAbsent( + it, + startable -> { + return deepStart(subStarted, startable.getDependencies().stream()) + .thenRunAsync(startable::start, EXECUTOR); + } + ); started.putAll(subStarted); return future; }) diff --git a/core/src/main/java/org/testcontainers/lifecycle/TestDescription.java b/core/src/main/java/org/testcontainers/lifecycle/TestDescription.java index c27f59fb0fc..3787707509a 100644 --- a/core/src/main/java/org/testcontainers/lifecycle/TestDescription.java +++ b/core/src/main/java/org/testcontainers/lifecycle/TestDescription.java @@ -1,7 +1,6 @@ package org.testcontainers.lifecycle; public interface TestDescription { - String getTestId(); String getFilesystemFriendlyName(); diff --git a/core/src/main/java/org/testcontainers/lifecycle/TestLifecycleAware.java b/core/src/main/java/org/testcontainers/lifecycle/TestLifecycleAware.java index 178e081c083..1e5a0258f14 100644 --- a/core/src/main/java/org/testcontainers/lifecycle/TestLifecycleAware.java +++ b/core/src/main/java/org/testcontainers/lifecycle/TestLifecycleAware.java @@ -3,12 +3,7 @@ import java.util.Optional; public interface TestLifecycleAware { + default void beforeTest(TestDescription description) {} - default void beforeTest(TestDescription description) { - - } - - default void afterTest(TestDescription description, Optional throwable) { - - } + default void afterTest(TestDescription description, Optional throwable) {} } diff --git a/core/src/main/java/org/testcontainers/utility/AuditLogger.java b/core/src/main/java/org/testcontainers/utility/AuditLogger.java index f6c4559485d..518144c4302 100644 --- a/core/src/main/java/org/testcontainers/utility/AuditLogger.java +++ b/core/src/main/java/org/testcontainers/utility/AuditLogger.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dockerjava.api.command.DockerCmd; +import com.google.common.base.Strings; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -12,8 +13,6 @@ import java.util.List; -import static com.google.common.base.Strings.nullToEmpty; - /** * Logger for tracking potentially destructive actions, intended for usage in a shared Docker environment where * traceability is needed. This class uses SLF4J, logging at TRACE level and capturing common fields as MDC fields. @@ -26,34 +25,36 @@ public class AuditLogger { private static final ObjectMapper objectMapper = new ObjectMapper(); - public static final String MDC_PREFIX = AuditLogger.class.getCanonicalName(); - public static void doLog(@NotNull String action, - @Nullable String image, - @Nullable String containerId, - @NotNull DockerCmd cmd) { + public static final String MDC_PREFIX = AuditLogger.class.getCanonicalName(); + public static void doLog( + @NotNull String action, + @Nullable String image, + @Nullable String containerId, + @NotNull DockerCmd cmd + ) { doLog(action, image, containerId, cmd, null); } - public static void doLog(@NotNull String action, - @Nullable String image, - @Nullable String containerId, - @NotNull DockerCmd cmd, - @Nullable Exception e) { - - if (! log.isTraceEnabled()) { + public static void doLog( + @NotNull String action, + @Nullable String image, + @Nullable String containerId, + @NotNull DockerCmd cmd, + @Nullable Exception e + ) { + if (!log.isTraceEnabled()) { return; } - MDC.put(MDC_PREFIX + ".Action", nullToEmpty(action)); - MDC.put(MDC_PREFIX + ".Image", nullToEmpty(image)); - MDC.put(MDC_PREFIX + ".ContainerId", nullToEmpty(containerId)); + MDC.put(MDC_PREFIX + ".Action", Strings.nullToEmpty(action)); + MDC.put(MDC_PREFIX + ".Image", Strings.nullToEmpty(image)); + MDC.put(MDC_PREFIX + ".ContainerId", Strings.nullToEmpty(containerId)); try { MDC.put(MDC_PREFIX + ".Command", objectMapper.writeValueAsString(cmd)); - } catch (JsonProcessingException ignored) { - } + } catch (JsonProcessingException ignored) {} if (e != null) { MDC.put(MDC_PREFIX + ".Exception", e.getLocalizedMessage()); @@ -69,10 +70,8 @@ public static void doLog(@NotNull String action, MDC.remove(MDC_PREFIX + ".Exception"); } - public static void doComposeLog(@NotNull String[] commandParts, - @Nullable List env) { - - if (! log.isTraceEnabled()) { + public static void doComposeLog(@NotNull String[] commandParts, @Nullable List env) { + if (!log.isTraceEnabled()) { return; } diff --git a/core/src/main/java/org/testcontainers/utility/AuthConfigUtil.java b/core/src/main/java/org/testcontainers/utility/AuthConfigUtil.java index 77b670d374b..8ed91a5e34e 100644 --- a/core/src/main/java/org/testcontainers/utility/AuthConfigUtil.java +++ b/core/src/main/java/org/testcontainers/utility/AuthConfigUtil.java @@ -2,22 +2,23 @@ import com.github.dockerjava.api.model.AuthConfig; import com.google.common.base.MoreObjects; +import com.google.common.base.Strings; import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; -import static com.google.common.base.Strings.isNullOrEmpty; - /** * TODO: Javadocs */ @UtilityClass public class AuthConfigUtil { + public static String toSafeString(AuthConfig authConfig) { if (authConfig == null) { return "null"; } - return MoreObjects.toStringHelper(authConfig) + return MoreObjects + .toStringHelper(authConfig) .add("username", authConfig.getUsername()) .add("password", obfuscated(authConfig.getPassword())) .add("auth", obfuscated(authConfig.getAuth())) @@ -29,6 +30,6 @@ public static String toSafeString(AuthConfig authConfig) { @NotNull private static String obfuscated(String value) { - return isNullOrEmpty(value) ? "blank" : "hidden non-blank value"; + return Strings.isNullOrEmpty(value) ? "blank" : "hidden non-blank value"; } } diff --git a/core/src/main/java/org/testcontainers/utility/Base58.java b/core/src/main/java/org/testcontainers/utility/Base58.java index 1f56978c7cc..2cbfc751f4d 100644 --- a/core/src/main/java/org/testcontainers/utility/Base58.java +++ b/core/src/main/java/org/testcontainers/utility/Base58.java @@ -7,8 +7,7 @@ */ public class Base58 { - private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" - .toCharArray(); + private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); private static final SecureRandom RANDOM = new SecureRandom(); diff --git a/core/src/main/java/org/testcontainers/utility/ClasspathScanner.java b/core/src/main/java/org/testcontainers/utility/ClasspathScanner.java index 76716cfdb7c..0c8addc2874 100644 --- a/core/src/main/java/org/testcontainers/utility/ClasspathScanner.java +++ b/core/src/main/java/org/testcontainers/utility/ClasspathScanner.java @@ -40,11 +40,7 @@ private static Integer filesFileSchemeFirst(final URL t) { * context classloader. Results are currently alphabetically sorted. */ static Stream scanFor(final String name) { - return scanFor( - name, - ClasspathScanner.class.getClassLoader(), - Thread.currentThread().getContextClassLoader() - ); + return scanFor(name, ClasspathScanner.class.getClassLoader(), Thread.currentThread().getContextClassLoader()); } @Nullable diff --git a/core/src/main/java/org/testcontainers/utility/CommandLine.java b/core/src/main/java/org/testcontainers/utility/CommandLine.java index a217823c40f..1bb8f827148 100644 --- a/core/src/main/java/org/testcontainers/utility/CommandLine.java +++ b/core/src/main/java/org/testcontainers/utility/CommandLine.java @@ -2,6 +2,7 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.zeroturnaround.exec.InvalidExitValueException; import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.ProcessResult; @@ -14,14 +15,12 @@ import java.util.concurrent.TimeoutException; import java.util.regex.Pattern; -import static org.slf4j.LoggerFactory.getLogger; - /** * Process execution utility methods. */ public class CommandLine { - private static final Logger LOGGER = getLogger(CommandLine.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CommandLine.class); /** * Run a shell command synchronously. @@ -30,16 +29,11 @@ public class CommandLine { * @return the stdout output of the command */ public static String runShellCommand(String... command) { - String joinedCommand = String.join(" ", command); LOGGER.debug("Executing shell command: `{}`", joinedCommand); try { - ProcessResult result = new ProcessExecutor() - .command(command) - .readOutput(true) - .exitValueNormal() - .execute(); + ProcessResult result = new ProcessExecutor().command(command).readOutput(true).exitValueNormal().execute(); return result.outputUTF8().trim(); } catch (IOException | InterruptedException | TimeoutException | InvalidExitValueException e) { @@ -55,7 +49,6 @@ public static String runShellCommand(String... command) { * @return whether the executable exists and is executable */ public static boolean executableExists(String executable) { - // First check if we've been given the full path already File directFile = new File(executable); if (directFile.exists() && directFile.canExecute()) { @@ -78,6 +71,7 @@ public static String[] getSystemPath() { } private static class ShellCommandException extends RuntimeException { + public ShellCommandException(String message, Exception e) { super(message, e); } diff --git a/core/src/main/java/org/testcontainers/utility/ComparableVersion.java b/core/src/main/java/org/testcontainers/utility/ComparableVersion.java index d3e3d9eb958..999c4b40b3b 100644 --- a/core/src/main/java/org/testcontainers/utility/ComparableVersion.java +++ b/core/src/main/java/org/testcontainers/utility/ComparableVersion.java @@ -1,12 +1,11 @@ package org.testcontainers.utility; -import java.util.ArrayList; -import java.util.List; - import com.google.common.annotations.VisibleForTesting; - import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; + public final class ComparableVersion implements Comparable { private final int[] parts; @@ -19,7 +18,7 @@ public ComparableVersion(String version) { @Override public int compareTo(@NotNull ComparableVersion other) { - for (int i=0; i otherPart) { @@ -71,5 +70,4 @@ static int[] parseVersion(final String version) { return ret; } - } diff --git a/core/src/main/java/org/testcontainers/utility/ConfigurationFileImageNameSubstitutor.java b/core/src/main/java/org/testcontainers/utility/ConfigurationFileImageNameSubstitutor.java index 530d5a76118..ee7ab1d95b6 100644 --- a/core/src/main/java/org/testcontainers/utility/ConfigurationFileImageNameSubstitutor.java +++ b/core/src/main/java/org/testcontainers/utility/ConfigurationFileImageNameSubstitutor.java @@ -28,7 +28,8 @@ public DockerImageName apply(final DockerImageName original) { .asCompatibleSubstituteFor(original); if (!result.equals(original)) { - log.warn("Image name {} was substituted by configuration to {}. This approach is deprecated and will be removed in the future", + log.warn( + "Image name {} was substituted by configuration to {}. This approach is deprecated and will be removed in the future", original, result ); diff --git a/core/src/main/java/org/testcontainers/utility/DefaultImageNameSubstitutor.java b/core/src/main/java/org/testcontainers/utility/DefaultImageNameSubstitutor.java index 840b8a77b40..a7755f8eea8 100644 --- a/core/src/main/java/org/testcontainers/utility/DefaultImageNameSubstitutor.java +++ b/core/src/main/java/org/testcontainers/utility/DefaultImageNameSubstitutor.java @@ -11,6 +11,7 @@ final class DefaultImageNameSubstitutor extends ImageNameSubstitutor { private final ConfigurationFileImageNameSubstitutor configurationFileImageNameSubstitutor; + private final PrefixingImageNameSubstitutor prefixingImageNameSubstitutor; public DefaultImageNameSubstitutor() { @@ -29,13 +30,17 @@ public DefaultImageNameSubstitutor() { @Override public DockerImageName apply(final DockerImageName original) { - return configurationFileImageNameSubstitutor - .andThen(prefixingImageNameSubstitutor) - .apply(original); + return configurationFileImageNameSubstitutor.andThen(prefixingImageNameSubstitutor).apply(original); } @Override protected String getDescription() { - return "DefaultImageNameSubstitutor (composite of '" + configurationFileImageNameSubstitutor.getDescription() + "' and '" + prefixingImageNameSubstitutor.getDescription() + "')"; + return ( + "DefaultImageNameSubstitutor (composite of '" + + configurationFileImageNameSubstitutor.getDescription() + + "' and '" + + prefixingImageNameSubstitutor.getDescription() + + "')" + ); } } diff --git a/core/src/main/java/org/testcontainers/utility/DockerImageName.java b/core/src/main/java/org/testcontainers/utility/DockerImageName.java index b9d266a41ca..9fca02aad6f 100644 --- a/core/src/main/java/org/testcontainers/utility/DockerImageName.java +++ b/core/src/main/java/org/testcontainers/utility/DockerImageName.java @@ -1,6 +1,5 @@ package org.testcontainers.utility; - import com.google.common.net.HostAndPort; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -20,16 +19,29 @@ public final class DockerImageName { /* Regex patterns used for validation */ private static final String ALPHA_NUMERIC = "[a-z0-9]+"; + private static final String SEPARATOR = "([.]|_{1,2}|-+)"; + private static final String REPO_NAME_PART = ALPHA_NUMERIC + "(" + SEPARATOR + ALPHA_NUMERIC + ")*"; + private static final Pattern REPO_NAME = Pattern.compile(REPO_NAME_PART + "(/" + REPO_NAME_PART + ")*"); private final String rawName; - @With @Getter private final String registry; - @With @Getter private final String repository; - @NotNull @With(AccessLevel.PRIVATE) + + @With + @Getter + private final String registry; + + @With + @Getter + private final String repository; + + @NotNull + @With(AccessLevel.PRIVATE) private final Versioning versioning; - @Nullable @With(AccessLevel.PRIVATE) + + @Nullable + @With(AccessLevel.PRIVATE) private final DockerImageName compatibleSubstituteFor; /** @@ -57,10 +69,14 @@ public DockerImageName(String fullImageName) { final int slashIndex = fullImageName.indexOf('/'); String remoteName; - if (slashIndex == -1 || - (!fullImageName.substring(0, slashIndex).contains(".") && + if ( + slashIndex == -1 || + ( + !fullImageName.substring(0, slashIndex).contains(".") && !fullImageName.substring(0, slashIndex).contains(":") && - !fullImageName.substring(0, slashIndex).equals("localhost"))) { + !fullImageName.substring(0, slashIndex).equals("localhost") + ) + ) { registry = ""; remoteName = fullImageName; } else { @@ -99,10 +115,14 @@ public DockerImageName(String nameWithoutTag, @NotNull String version) { final int slashIndex = nameWithoutTag.indexOf('/'); String remoteName; - if (slashIndex == -1 || - (!nameWithoutTag.substring(0, slashIndex).contains(".") && + if ( + slashIndex == -1 || + ( + !nameWithoutTag.substring(0, slashIndex).contains(".") && !nameWithoutTag.substring(0, slashIndex).contains(":") && - !nameWithoutTag.substring(0, slashIndex).equals("localhost"))) { + !nameWithoutTag.substring(0, slashIndex).equals("localhost") + ) + ) { registry = ""; remoteName = nameWithoutTag; } else { @@ -163,7 +183,9 @@ public void assertValid() { throw new IllegalArgumentException(repository + " is not a valid Docker image name (in " + rawName + ")"); } if (!versioning.isValid()) { - throw new IllegalArgumentException(versioning + " is not a valid image versioning identifier (in " + rawName + ")"); + throw new IllegalArgumentException( + versioning + " is not a valid image versioning identifier (in " + rawName + ")" + ); } } @@ -246,18 +268,16 @@ public void assertCompatibleWith(DockerImageName... anyOthers) { throw new IllegalStateException( String.format( - "Failed to verify that image '%s' is a compatible substitute for '%s'. This generally means that " - + - "you are trying to use an image that Testcontainers has not been designed to use. If this is " - + - "deliberate, and if you are confident that the image is compatible, you should declare " - + - "compatibility in code using the `asCompatibleSubstituteFor` method. For example:\n" - + - " DockerImageName myImage = DockerImageName.parse(\"%s\").asCompatibleSubstituteFor(\"%s\");\n" - + - "and then use `myImage` instead.", - this.rawName, exampleOther.rawName, this.rawName, exampleOther.rawName + "Failed to verify that image '%s' is a compatible substitute for '%s'. This generally means that " + + "you are trying to use an image that Testcontainers has not been designed to use. If this is " + + "deliberate, and if you are confident that the image is compatible, you should declare " + + "compatibility in code using the `asCompatibleSubstituteFor` method. For example:\n" + + " DockerImageName myImage = DockerImageName.parse(\"%s\").asCompatibleSubstituteFor(\"%s\");\n" + + "and then use `myImage` instead.", + this.rawName, + exampleOther.rawName, + this.rawName, + exampleOther.rawName ) ); } diff --git a/core/src/main/java/org/testcontainers/utility/DockerLoggerFactory.java b/core/src/main/java/org/testcontainers/utility/DockerLoggerFactory.java index 69f7b998da2..c372c3cea3e 100644 --- a/core/src/main/java/org/testcontainers/utility/DockerLoggerFactory.java +++ b/core/src/main/java/org/testcontainers/utility/DockerLoggerFactory.java @@ -9,7 +9,6 @@ public final class DockerLoggerFactory { public static Logger getLogger(String dockerImageName) { - final String abbreviatedName; if (dockerImageName.contains("@sha256")) { abbreviatedName = dockerImageName.substring(0, dockerImageName.indexOf("@sha256") + 14) + "..."; diff --git a/core/src/main/java/org/testcontainers/utility/DockerMachineClient.java b/core/src/main/java/org/testcontainers/utility/DockerMachineClient.java index 6f1e2c9d50b..1a2b4aafe74 100644 --- a/core/src/main/java/org/testcontainers/utility/DockerMachineClient.java +++ b/core/src/main/java/org/testcontainers/utility/DockerMachineClient.java @@ -3,44 +3,42 @@ import lombok.NonNull; import org.apache.commons.lang3.SystemUtils; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.Arrays; import java.util.List; import java.util.Optional; -import static java.util.Arrays.asList; -import static org.slf4j.LoggerFactory.getLogger; -import static org.testcontainers.utility.CommandLine.executableExists; -import static org.testcontainers.utility.CommandLine.runShellCommand; - /** * Created by rnorth on 27/10/2015. */ public class DockerMachineClient { private static DockerMachineClient instance; - private static final Logger LOGGER = getLogger(DockerMachineClient.class); + + private static final Logger LOGGER = LoggerFactory.getLogger(DockerMachineClient.class); private static final String executableName; + static { - if(SystemUtils.IS_OS_WINDOWS) { - executableName = "docker-machine.exe"; - } else { - executableName = "docker-machine"; - } + if (SystemUtils.IS_OS_WINDOWS) { + executableName = "docker-machine.exe"; + } else { + executableName = "docker-machine"; + } } /** * Private constructor */ - private DockerMachineClient() { - } + private DockerMachineClient() {} /** * Obtain an instance of the DockerMachineClient wrapper. * * @return the singleton instance of DockerMachineClient */ - public synchronized static DockerMachineClient instance() { + public static synchronized DockerMachineClient instance() { if (instance == null) { instance = new DockerMachineClient(); } @@ -49,12 +47,12 @@ public synchronized static DockerMachineClient instance() { } public boolean isInstalled() { - return executableExists(executableName); + return CommandLine.executableExists(executableName); } public Optional getDefaultMachine() { - String ls = runShellCommand(executableName, "ls", "-q"); - List machineNames = asList(ls.split("\n")); + String ls = CommandLine.runShellCommand(executableName, "ls", "-q"); + List machineNames = Arrays.asList(ls.split("\n")); String envMachineName = System.getenv("DOCKER_MACHINE_NAME"); @@ -65,7 +63,10 @@ public Optional getDefaultMachine() { LOGGER.debug("DOCKER_MACHINE_NAME is not set; Using 'default' docker-machine", envMachineName); return Optional.of("default"); } else if (machineNames.size() > 0) { - LOGGER.debug("DOCKER_MACHINE_NAME is not set and no machine named 'default' found; Using first machine found with `docker-machine ls`: {}", machineNames.get(0)); + LOGGER.debug( + "DOCKER_MACHINE_NAME is not set and no machine named 'default' found; Using first machine found with `docker-machine ls`: {}", + machineNames.get(0) + ); return Optional.of(machineNames.get(0)); } else { return Optional.empty(); @@ -75,7 +76,7 @@ public Optional getDefaultMachine() { public void ensureMachineRunning(@NonNull String machineName) { if (!isMachineRunning(machineName)) { LOGGER.info("Docker-machine '{}' is not running. Will start it now", machineName); - runShellCommand("docker-machine", "start", machineName); + CommandLine.runShellCommand("docker-machine", "start", machineName); } } @@ -84,15 +85,15 @@ public void ensureMachineRunning(@NonNull String machineName) { */ @Deprecated public String getDockerDaemonIpAddress(@NonNull String machineName) { - return runShellCommand(executableName, "ip", machineName); + return CommandLine.runShellCommand(executableName, "ip", machineName); } public String getDockerDaemonUrl(@NonNull String machineName) { - return runShellCommand(executableName, "url", machineName); + return CommandLine.runShellCommand(executableName, "url", machineName); } public boolean isMachineRunning(String machineName) { - String status = runShellCommand("docker-machine", "status", machineName); + String status = CommandLine.runShellCommand("docker-machine", "status", machineName); return status.trim().equalsIgnoreCase("running"); } diff --git a/core/src/main/java/org/testcontainers/utility/DockerStatus.java b/core/src/main/java/org/testcontainers/utility/DockerStatus.java index a410597dcfb..00f71249dd1 100644 --- a/core/src/main/java/org/testcontainers/utility/DockerStatus.java +++ b/core/src/main/java/org/testcontainers/utility/DockerStatus.java @@ -33,15 +33,16 @@ public class DockerStatus { * @param now the time to consider as the current time * @return true if we can conclude that the container is running, false otherwise */ - public static boolean isContainerRunning(InspectContainerResponse.ContainerState state, - Duration minimumRunningDuration, - Instant now) { + public static boolean isContainerRunning( + InspectContainerResponse.ContainerState state, + Duration minimumRunningDuration, + Instant now + ) { if (state.getRunning()) { if (minimumRunningDuration == null) { return true; } - Instant startedAt = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse( - state.getStartedAt(), Instant::from); + Instant startedAt = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(state.getStartedAt(), Instant::from); if (startedAt.isBefore(now.minus(minimumRunningDuration))) { return true; @@ -57,7 +58,6 @@ public static boolean isContainerRunning(InspectContainerResponse.ContainerState * @return true if we can conclude that the container has started but is now stopped, false otherwise. */ public static boolean isContainerStopped(InspectContainerResponse.ContainerState state) { - // get some preconditions out of the way if (state.getRunning() || state.getPaused()) { return false; @@ -72,10 +72,12 @@ public static boolean isContainerStopped(InspectContainerResponse.ContainerState public static boolean isDockerTimestampNonEmpty(String dockerTimestamp) { // This is a defensive approach. Current versions of Docker use the DOCKER_TIMESTAMP_ZERO value, but // that could change. - return dockerTimestamp != null - && !dockerTimestamp.isEmpty() - && !dockerTimestamp.equals(DOCKER_TIMESTAMP_ZERO) - && DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(dockerTimestamp, Instant::from).getEpochSecond() >= 0L; + return ( + dockerTimestamp != null && + !dockerTimestamp.isEmpty() && + !dockerTimestamp.equals(DOCKER_TIMESTAMP_ZERO) && + DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(dockerTimestamp, Instant::from).getEpochSecond() >= 0L + ); } public static boolean isContainerExitCodeSuccess(InspectContainerResponse.ContainerState state) { diff --git a/core/src/main/java/org/testcontainers/utility/DynamicPollInterval.java b/core/src/main/java/org/testcontainers/utility/DynamicPollInterval.java index 1252fb2c3a1..043befe04bb 100644 --- a/core/src/main/java/org/testcontainers/utility/DynamicPollInterval.java +++ b/core/src/main/java/org/testcontainers/utility/DynamicPollInterval.java @@ -15,6 +15,7 @@ public class DynamicPollInterval implements PollInterval { final Duration interval; + Instant lastTimestamp; private DynamicPollInterval(Duration interval) { diff --git a/core/src/main/java/org/testcontainers/utility/ImageNameSubstitutor.java b/core/src/main/java/org/testcontainers/utility/ImageNameSubstitutor.java index a1cb2492204..dae3f178230 100644 --- a/core/src/main/java/org/testcontainers/utility/ImageNameSubstitutor.java +++ b/core/src/main/java/org/testcontainers/utility/ImageNameSubstitutor.java @@ -24,7 +24,7 @@ public abstract class ImageNameSubstitutor implements Function> filters) { - String[] labels = filters.stream() + String[] labels = filters + .stream() .filter(it -> "label".equals(it.getKey())) .map(Map.Entry::getValue) .toArray(String[]::new); switch (pruneType) { // Docker only prunes stopped containers, so we have to do it manually case CONTAINERS: - List containers = dockerClient.listContainersCmd() + List containers = dockerClient + .listContainersCmd() .withFilter("label", Arrays.asList(labels)) .withShowAll(true) .exec(); - containers.parallelStream().forEach(container -> { - dockerClient.removeContainerCmd(container.getId()) - .withForce(true) - .withRemoveVolumes(true) - .exec(); - }); + containers + .parallelStream() + .forEach(container -> { + dockerClient + .removeContainerCmd(container.getId()) + .withForce(true) + .withRemoveVolumes(true) + .exec(); + }); break; default: dockerClient.pruneCmd(pruneType).withLabelFilter(labels).exec(); diff --git a/core/src/main/java/org/testcontainers/utility/LazyFuture.java b/core/src/main/java/org/testcontainers/utility/LazyFuture.java index 758082f5185..bde9feb69ec 100644 --- a/core/src/main/java/org/testcontainers/utility/LazyFuture.java +++ b/core/src/main/java/org/testcontainers/utility/LazyFuture.java @@ -17,7 +17,7 @@ public abstract class LazyFuture implements Future { @Getter(value = AccessLevel.MODULE, lazy = true) private final T resolvedValue = resolve(); - abstract protected T resolve(); + protected abstract T resolve(); @Override public boolean cancel(boolean mayInterruptIfRunning) { diff --git a/core/src/main/java/org/testcontainers/utility/LicenseAcceptance.java b/core/src/main/java/org/testcontainers/utility/LicenseAcceptance.java index 55037d8978c..9fe8d9db8e6 100644 --- a/core/src/main/java/org/testcontainers/utility/LicenseAcceptance.java +++ b/core/src/main/java/org/testcontainers/utility/LicenseAcceptance.java @@ -27,10 +27,17 @@ public static void assertLicenseAccepted(final String imageName) { // suppressed } - throw new IllegalStateException("The image " + imageName + " requires you to accept a license agreement. " + - "Please place a file at the root of the classpath named " + ACCEPTANCE_FILE_NAME + ", e.g. at " + - "src/test/resources/" + ACCEPTANCE_FILE_NAME + ". This file should contain the line:\n " + - imageName); - + throw new IllegalStateException( + "The image " + + imageName + + " requires you to accept a license agreement. " + + "Please place a file at the root of the classpath named " + + ACCEPTANCE_FILE_NAME + + ", e.g. at " + + "src/test/resources/" + + ACCEPTANCE_FILE_NAME + + ". This file should contain the line:\n " + + imageName + ); } } diff --git a/core/src/main/java/org/testcontainers/utility/LogUtils.java b/core/src/main/java/org/testcontainers/utility/LogUtils.java index ce27387490f..e5912563cd9 100644 --- a/core/src/main/java/org/testcontainers/utility/LogUtils.java +++ b/core/src/main/java/org/testcontainers/utility/LogUtils.java @@ -13,9 +13,6 @@ import java.io.IOException; import java.util.function.Consumer; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDERR; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; - /** * Provides utility methods for logging. */ @@ -31,11 +28,12 @@ public class LogUtils { * @param consumer a consumer of {@link OutputFrame}s * @param types types of {@link OutputFrame} to receive */ - public void followOutput(DockerClient dockerClient, - String containerId, - Consumer consumer, - OutputFrame.OutputType... types) { - + public void followOutput( + DockerClient dockerClient, + String containerId, + Consumer consumer, + OutputFrame.OutputType... types + ) { attachConsumer(dockerClient, containerId, consumer, true, types); } @@ -47,11 +45,8 @@ public void followOutput(DockerClient dockerClient, * @param containerId container ID to attach to * @param consumer a consumer of {@link OutputFrame}s */ - public void followOutput(DockerClient dockerClient, - String containerId, - Consumer consumer) { - - followOutput(dockerClient, containerId, consumer, STDOUT, STDERR); + public void followOutput(DockerClient dockerClient, String containerId, Consumer consumer) { + followOutput(dockerClient, containerId, consumer, OutputFrame.OutputType.STDOUT, OutputFrame.OutputType.STDERR); } /** @@ -63,16 +58,13 @@ public void followOutput(DockerClient dockerClient, * @return all previous output frames (stdout/stderr being separated by newline characters) */ @SneakyThrows(IOException.class) - public String getOutput(DockerClient dockerClient, - String containerId, - OutputFrame.OutputType... types) { - + public String getOutput(DockerClient dockerClient, String containerId, OutputFrame.OutputType... types) { if (containerId == null) { return ""; } if (types.length == 0) { - types = new OutputFrame.OutputType[] { STDOUT, STDERR }; + types = new OutputFrame.OutputType[] { OutputFrame.OutputType.STDOUT, OutputFrame.OutputType.STDERR }; } final ToStringConsumer consumer = new ToStringConsumer(); @@ -90,16 +82,20 @@ private static Closeable attachConsumer( boolean followStream, OutputFrame.OutputType... types ) { - - final LogContainerCmd cmd = dockerClient.logContainerCmd(containerId) + final LogContainerCmd cmd = dockerClient + .logContainerCmd(containerId) .withFollowStream(followStream) .withSince(0); final FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); for (OutputFrame.OutputType type : types) { callback.addConsumer(type, consumer); - if (type == STDOUT) cmd.withStdOut(true); - if (type == STDERR) cmd.withStdErr(true); + if (type == OutputFrame.OutputType.STDOUT) { + cmd.withStdOut(true); + } + if (type == OutputFrame.OutputType.STDERR) { + cmd.withStdErr(true); + } } return cmd.exec(callback); diff --git a/core/src/main/java/org/testcontainers/utility/MountableFile.java b/core/src/main/java/org/testcontainers/utility/MountableFile.java index 81cc37adeab..a8a9f465a19 100644 --- a/core/src/main/java/org/testcontainers/utility/MountableFile.java +++ b/core/src/main/java/org/testcontainers/utility/MountableFile.java @@ -1,7 +1,7 @@ package org.testcontainers.utility; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; +import lombok.AccessLevel; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @@ -34,23 +34,24 @@ import java.util.stream.Stream; import java.util.zip.Checksum; -import static lombok.AccessLevel.PACKAGE; -import static org.testcontainers.utility.PathUtils.recursiveDeleteDir; - /** * An abstraction over files and classpath resources aimed at encapsulating all the complexity of generating * a path that the Docker daemon is about to create a volume mount for. */ -@RequiredArgsConstructor(access = PACKAGE) +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) @Slf4j public class MountableFile implements Transferable { private static final String TESTCONTAINERS_TMP_DIR_PREFIX = ".testcontainers-tmp-"; + private static final String OS_MAC_TMP_DIR = "/tmp"; + private static final int BASE_FILE_MODE = 0100000; + private static final int BASE_DIR_MODE = 0040000; private final String path; + private final Integer forcedFileMode; @Getter(lazy = true) @@ -124,10 +125,11 @@ public static MountableFile forHostPath(final Path path, Integer mode) { return new MountableFile(path.toAbsolutePath().toString(), mode); } - @NotNull - private static URL getClasspathResource(@NotNull final String resourcePath, @NotNull final Set classLoaders) { - + private static URL getClasspathResource( + @NotNull final String resourcePath, + @NotNull final Set classLoaders + ) { final Set classLoadersToSearch = new HashSet<>(classLoaders); // try context and system classloaders as well classLoadersToSearch.add(Thread.currentThread().getContextClassLoader()); @@ -153,16 +155,22 @@ private static URL getClasspathResource(@NotNull final String resourcePath, @Not } } - throw new IllegalArgumentException("Resource with path " + resourcePath + " could not be found on any of these classloaders: " + classLoadersToSearch); + throw new IllegalArgumentException( + "Resource with path " + + resourcePath + + " could not be found on any of these classloaders: " + + classLoadersToSearch + ); } private static String unencodeResourceURIToFilePath(@NotNull final String resource) { try { // Convert any url-encoded characters (e.g. spaces) back into unencoded form - return URLDecoder.decode(resource.replaceAll("\\+", "%2B"), Charsets.UTF_8.name()) - .replaceFirst("jar:", "") - .replaceFirst("file:", "") - .replaceAll("!.*", ""); + return URLDecoder + .decode(resource.replaceAll("\\+", "%2B"), Charsets.UTF_8.name()) + .replaceFirst("jar:", "") + .replaceFirst("file:", "") + .replaceAll("!.*", ""); } catch (UnsupportedEncodingException e) { throw new IllegalStateException(e); } @@ -237,15 +245,19 @@ private String extractClassPathResourceToTempLocation(final String hostPath) { JarEntry entry = entries.nextElement(); final String name = entry.getName(); if (name.startsWith(internalPath)) { - log.debug("Copying classpath resource(s) from {} to {} to permit Docker to bind", - hostPath, - tmpLocation); + log.debug( + "Copying classpath resource(s) from {} to {} to permit Docker to bind", + hostPath, + tmpLocation + ); copyFromJarToLocation(jarFile, entry, internalPath, tmpLocation); } } - } catch (IOException e) { - throw new IllegalStateException("Failed to process JAR file when extracting classpath resource: " + hostPath, e); + throw new IllegalStateException( + "Failed to process JAR file when extracting classpath resource: " + hostPath, + e + ); } // Mark temporary files/dirs for deletion at JVM shutdown @@ -264,23 +276,22 @@ private File createTempDirectory() { return Files.createTempDirectory(Paths.get(OS_MAC_TMP_DIR), TESTCONTAINERS_TMP_DIR_PREFIX).toFile(); } return Files.createTempDirectory(TESTCONTAINERS_TMP_DIR_PREFIX).toFile(); - } catch (IOException e) { + } catch (IOException e) { return new File(TESTCONTAINERS_TMP_DIR_PREFIX + Base58.randomString(5)); } } @SuppressWarnings("ResultOfMethodCallIgnored") - private void copyFromJarToLocation(final JarFile jarFile, - final JarEntry entry, - final String fromRoot, - final File toRoot) throws IOException { - + private void copyFromJarToLocation( + final JarFile jarFile, + final JarEntry entry, + final String fromRoot, + final File toRoot + ) throws IOException { String destinationName = entry.getName().replaceFirst(fromRoot, ""); File newFile = new File(toRoot, destinationName); - log.debug("Copying resource {} from JAR file {}", - fromRoot, - jarFile.getName()); + log.debug("Copying resource {} from JAR file {}", fromRoot, jarFile.getName()); if (!entry.isDirectory()) { // Create parent directories @@ -291,14 +302,21 @@ private void copyFromJarToLocation(final JarFile jarFile, try (InputStream is = jarFile.getInputStream(entry)) { Files.copy(is, newFile.toPath()); } catch (IOException e) { - log.error("Failed to extract classpath resource " + entry.getName() + " from JAR file " + jarFile.getName(), e); + log.error( + "Failed to extract classpath resource " + entry.getName() + " from JAR file " + jarFile.getName(), + e + ); throw e; } } } private void deleteOnExit(final Path path) { - Runtime.getRuntime().addShutdownHook(new Thread(DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, () -> recursiveDeleteDir(path))); + Runtime + .getRuntime() + .addShutdownHook( + new Thread(DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, () -> PathUtils.recursiveDeleteDir(path)) + ); } /** @@ -312,11 +330,20 @@ public void transferTo(final TarArchiveOutputStream outputStream, String destina /* * Recursively copies a file/directory into a TarArchiveOutputStream */ - private void recursiveTar(String entryFilename, String rootPath, String itemPath, TarArchiveOutputStream tarArchive) { + private void recursiveTar( + String entryFilename, + String rootPath, + String itemPath, + TarArchiveOutputStream tarArchive + ) { try { - final File sourceFile = new File(itemPath).getCanonicalFile(); // e.g. /foo/bar/baz - final File sourceRootFile = new File(rootPath).getCanonicalFile(); // e.g. /foo - final String relativePathToSourceFile = sourceRootFile.toPath().relativize(sourceFile.toPath()).toFile().toString(); // e.g. /bar/baz + final File sourceFile = new File(itemPath).getCanonicalFile(); // e.g. /foo/bar/baz + final File sourceRootFile = new File(rootPath).getCanonicalFile(); // e.g. /foo + final String relativePathToSourceFile = sourceRootFile + .toPath() + .relativize(sourceFile.toPath()) + .toFile() + .toString(); // e.g. /bar/baz final String tarEntryFilename; if (relativePathToSourceFile.isEmpty()) { @@ -341,7 +368,12 @@ private void recursiveTar(String entryFilename, String rootPath, String itemPath if (children != null) { // recurse into child files/directories for (final File child : children) { - recursiveTar(entryFilename, sourceRootFile.getCanonicalPath(), child.getCanonicalPath(), tarArchive); + recursiveTar( + entryFilename, + sourceRootFile.getCanonicalPath(), + child.getCanonicalPath(), + tarArchive + ); } } } catch (IOException e) { @@ -352,7 +384,6 @@ private void recursiveTar(String entryFilename, String rootPath, String itemPath @Override public long getSize() { - final File file = new File(this.getResolvedPath()); if (file.isFile()) { return file.length(); @@ -378,9 +409,11 @@ private void checksumFile(File file, Checksum checksum) { checksum.update(MountableFile.getUnixFileMode(path)); if (file.isDirectory()) { try (Stream stream = Files.walk(path)) { - stream.filter(it -> it != path).forEach(it -> { - checksumFile(it.toFile(), checksum); - }); + stream + .filter(it -> it != path) + .forEach(it -> { + checksumFile(it.toFile(), checksum); + }); } } else { FileUtils.checksum(file, checksum); @@ -405,9 +438,11 @@ public static int getUnixFileMode(final Path path) { try { int unixMode = (int) Files.readAttributes(path, "unix:mode").get("mode"); // Truncate mode bits for z/OS - if ("OS/390".equals(SystemUtils.OS_NAME) || + if ( + "OS/390".equals(SystemUtils.OS_NAME) || "z/OS".equals(SystemUtils.OS_NAME) || - "zOS".equals(SystemUtils.OS_NAME) ) { + "zOS".equals(SystemUtils.OS_NAME) + ) { unixMode &= TarConstants.MAXID; unixMode |= Files.isDirectory(path) ? 040000 : 0100000; } diff --git a/core/src/main/java/org/testcontainers/utility/PathUtils.java b/core/src/main/java/org/testcontainers/utility/PathUtils.java index 2dcf9db8a8d..7f8b5925689 100644 --- a/core/src/main/java/org/testcontainers/utility/PathUtils.java +++ b/core/src/main/java/org/testcontainers/utility/PathUtils.java @@ -23,21 +23,23 @@ public class PathUtils { */ public static void recursiveDeleteDir(final @NonNull Path directory) { try { - Files.walkFileTree(directory, new SimpleFileVisitor() { - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } + Files.walkFileTree( + directory, + new SimpleFileVisitor() { + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } } - }); - } catch (IOException ignored) { - } + ); + } catch (IOException ignored) {} } /** @@ -66,8 +68,10 @@ public static String createMinGWPath(String path) { } // drive-letter must be lower case - mingwPath = "//" + Character.toLowerCase(mingwPath.charAt(driveLetterIndex)) + - mingwPath.substring(driveLetterIndex + 1); + mingwPath = + "//" + + Character.toLowerCase(mingwPath.charAt(driveLetterIndex)) + + mingwPath.substring(driveLetterIndex + 1); mingwPath = mingwPath.replace(":", ""); return mingwPath; } diff --git a/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java b/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java index c720416deac..7cf082000a4 100644 --- a/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java +++ b/core/src/main/java/org/testcontainers/utility/PrefixingImageNameSubstitutor.java @@ -38,11 +38,7 @@ public DockerImageName apply(DockerImageName original) { return original; } - log.debug( - "Applying changes to image name {}: applying prefix '{}'", - original, - configuredPrefix - ); + log.debug("Applying changes to image name {}: applying prefix '{}'", original, configuredPrefix); DockerImageName prefixAsImage = DockerImageName.parse(configuredPrefix); diff --git a/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java b/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java index e487bda686b..0001b926059 100644 --- a/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java +++ b/core/src/main/java/org/testcontainers/utility/RegistryAuthLocator.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.testcontainers.DockerClientFactory; import org.zeroturnaround.exec.InvalidResultException; import org.zeroturnaround.exec.ProcessExecutor; @@ -23,23 +24,23 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static org.apache.commons.lang3.StringUtils.isBlank; -import static org.slf4j.LoggerFactory.getLogger; -import static org.testcontainers.utility.AuthConfigUtil.toSafeString; - /** * Utility to look up registry authentication information for an image. */ public class RegistryAuthLocator { - private static final Logger log = getLogger(RegistryAuthLocator.class); + private static final Logger log = LoggerFactory.getLogger(RegistryAuthLocator.class); + private static final String DEFAULT_REGISTRY_NAME = "https://index.docker.io/v1/"; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static RegistryAuthLocator instance; private final String commandPathPrefix; + private final String commandExtension; + private final File configFile; private final Map> cache = new ConcurrentHashMap<>(); @@ -51,8 +52,12 @@ public class RegistryAuthLocator { private final Map CREDENTIALS_HELPERS_NOT_FOUND_MESSAGE_CACHE; @VisibleForTesting - RegistryAuthLocator(File configFile, String commandPathPrefix, String commandExtension, - Map notFoundMessageHolderReference) { + RegistryAuthLocator( + File configFile, + String commandPathPrefix, + String commandExtension, + Map notFoundMessageHolderReference + ) { this.configFile = configFile; this.commandPathPrefix = commandPathPrefix; this.commandExtension = commandExtension; @@ -63,8 +68,9 @@ public class RegistryAuthLocator { /** */ protected RegistryAuthLocator() { - final String dockerConfigLocation = System.getenv().getOrDefault("DOCKER_CONFIG", - System.getProperty("user.home") + "/.docker"); + final String dockerConfigLocation = System + .getenv() + .getOrDefault("DOCKER_CONFIG", System.getProperty("user.home") + "/.docker"); this.configFile = new File(dockerConfigLocation + "/config.json"); this.commandPathPrefix = ""; this.commandExtension = ""; @@ -72,7 +78,7 @@ protected RegistryAuthLocator() { this.CREDENTIALS_HELPERS_NOT_FOUND_MESSAGE_CACHE = new HashMap<>(); } - public synchronized static RegistryAuthLocator instance() { + public static synchronized RegistryAuthLocator instance() { if (instance == null) { instance = new RegistryAuthLocator(); } @@ -106,23 +112,31 @@ public AuthConfig lookupAuthConfig(DockerImageName dockerImageName, AuthConfig d final String registryName = effectiveRegistryName(dockerImageName); log.debug("Looking up auth config for image: {} at registry: {}", dockerImageName, registryName); - final Optional cachedAuth = cache.computeIfAbsent(registryName, __ -> lookupUncachedAuthConfig(registryName, dockerImageName)); + final Optional cachedAuth = cache.computeIfAbsent( + registryName, + __ -> lookupUncachedAuthConfig(registryName, dockerImageName) + ); if (cachedAuth.isPresent()) { - log.debug("Cached auth found: [{}]", toSafeString(cachedAuth.get())); + log.debug("Cached auth found: [{}]", AuthConfigUtil.toSafeString(cachedAuth.get())); return cachedAuth.get(); } else { - log.debug("No matching Auth Configs - falling back to defaultAuthConfig [{}]", toSafeString(defaultAuthConfig)); + log.debug( + "No matching Auth Configs - falling back to defaultAuthConfig [{}]", + AuthConfigUtil.toSafeString(defaultAuthConfig) + ); // otherwise, defaultAuthConfig should already contain any credentials available return defaultAuthConfig; } } private Optional lookupUncachedAuthConfig(String registryName, DockerImageName dockerImageName) { - log.debug("RegistryAuthLocator has configFile: {} ({}) and commandPathPrefix: {}", + log.debug( + "RegistryAuthLocator has configFile: {} ({}) and commandPathPrefix: {}", configFile, configFile.exists() ? "exists" : "does not exist", - commandPathPrefix); + commandPathPrefix + ); try { final JsonNode config = OBJECT_MAPPER.readTree(configFile); @@ -131,32 +145,33 @@ private Optional lookupUncachedAuthConfig(String registryName, Docke // use helper preferentially (per https://docs.docker.com/engine/reference/commandline/cli/) final AuthConfig helperAuthConfig = authConfigUsingHelper(config, registryName); if (helperAuthConfig != null) { - log.debug("found helper auth config [{}]", toSafeString(helperAuthConfig)); + log.debug("found helper auth config [{}]", AuthConfigUtil.toSafeString(helperAuthConfig)); return Optional.of(helperAuthConfig); } // no credsHelper to use, using credsStore: final AuthConfig storeAuthConfig = authConfigUsingStore(config, registryName); if (storeAuthConfig != null) { - log.debug("found creds store auth config [{}]", toSafeString(storeAuthConfig)); + log.debug("found creds store auth config [{}]", AuthConfigUtil.toSafeString(storeAuthConfig)); return Optional.of(storeAuthConfig); } // fall back to base64 encoded auth hardcoded in config file final AuthConfig existingAuthConfig = findExistingAuthConfig(config, registryName); if (existingAuthConfig != null) { - log.debug("found existing auth config [{}]", toSafeString(existingAuthConfig)); + log.debug("found existing auth config [{}]", AuthConfigUtil.toSafeString(existingAuthConfig)); return Optional.of(existingAuthConfig); } } catch (Exception e) { - log.info("Failure when attempting to lookup auth config. Please ignore if you don't have images in an authenticated registry. Details: (dockerImageName: {}, configFile: {}. Falling back to docker-java default behaviour. Exception message: {}", + log.info( + "Failure when attempting to lookup auth config. Please ignore if you don't have images in an authenticated registry. Details: (dockerImageName: {}, configFile: {}. Falling back to docker-java default behaviour. Exception message: {}", dockerImageName, configFile, - e.getMessage()); + e.getMessage() + ); } return Optional.empty(); } private AuthConfig findExistingAuthConfig(final JsonNode config, final String reposName) throws Exception { - final Map.Entry entry = findAuthNode(config, reposName); if (entry != null && entry.getValue() != null && entry.getValue().size() > 0) { @@ -164,10 +179,11 @@ private AuthConfig findExistingAuthConfig(final JsonNode config, final String re .treeToValue(entry.getValue(), AuthConfig.class) .withRegistryAddress(entry.getKey()); - if (isBlank(deserializedAuth.getUsername()) && - isBlank(deserializedAuth.getPassword()) && - !isBlank(deserializedAuth.getAuth())) { - + if ( + StringUtils.isBlank(deserializedAuth.getUsername()) && + StringUtils.isBlank(deserializedAuth.getPassword()) && + !StringUtils.isBlank(deserializedAuth.getAuth()) + ) { final String rawAuth = new String(Base64.getDecoder().decode(deserializedAuth.getAuth())); final String[] splitRawAuth = rawAuth.split(":", 2); @@ -198,7 +214,7 @@ private AuthConfig authConfigUsingStore(final JsonNode config, final String repo final JsonNode credsStoreNode = config.get("credsStore"); if (credsStoreNode != null && !credsStoreNode.isMissingNode() && credsStoreNode.isTextual()) { final String credsStore = credsStoreNode.asText(); - if (isBlank(credsStore)) { + if (StringUtils.isBlank(credsStore)) { log.warn("Docker auth config credsStore field will be ignored, because value is blank"); return null; } @@ -222,8 +238,7 @@ private Map.Entry findAuthNode(final JsonNode config, final St } private AuthConfig runCredentialProvider(String hostName, String helperOrStoreName) throws Exception { - - if (isBlank(hostName)) { + if (StringUtils.isBlank(hostName)) { log.debug("There is no point in locating AuthConfig for blank hostName. Returning NULL to allow fallback"); return null; } @@ -231,28 +246,34 @@ private AuthConfig runCredentialProvider(String hostName, String helperOrStoreNa final String credentialProgramName = getCredentialProgramName(helperOrStoreName); final String data; - log.debug("Executing docker credential provider: {} to locate auth config for: {}", - credentialProgramName, hostName); + log.debug( + "Executing docker credential provider: {} to locate auth config for: {}", + credentialProgramName, + hostName + ); try { data = runCredentialProgram(hostName, credentialProgramName); } catch (InvalidResultException e) { - final String responseErrorMsg = extractCredentialProviderErrorMessage(e); - if (!isBlank(responseErrorMsg)) { + if (!StringUtils.isBlank(responseErrorMsg)) { String credentialsNotFoundMsg = getGenericCredentialsNotFoundMsg(credentialProgramName); if (credentialsNotFoundMsg != null && credentialsNotFoundMsg.equals(responseErrorMsg)) { - log.info("Credential helper/store ({}) does not have credentials for {}", + log.info( + "Credential helper/store ({}) does not have credentials for {}", credentialProgramName, - hostName); + hostName + ); return null; } - log.debug("Failure running docker credential helper/store ({}) with output '{}'", - credentialProgramName, responseErrorMsg); - + log.debug( + "Failure running docker credential helper/store ({}) with output '{}'", + credentialProgramName, + responseErrorMsg + ); } else { log.debug("Failure running docker credential helper/store ({})", credentialProgramName); } @@ -296,7 +317,7 @@ private String effectiveRegistryName(DockerImageName dockerImageName) { private String getGenericCredentialsNotFoundMsg(String credentialHelperName) { if (!CREDENTIALS_HELPERS_NOT_FOUND_MESSAGE_CACHE.containsKey(credentialHelperName)) { String credentialsNotFoundMsg = discoverCredentialsHelperNotFoundMessage(credentialHelperName); - if (!isBlank(credentialsNotFoundMsg)) { + if (!StringUtils.isBlank(credentialsNotFoundMsg)) { CREDENTIALS_HELPERS_NOT_FOUND_MESSAGE_CACHE.put(credentialHelperName, credentialsNotFoundMsg); } } @@ -317,19 +338,26 @@ private String discoverCredentialsHelperNotFoundMessage(String credentialHelperN runCredentialProgram(notExistentFakeHostName, credentialHelperName); // should not reach here - log.warn("Failure running docker credential helper ({}) with fake call, expected 'credentials not found' response", - credentialHelperName); - } catch(Exception e) { + log.warn( + "Failure running docker credential helper ({}) with fake call, expected 'credentials not found' response", + credentialHelperName + ); + } catch (Exception e) { if (e instanceof InvalidResultException) { - credentialsNotFoundMsg = extractCredentialProviderErrorMessage((InvalidResultException)e); + credentialsNotFoundMsg = extractCredentialProviderErrorMessage((InvalidResultException) e); } - if (isBlank(credentialsNotFoundMsg)) { - log.warn("Failure running docker credential helper ({}) with fake call, expected 'credentials not found' response. Exception message: {}", + if (StringUtils.isBlank(credentialsNotFoundMsg)) { + log.warn( + "Failure running docker credential helper ({}) with fake call, expected 'credentials not found' response. Exception message: {}", credentialHelperName, - e.getMessage()); + e.getMessage() + ); } else { - log.debug("Got credentials not found error message from docker credential helper - {}", credentialsNotFoundMsg); + log.debug( + "Got credentials not found error message from docker credential helper - {}", + credentialsNotFoundMsg + ); } } @@ -345,16 +373,17 @@ private String extractCredentialProviderErrorMessage(InvalidResultException inva private String runCredentialProgram(String hostName, String credentialHelperName) throws InvalidResultException, InterruptedException, TimeoutException, IOException { - - String[] command = SystemUtils.IS_OS_WINDOWS ? new String[] {"cmd", "/c", credentialHelperName, "get"} : new String[]{credentialHelperName, "get"}; + String[] command = SystemUtils.IS_OS_WINDOWS + ? new String[] { "cmd", "/c", credentialHelperName, "get" } + : new String[] { credentialHelperName, "get" }; return new ProcessExecutor() - .command(command) - .redirectInput(new ByteArrayInputStream(hostName.getBytes())) - .readOutput(true) - .exitValueNormal() - .timeout(30, TimeUnit.SECONDS) - .execute() - .outputUTF8() - .trim(); + .command(command) + .redirectInput(new ByteArrayInputStream(hostName.getBytes())) + .readOutput(true) + .exitValueNormal() + .timeout(30, TimeUnit.SECONDS) + .execute() + .outputUTF8() + .trim(); } } diff --git a/core/src/main/java/org/testcontainers/utility/ResourceReaper.java b/core/src/main/java/org/testcontainers/utility/ResourceReaper.java index d916579db35..ad0c949f6e7 100644 --- a/core/src/main/java/org/testcontainers/utility/ResourceReaper.java +++ b/core/src/main/java/org/testcontainers/utility/ResourceReaper.java @@ -49,29 +49,30 @@ public class ResourceReaper { static final List>> DEATH_NOTE = new ArrayList<>( Arrays.asList( Stream - .concat( - DockerClientFactory.DEFAULT_LABELS.entrySet().stream(), - MARKER_LABELS.entrySet().stream() - ) + .concat(DockerClientFactory.DEFAULT_LABELS.entrySet().stream(), MARKER_LABELS.entrySet().stream()) .>map(it -> new SimpleEntry<>("label", it.getKey() + "=" + it.getValue())) .collect(Collectors.toList()) ) ); private static ResourceReaper instance; + final DockerClient dockerClient = DockerClientFactory.lazyClient(); + private Map registeredContainers = new ConcurrentHashMap<>(); + private Set registeredNetworks = Sets.newConcurrentHashSet(); + private Set registeredImages = Sets.newConcurrentHashSet(); + private AtomicBoolean hookIsSet = new AtomicBoolean(false); /** * Internal constructor to avoid custom implementations */ - ResourceReaper() { - } + ResourceReaper() {} - public synchronized static ResourceReaper instance() { + public static synchronized ResourceReaper instance() { if (instance == null) { boolean useRyuk = !Boolean.parseBoolean(System.getenv("TESTCONTAINERS_RYUK_DISABLED")); if (useRyuk) { @@ -117,7 +118,9 @@ public void registerFilterForCleanup(List> filter) { */ public void registerLabelsFilterForCleanup(Map labels) { registerFilterForCleanup( - labels.entrySet().stream() + labels + .entrySet() + .stream() .map(it -> new SimpleEntry<>("label", it.getKey() + "=" + it.getValue())) .collect(Collectors.toList()) ); @@ -172,9 +175,11 @@ private void removeContainer(String containerId, String imageName) { LOGGER.trace("Was going to stop container but it apparently no longer exists: {}", containerId); return; } catch (Exception e) { - LOGGER.trace("Error encountered when checking container for shutdown (ID: {}) - it may not have been stopped, or may already be stopped. Root cause: {}", + LOGGER.trace( + "Error encountered when checking container for shutdown (ID: {}) - it may not have been stopped, or may already be stopped. Root cause: {}", containerId, - Throwables.getRootCause(e).getMessage()); + Throwables.getRootCause(e).getMessage() + ); return; } @@ -184,9 +189,11 @@ private void removeContainer(String containerId, String imageName) { dockerClient.killContainerCmd(containerId).exec(); LOGGER.trace("Stopped container: {}", imageName); } catch (Exception e) { - LOGGER.trace("Error encountered shutting down container (ID: {}) - it may not have been stopped, or may already be stopped. Root cause: {}", + LOGGER.trace( + "Error encountered shutting down container (ID: {}) - it may not have been stopped, or may already be stopped. Root cause: {}", containerId, - Throwables.getRootCause(e).getMessage()); + Throwables.getRootCause(e).getMessage() + ); } } @@ -202,9 +209,11 @@ private void removeContainer(String containerId, String imageName) { dockerClient.removeContainerCmd(containerId).withRemoveVolumes(true).withForce(true).exec(); LOGGER.debug("Removed container and associated volume(s): {}", imageName); } catch (Exception e) { - LOGGER.trace("Error encountered shutting down container (ID: {}) - it may not have been stopped, or may already be stopped. Root cause: {}", + LOGGER.trace( + "Error encountered shutting down container (ID: {}) - it may not have been stopped, or may already be stopped. Root cause: {}", containerId, - Throwables.getRootCause(e).getMessage()); + Throwables.getRootCause(e).getMessage() + ); } } @@ -227,10 +236,9 @@ public void registerNetworkIdForCleanup(String id) { */ @Deprecated public void removeNetworkById(String id) { - removeNetwork(id); + removeNetwork(id); } - private void removeNetwork(String id) { try { List networks; @@ -239,7 +247,10 @@ private void removeNetwork(String id) { // Listing by ID first prevents docker-java logging an error if we just go blindly into removeNetworkCmd networks = dockerClient.listNetworksCmd().withIdFilter(id).exec(); } catch (Exception e) { - LOGGER.trace("Error encountered when looking up network for removal (name: {}) - it may not have been removed", id); + LOGGER.trace( + "Error encountered when looking up network for removal (name: {}) - it may not have been removed", + id + ); return; } @@ -251,7 +262,10 @@ private void removeNetwork(String id) { registeredNetworks.remove(network.getId()); LOGGER.debug("Removed network: {}", id); } catch (Exception e) { - LOGGER.trace("Error encountered removing network (name: {}) - it may not have been removed", network.getName()); + LOGGER.trace( + "Error encountered removing network (name: {}) - it may not have been removed", + network.getName() + ); } } } finally { @@ -296,7 +310,9 @@ private void removeImage(String dockerImageName) { void setHook() { if (hookIsSet.compareAndSet(false, true)) { // If the JVM stops without containers being stopped, try and stop the container. - Runtime.getRuntime().addShutdownHook(new Thread(DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, this::performCleanup)); + Runtime + .getRuntime() + .addShutdownHook(new Thread(DockerClientFactory.TESTCONTAINERS_THREAD_GROUP, this::performCleanup)); } } @@ -323,8 +339,7 @@ public CreateContainerCmd register(GenericContainer container, CreateContaine * @deprecated internal API */ @Deprecated - public void init() { - } + public void init() {} static class FilterRegistry { @@ -332,6 +347,7 @@ static class FilterRegistry { static final String ACKNOWLEDGMENT = "ACK"; private final BufferedReader in; + private final OutputStream out; FilterRegistry(InputStream ryukInputStream, OutputStream ryukOutputStream) { @@ -347,10 +363,13 @@ static class FilterRegistry { * @throws IOException if communication with Ryuk fails */ protected boolean register(List> filters) throws IOException { - String query = filters.stream() + String query = filters + .stream() .map(it -> { try { - return URLEncoder.encode(it.getKey(), "UTF-8") + "=" + URLEncoder.encode(it.getValue(), "UTF-8"); + return ( + URLEncoder.encode(it.getKey(), "UTF-8") + "=" + URLEncoder.encode(it.getValue(), "UTF-8") + ); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } @@ -372,6 +391,5 @@ private static boolean waitForAcknowledgment(BufferedReader in) throws IOExcepti } return ACKNOWLEDGMENT.equalsIgnoreCase(line); } - } } diff --git a/core/src/main/java/org/testcontainers/utility/RyukContainer.java b/core/src/main/java/org/testcontainers/utility/RyukContainer.java index 1e18c14157a..511e6ccac17 100644 --- a/core/src/main/java/org/testcontainers/utility/RyukContainer.java +++ b/core/src/main/java/org/testcontainers/utility/RyukContainer.java @@ -10,15 +10,20 @@ class RyukContainer extends GenericContainer { RyukContainer() { super("testcontainers/ryuk:0.3.3"); - withExposedPorts(8080); withCreateContainerCmdModifier(cmd -> { cmd.withName("testcontainers-ryuk-" + DockerClientFactory.SESSION_ID); cmd.withHostConfig( - cmd.getHostConfig() + cmd + .getHostConfig() .withAutoRemove(true) .withPrivileged(TestcontainersConfiguration.getInstance().isRyukPrivileged()) - .withBinds(new Bind(DockerClientFactory.instance().getRemoteDockerUnixSocketPath(), new Volume("/var/run/docker.sock"))) + .withBinds( + new Bind( + DockerClientFactory.instance().getRemoteDockerUnixSocketPath(), + new Volume("/var/run/docker.sock") + ) + ) ); }); diff --git a/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java b/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java index 6ce9c372fd2..999b1cbbffb 100644 --- a/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java +++ b/core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java @@ -90,7 +90,10 @@ private synchronized void maybeStart() { // not set the read timeout, as Ryuk would not send anything unless a new filter is submitted, meaning that we would get a timeout exception pretty quick try (Socket clientSocket = new Socket()) { clientSocket.connect(new InetSocketAddress(host, ryukPort), 5 * 1000); - ResourceReaper.FilterRegistry registry = new ResourceReaper.FilterRegistry(clientSocket.getInputStream(), clientSocket.getOutputStream()); + ResourceReaper.FilterRegistry registry = new ResourceReaper.FilterRegistry( + clientSocket.getInputStream(), + clientSocket.getOutputStream() + ); synchronized (ResourceReaper.DEATH_NOTE) { while (true) { diff --git a/core/src/main/java/org/testcontainers/utility/TestEnvironment.java b/core/src/main/java/org/testcontainers/utility/TestEnvironment.java index dbd8e45a98f..ee58199540b 100644 --- a/core/src/main/java/org/testcontainers/utility/TestEnvironment.java +++ b/core/src/main/java/org/testcontainers/utility/TestEnvironment.java @@ -8,8 +8,7 @@ */ public class TestEnvironment { - private TestEnvironment() { - } + private TestEnvironment() {} public static boolean dockerApiAtLeast(String minimumVersion) { ComparableVersion min = new ComparableVersion(minimumVersion); @@ -29,4 +28,3 @@ public static boolean dockerIsDockerMachine() { return DockerClientFactory.instance().isUsing(DockerMachineClientProviderStrategy.class); } } - diff --git a/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java b/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java index c9dfd543ad6..e647a8d50b3 100644 --- a/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java +++ b/core/src/main/java/org/testcontainers/utility/TestcontainersConfiguration.java @@ -50,18 +50,29 @@ public class TestcontainersConfiguration { private static File USER_CONFIG_FILE = new File(System.getProperty("user.home"), "." + PROPERTIES_FILE_NAME); private static final String AMBASSADOR_IMAGE = "richnorth/ambassador"; + private static final String SOCAT_IMAGE = "alpine/socat"; + private static final String VNC_RECORDER_IMAGE = "testcontainers/vnc-recorder"; + private static final String COMPOSE_IMAGE = "docker/compose"; + private static final String ALPINE_IMAGE = "alpine"; + private static final String RYUK_IMAGE = "testcontainers/ryuk"; + private static final String KAFKA_IMAGE = "confluentinc/cp-kafka"; + private static final String PULSAR_IMAGE = "apachepulsar/pulsar"; + private static final String LOCALSTACK_IMAGE = "localstack/localstack"; + private static final String SSHD_IMAGE = "testcontainers/sshd"; + private static final String ORACLE_IMAGE = "gvenzl/oracle-xe"; - private static final ImmutableMap CONTAINER_MAPPING = ImmutableMap.builder() + private static final ImmutableMap CONTAINER_MAPPING = ImmutableMap + .builder() .put(DockerImageName.parse(AMBASSADOR_IMAGE), "ambassador.container.image") .put(DockerImageName.parse(SOCAT_IMAGE), "socat.container.image") .put(DockerImageName.parse(VNC_RECORDER_IMAGE), "vncrecorder.container.image") @@ -78,7 +89,7 @@ public class TestcontainersConfiguration { @Getter(lazy = true) private static final TestcontainersConfiguration instance = loadConfiguration(); - @SuppressWarnings({"ConstantConditions", "unchecked", "rawtypes"}) + @SuppressWarnings({ "ConstantConditions", "unchecked", "rawtypes" }) @VisibleForTesting static AtomicReference getInstanceField() { // Lazy Getter from Lombok changes the field's type to AtomicReference @@ -86,10 +97,16 @@ static AtomicReference getInstanceField() { } private final Properties userProperties; + private final Properties classpathProperties; + private final Map environment; - TestcontainersConfiguration(Properties userProperties, Properties classpathProperties, final Map environment) { + TestcontainersConfiguration( + Properties userProperties, + Properties classpathProperties, + final Map environment + ) { this.userProperties = userProperties; this.classpathProperties = classpathProperties; this.environment = environment; @@ -121,8 +138,7 @@ public String getTinyImage() { } public boolean isRyukPrivileged() { - return Boolean - .parseBoolean(getEnvVarOrProperty("ryuk.container.privileged", "false")); + return Boolean.parseBoolean(getEnvVarOrProperty("ryuk.container.privileged", "false")); } @Deprecated @@ -203,7 +219,11 @@ public Integer getClientPingTimeout() { @Nullable @Contract("_, !null, _ -> !null") - private String getConfigurable(@NotNull final String propertyName, @Nullable final String defaultValue, Properties... propertiesSources) { + private String getConfigurable( + @NotNull final String propertyName, + @Nullable final String defaultValue, + Properties... propertiesSources + ) { String envVarName = propertyName.replaceAll("\\.", "_").toUpperCase(); if (!envVarName.startsWith("TESTCONTAINERS_") && !envVarName.startsWith("DOCKER_")) { envVarName = "TESTCONTAINERS_" + envVarName; @@ -279,11 +299,15 @@ public String getUserProperty(@NotNull final String propertyName, @Nullable fina */ @Deprecated public Properties getProperties() { - return Stream.of(userProperties, classpathProperties) - .reduce(new Properties(), (a, b) -> { - a.putAll(b); - return a; - }); + return Stream + .of(userProperties, classpathProperties) + .reduce( + new Properties(), + (a, b) -> { + a.putAll(b); + return a; + } + ); } @Deprecated @@ -318,15 +342,20 @@ public boolean updateUserConfig(@NonNull String prop, @NonNull String value) { private static TestcontainersConfiguration loadConfiguration() { return new TestcontainersConfiguration( readProperties(USER_CONFIG_FILE.toURI().toURL()), - ClasspathScanner.scanFor(PROPERTIES_FILE_NAME) + ClasspathScanner + .scanFor(PROPERTIES_FILE_NAME) .map(TestcontainersConfiguration::readProperties) - .reduce(new Properties(), (a, b) -> { - // first-write-wins merging - URLs appearing first on the classpath alphabetically will take priority. - // Note that this means that file: URLs will always take priority over jar: URLs. - b.putAll(a); - return b; - }), - System.getenv()); + .reduce( + new Properties(), + (a, b) -> { + // first-write-wins merging - URLs appearing first on the classpath alphabetically will take priority. + // Note that this means that file: URLs will always take priority over jar: URLs. + b.putAll(a); + return b; + } + ), + System.getenv() + ); } private static Properties readProperties(URL url) { @@ -335,9 +364,17 @@ private static Properties readProperties(URL url) { try (InputStream inputStream = url.openStream()) { properties.load(inputStream); } catch (FileNotFoundException e) { - log.warn("Attempted to read Testcontainers configuration file at {} but the file was not found. Exception message: {}", url, ExceptionUtils.getRootCauseMessage(e)); + log.warn( + "Attempted to read Testcontainers configuration file at {} but the file was not found. Exception message: {}", + url, + ExceptionUtils.getRootCauseMessage(e) + ); } catch (IOException e) { - log.warn("Attempted to read Testcontainers configuration file at {} but could it not be loaded. Exception message: {}", url, ExceptionUtils.getRootCauseMessage(e)); + log.warn( + "Attempted to read Testcontainers configuration file at {} but could it not be loaded. Exception message: {}", + url, + ExceptionUtils.getRootCauseMessage(e) + ); } return properties; } @@ -349,14 +386,14 @@ private DockerImageName getImage(final String defaultValue) { DockerImageName getConfiguredSubstituteImage(DockerImageName original) { for (final Map.Entry entry : CONTAINER_MAPPING.entrySet()) { if (original.isCompatibleWith(entry.getKey())) { - return - Optional.ofNullable(entry.getValue()) - .map(propertyName -> getEnvVarOrProperty(propertyName, null)) - .map(String::valueOf) - .map(String::trim) - .map(DockerImageName::parse) - .orElse(original) - .asCompatibleSubstituteFor(original); + return Optional + .ofNullable(entry.getValue()) + .map(propertyName -> getEnvVarOrProperty(propertyName, null)) + .map(String::valueOf) + .map(String::trim) + .map(DockerImageName::parse) + .orElse(original) + .asCompatibleSubstituteFor(original); } } return original; diff --git a/core/src/main/java/org/testcontainers/utility/ThrowingFunction.java b/core/src/main/java/org/testcontainers/utility/ThrowingFunction.java index 6b2cef907e1..a8138f9dda0 100644 --- a/core/src/main/java/org/testcontainers/utility/ThrowingFunction.java +++ b/core/src/main/java/org/testcontainers/utility/ThrowingFunction.java @@ -1,6 +1,5 @@ package org.testcontainers.utility; public interface ThrowingFunction { - R apply(T t) throws Exception; } diff --git a/core/src/main/java/org/testcontainers/utility/Versioning.java b/core/src/main/java/org/testcontainers/utility/Versioning.java index 4b1da407440..372a105518f 100644 --- a/core/src/main/java/org/testcontainers/utility/Versioning.java +++ b/core/src/main/java/org/testcontainers/utility/Versioning.java @@ -45,8 +45,11 @@ public int hashCode() { @EqualsAndHashCode class TagVersioning implements Versioning { + public static final String TAG_REGEX = "[\\w][\\w.\\-]{0,127}"; + static final TagVersioning LATEST = new TagVersioning("latest"); + private final String tag; TagVersioning(String tag) { @@ -71,7 +74,9 @@ public String toString() { @EqualsAndHashCode class Sha256Versioning implements Versioning { + public static final String HASH_REGEX = "[0-9a-fA-F]{32,}"; + private final String hash; Sha256Versioning(String hash) { diff --git a/core/src/test/java/alt/testcontainers/images/OutOfPackageImagePullPolicyTest.java b/core/src/test/java/alt/testcontainers/images/OutOfPackageImagePullPolicyTest.java index e4197c7c1f6..168932106fb 100644 --- a/core/src/test/java/alt/testcontainers/images/OutOfPackageImagePullPolicyTest.java +++ b/core/src/test/java/alt/testcontainers/images/OutOfPackageImagePullPolicyTest.java @@ -1,29 +1,30 @@ package alt.testcontainers.images; import org.junit.Test; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.images.AbstractImagePullPolicy; import org.testcontainers.images.ImageData; import org.testcontainers.utility.DockerImageName; -import static org.testcontainers.TestImages.TINY_IMAGE; - public class OutOfPackageImagePullPolicyTest { + @Test public void shouldSupportCustomPoliciesOutOfTestContainersPackage() { try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) - .withImagePullPolicy(new AbstractImagePullPolicy() { - @Override - protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) { - return false; + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) + .withImagePullPolicy( + new AbstractImagePullPolicy() { + @Override + protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) { + return false; + } } - }) + ) ) { container.withStartupCheckStrategy(new OneShotStartupCheckStrategy()); container.start(); } } - } diff --git a/core/src/test/java/org/testcontainers/DaemonTest.java b/core/src/test/java/org/testcontainers/DaemonTest.java index f08614c8cdc..c1a1c20d60a 100644 --- a/core/src/test/java/org/testcontainers/DaemonTest.java +++ b/core/src/test/java/org/testcontainers/DaemonTest.java @@ -10,7 +10,6 @@ import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; -import static org.testcontainers.TestImages.TINY_IMAGE; /** * This test forks a new JVM, otherwise it's not possible to reliably diff the threads @@ -23,7 +22,7 @@ public static void main(String[] args) { GenericContainer genericContainer = null; try { - genericContainer = new GenericContainer<>(TINY_IMAGE).withCommand("top"); + genericContainer = new GenericContainer<>(TestImages.TINY_IMAGE).withCommand("top"); genericContainer.start(); Set threads = new HashSet<>(Thread.getAllStackTraces().keySet()); @@ -34,11 +33,14 @@ public static void main(String[] args) { if (nonDaemonThreads.isEmpty()) { VisibleAssertions.pass("All threads marked as daemon"); } else { - String nonDaemonThreadNames = nonDaemonThreads.stream() + String nonDaemonThreadNames = nonDaemonThreads + .stream() .map(Thread::getName) .collect(Collectors.joining("\n", "\n", "")); - VisibleAssertions.fail("Expected all threads to be daemons but the following are not:\n" + nonDaemonThreadNames); + VisibleAssertions.fail( + "Expected all threads to be daemons but the following are not:\n" + nonDaemonThreadNames + ); } } finally { if (genericContainer != null) { diff --git a/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java b/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java index a889764579f..794bbbc37c9 100644 --- a/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java +++ b/core/src/test/java/org/testcontainers/DockerClientFactoryTest.java @@ -28,11 +28,13 @@ public void runCommandInsideDockerShouldNotFailIfImageDoesNotExistsLocally() { dockFactory.runInsideDocker( imageName, cmd -> cmd.withCmd("sh", "-c", "echo 'SUCCESS'"), - (client, id) -> - client.logContainerCmd(id) + (client, id) -> { + return client + .logContainerCmd(id) .withStdOut(true) .exec(new LogToStringContainerCallback()) - .toString() + .toString(); + } ); } } diff --git a/core/src/test/java/org/testcontainers/DockerRegistryContainer.java b/core/src/test/java/org/testcontainers/DockerRegistryContainer.java index 4018b2b954d..a907c674386 100644 --- a/core/src/test/java/org/testcontainers/DockerRegistryContainer.java +++ b/core/src/test/java/org/testcontainers/DockerRegistryContainer.java @@ -51,22 +51,30 @@ protected void containerIsStarting(InspectContainerResponse containerInfo) { WaitingConsumer waitingConsumer = new WaitingConsumer(); resultCallback.addConsumer(OutputFrame.OutputType.STDERR, waitingConsumer); - dockerClient.logContainerCmd(containerInfo.getId()) + dockerClient + .logContainerCmd(containerInfo.getId()) .withStdErr(true) .withFollowStream(true) .exec(resultCallback); - Pattern pattern = Pattern.compile(".*listening on .*:(\\d+).*", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); - waitingConsumer.waitUntil(it -> { - String s = it.getUtf8String(); - Matcher matcher = pattern.matcher(s); - if (matcher.matches()) { - port.set(Integer.parseInt(matcher.group(1))); - return true; - } else { - return false; - } - }, 10, TimeUnit.SECONDS); + Pattern pattern = Pattern.compile( + ".*listening on .*:(\\d+).*", + Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE + ); + waitingConsumer.waitUntil( + it -> { + String s = it.getUtf8String(); + Matcher matcher = pattern.matcher(s); + if (matcher.matches()) { + port.set(Integer.parseInt(matcher.group(1))); + return true; + } else { + return false; + } + }, + 10, + TimeUnit.SECONDS + ); } endpoint = getHost() + ":" + port.get(); @@ -87,12 +95,15 @@ public DockerImageName createImage(String originalImage, String tag) { String dummyImageId = client.inspectImageCmd(originalImage).exec().getId(); - DockerImageName imageName = DockerImageName.parse(getEndpoint() + "/" + Base58.randomString(6).toLowerCase()).withTag(tag); + DockerImageName imageName = DockerImageName + .parse(getEndpoint() + "/" + Base58.randomString(6).toLowerCase()) + .withTag(tag); // push the image to the registry client.tagImageCmd(dummyImageId, imageName.asCanonicalNameString(), tag).exec(); - client.pushImageCmd(imageName.asCanonicalNameString()) + client + .pushImageCmd(imageName.asCanonicalNameString()) .exec(new ResultCallback.Adapter<>()) .awaitCompletion(1, TimeUnit.MINUTES); diff --git a/core/src/test/java/org/testcontainers/containers/ContainerStateTest.java b/core/src/test/java/org/testcontainers/containers/ContainerStateTest.java index 52296678fd4..4909e908713 100644 --- a/core/src/test/java/org/testcontainers/containers/ContainerStateTest.java +++ b/core/src/test/java/org/testcontainers/containers/ContainerStateTest.java @@ -5,10 +5,9 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import java.util.Collections; import java.util.List; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -18,21 +17,22 @@ public class ContainerStateTest { @Parameterized.Parameters(name = "{0} ({1} -> {2})") public static Object[][] params() { - return new Object[][]{ - new Object[]{"regular mapping", "80:8080/tcp", singletonList(80),}, - new Object[]{"regular mapping with host", "127.0.0.1:80:8080/tcp", singletonList(80),}, - new Object[]{"zero port without host", ":0:8080/tcp", emptyList(),}, - new Object[]{"missing port with host", "0.0.0.0:0:8080/tcp", emptyList(),}, - new Object[]{"zero port (synthetic case)", "0:8080/tcp", emptyList(),}, - new Object[]{"missing port", ":8080/tcp", emptyList(), - } + return new Object[][] { + new Object[] { "regular mapping", "80:8080/tcp", Collections.singletonList(80) }, + new Object[] { "regular mapping with host", "127.0.0.1:80:8080/tcp", Collections.singletonList(80) }, + new Object[] { "zero port without host", ":0:8080/tcp", Collections.emptyList() }, + new Object[] { "missing port with host", "0.0.0.0:0:8080/tcp", Collections.emptyList() }, + new Object[] { "zero port (synthetic case)", "0:8080/tcp", Collections.emptyList() }, + new Object[] { "missing port", ":8080/tcp", Collections.emptyList() }, }; } @Parameterized.Parameter(0) public String name; + @Parameterized.Parameter(1) public String testSet; + @Parameterized.Parameter(2) public List expectedResult; @@ -41,7 +41,7 @@ public void test() { ContainerState containerState = mock(ContainerState.class); doCallRealMethod().when(containerState).getBoundPortNumbers(); - when(containerState.getPortBindings()).thenReturn(singletonList(testSet)); + when(containerState.getPortBindings()).thenReturn(Collections.singletonList(testSet)); List result = containerState.getBoundPortNumbers(); Assertions.assertThat(result).hasSameElementsAs(expectedResult); diff --git a/core/src/test/java/org/testcontainers/containers/DockerComposeContainerWithServicesTest.java b/core/src/test/java/org/testcontainers/containers/DockerComposeContainerWithServicesTest.java index 8927972e642..8f056de98fa 100644 --- a/core/src/test/java/org/testcontainers/containers/DockerComposeContainerWithServicesTest.java +++ b/core/src/test/java/org/testcontainers/containers/DockerComposeContainerWithServicesTest.java @@ -9,17 +9,20 @@ import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; - public class DockerComposeContainerWithServicesTest { - public static final File SIMPLE_COMPOSE_FILE = new File("src/test/resources/compose-scaling-multiple-containers.yml"); - public static final File COMPOSE_FILE_WITH_INLINE_SCALE = new File("src/test/resources/compose-with-inline-scale-test.yml"); + public static final File SIMPLE_COMPOSE_FILE = new File( + "src/test/resources/compose-scaling-multiple-containers.yml" + ); + + public static final File COMPOSE_FILE_WITH_INLINE_SCALE = new File( + "src/test/resources/compose-with-inline-scale-test.yml" + ); @Test public void testDesiredSubsetOfServicesAreStarted() { try ( - DockerComposeContainer compose = new DockerComposeContainer<>(SIMPLE_COMPOSE_FILE) - .withServices("redis") + DockerComposeContainer compose = new DockerComposeContainer<>(SIMPLE_COMPOSE_FILE).withServices("redis") ) { compose.start(); @@ -67,9 +70,7 @@ public void testDesiredSubsetOfSpecifiedOrScaledServicesAreStarted() { @Test public void testAllServicesAreStartedIfNotSpecified() { - try ( - DockerComposeContainer compose = new DockerComposeContainer<>(SIMPLE_COMPOSE_FILE) - ) { + try (DockerComposeContainer compose = new DockerComposeContainer<>(SIMPLE_COMPOSE_FILE)) { compose.start(); verifyStartedContainers(compose, "redis_1", "other_1"); @@ -78,9 +79,7 @@ public void testAllServicesAreStartedIfNotSpecified() { @Test public void testScaleInComposeFileIsRespected() { - try ( - DockerComposeContainer compose = new DockerComposeContainer<>(COMPOSE_FILE_WITH_INLINE_SCALE) - ) { + try (DockerComposeContainer compose = new DockerComposeContainer<>(COMPOSE_FILE_WITH_INLINE_SCALE)) { compose.start(); // the compose file includes `scale: 3` for the redis container @@ -89,17 +88,20 @@ public void testScaleInComposeFileIsRespected() { } private void verifyStartedContainers(final DockerComposeContainer compose, final String... names) { - final List containerNames = compose.listChildContainers().stream() + final List containerNames = compose + .listChildContainers() + .stream() .flatMap(container -> Stream.of(container.getNames())) .collect(Collectors.toList()); - assertEquals("number of running services of docker-compose is the same as length of listOfServices", - names.length, containerNames.size()); + assertEquals( + "number of running services of docker-compose is the same as length of listOfServices", + names.length, + containerNames.size() + ); for (final String expectedName : names) { - final long matches = containerNames.stream() - .filter(foundName -> foundName.endsWith(expectedName)) - .count(); + final long matches = containerNames.stream().filter(foundName -> foundName.endsWith(expectedName)).count(); assertEquals("container with name starting '" + expectedName + "' should be running", 1L, matches); } diff --git a/core/src/test/java/org/testcontainers/containers/DockerComposeFilesTest.java b/core/src/test/java/org/testcontainers/containers/DockerComposeFilesTest.java index c47db0c4b66..6e1630f005f 100644 --- a/core/src/test/java/org/testcontainers/containers/DockerComposeFilesTest.java +++ b/core/src/test/java/org/testcontainers/containers/DockerComposeFilesTest.java @@ -1,25 +1,33 @@ package org.testcontainers.containers; - import com.google.common.collect.Lists; -import java.io.File; import org.assertj.core.api.Assertions; import org.junit.Test; +import java.io.File; + public class DockerComposeFilesTest { + @Test public void shouldGetDependencyImages() { - DockerComposeFiles dockerComposeFiles = new DockerComposeFiles(Lists.newArrayList(new File("src/test/resources/docker-compose-imagename-parsing-v2.yml"))); - Assertions.assertThat(dockerComposeFiles.getDependencyImages()) + DockerComposeFiles dockerComposeFiles = new DockerComposeFiles( + Lists.newArrayList(new File("src/test/resources/docker-compose-imagename-parsing-v2.yml")) + ); + Assertions + .assertThat(dockerComposeFiles.getDependencyImages()) .containsExactlyInAnyOrder("postgres:latest", "redis:latest", "mysql:latest"); } @Test public void shouldGetDependencyImagesWhenOverriding() { DockerComposeFiles dockerComposeFiles = new DockerComposeFiles( - Lists.newArrayList(new File("src/test/resources/docker-compose-imagename-overriding-a.yml"), - new File("src/test/resources/docker-compose-imagename-overriding-b.yml"))); - Assertions.assertThat(dockerComposeFiles.getDependencyImages()) + Lists.newArrayList( + new File("src/test/resources/docker-compose-imagename-overriding-a.yml"), + new File("src/test/resources/docker-compose-imagename-overriding-b.yml") + ) + ); + Assertions + .assertThat(dockerComposeFiles.getDependencyImages()) .containsExactlyInAnyOrder("alpine:3.14", "redis:b", "mysql:b", "aservice:latest"); } } diff --git a/core/src/test/java/org/testcontainers/containers/DockerComposeOverridesTest.java b/core/src/test/java/org/testcontainers/containers/DockerComposeOverridesTest.java index 9e9eb27b509..6207ae5ff45 100644 --- a/core/src/test/java/org/testcontainers/containers/DockerComposeOverridesTest.java +++ b/core/src/test/java/org/testcontainers/containers/DockerComposeOverridesTest.java @@ -8,7 +8,6 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.rnorth.ducttape.unreliables.Unreliables; -import org.testcontainers.containers.DockerComposeContainer; import java.io.BufferedReader; import java.io.File; @@ -24,14 +23,23 @@ public class DockerComposeOverridesTest { private static final File BASE_COMPOSE_FILE = new File("src/test/resources/docker-compose-base.yml"); + private static final String BASE_ENV_VAR = "bar=base"; - private static final File OVERRIDE_COMPOSE_FILE = new File("src/test/resources/docker-compose-non-default-override.yml"); + + private static final File OVERRIDE_COMPOSE_FILE = new File( + "src/test/resources/docker-compose-non-default-override.yml" + ); + private static final String OVERRIDE_ENV_VAR = "bar=overwritten"; + private static final int SERVICE_PORT = 3000; + private static final String SERVICE_NAME = "alpine_1"; private final boolean localMode; + private final String expectedEnvVar; + private final File[] composeFiles; public DockerComposeOverridesTest(boolean localMode, String expectedEnvVar, File... composeFiles) { @@ -42,18 +50,21 @@ public DockerComposeOverridesTest(boolean localMode, String expectedEnvVar, File @Parameters(name = "{index}: local[{0}], composeFiles[{2}], expectedEnvVar[{1}]") public static Iterable data() { - return Arrays.asList(new Object[][]{ - {true, BASE_ENV_VAR, new File[]{BASE_COMPOSE_FILE}}, - {true, OVERRIDE_ENV_VAR, new File[]{BASE_COMPOSE_FILE, OVERRIDE_COMPOSE_FILE}}, - {false, BASE_ENV_VAR, new File[]{BASE_COMPOSE_FILE}}, - {false, OVERRIDE_ENV_VAR, new File[]{BASE_COMPOSE_FILE, OVERRIDE_COMPOSE_FILE}}, - }); + return Arrays.asList( + new Object[][] { + { true, BASE_ENV_VAR, new File[] { BASE_COMPOSE_FILE } }, + { true, OVERRIDE_ENV_VAR, new File[] { BASE_COMPOSE_FILE, OVERRIDE_COMPOSE_FILE } }, + { false, BASE_ENV_VAR, new File[] { BASE_COMPOSE_FILE } }, + { false, OVERRIDE_ENV_VAR, new File[] { BASE_COMPOSE_FILE, OVERRIDE_COMPOSE_FILE } }, + } + ); } @Before public void setUp() { if (localMode) { - Assumptions.assumeThat(LocalDockerCompose.executableExists()) + Assumptions + .assumeThat(LocalDockerCompose.executableExists()) .as("docker-compose executable exists") .isTrue(); } @@ -61,33 +72,43 @@ public void setUp() { @Test public void test() { - try (DockerComposeContainer compose = - new DockerComposeContainer(composeFiles) - .withLocalCompose(localMode) - .withExposedService(SERVICE_NAME, SERVICE_PORT)) { - + try ( + DockerComposeContainer compose = new DockerComposeContainer(composeFiles) + .withLocalCompose(localMode) + .withExposedService(SERVICE_NAME, SERVICE_PORT) + ) { compose.start(); - BufferedReader br = Unreliables.retryUntilSuccess(10, TimeUnit.SECONDS, () -> { - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + BufferedReader br = Unreliables.retryUntilSuccess( + 10, + TimeUnit.SECONDS, + () -> { + Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - Socket socket = new Socket(compose.getServiceHost(SERVICE_NAME, SERVICE_PORT), compose.getServicePort(SERVICE_NAME, SERVICE_PORT)); - return new BufferedReader(new InputStreamReader(socket.getInputStream())); - }); + Socket socket = new Socket( + compose.getServiceHost(SERVICE_NAME, SERVICE_PORT), + compose.getServicePort(SERVICE_NAME, SERVICE_PORT) + ); + return new BufferedReader(new InputStreamReader(socket.getInputStream())); + } + ); - Unreliables.retryUntilTrue(10, TimeUnit.SECONDS, () -> { - while (br.ready()) { - String line = br.readLine(); - if (line.contains(expectedEnvVar)) { - pass("Mapped environment variable was found"); - return true; + Unreliables.retryUntilTrue( + 10, + TimeUnit.SECONDS, + () -> { + while (br.ready()) { + String line = br.readLine(); + if (line.contains(expectedEnvVar)) { + pass("Mapped environment variable was found"); + return true; + } } + info("Mapped environment variable was not found yet - process probably not ready"); + Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS); + return false; } - info("Mapped environment variable was not found yet - process probably not ready"); - Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS); - return false; - }); + ); } } - } diff --git a/core/src/test/java/org/testcontainers/containers/ExposedHostTest.java b/core/src/test/java/org/testcontainers/containers/ExposedHostTest.java index 38005014662..4afddeaa5dd 100644 --- a/core/src/test/java/org/testcontainers/containers/ExposedHostTest.java +++ b/core/src/test/java/org/testcontainers/containers/ExposedHostTest.java @@ -7,13 +7,13 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import org.testcontainers.TestImages; import org.testcontainers.Testcontainers; import java.io.OutputStream; import java.net.InetSocketAddress; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.TestImages.TINY_IMAGE; public class ExposedHostTest { @@ -22,14 +22,17 @@ public class ExposedHostTest { @BeforeClass public static void setUpClass() throws Exception { server = HttpServer.create(new InetSocketAddress(0), 0); - server.createContext("/", exchange -> { - byte[] content = "Hello World!".getBytes(); - exchange.sendResponseHeaders(200, content.length); - try (OutputStream responseBody = exchange.getResponseBody()) { - responseBody.write(content); - responseBody.flush(); + server.createContext( + "/", + exchange -> { + byte[] content = "Hello World!".getBytes(); + exchange.sendResponseHeaders(200, content.length); + try (OutputStream responseBody = exchange.getResponseBody()) { + responseBody.write(content); + responseBody.flush(); + } } - }); + ); server.start(); } @@ -47,7 +50,7 @@ public void tearDown() { @Test public void testExposedHostAfterContainerIsStarted() { try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withCommand("top") .withAccessToHost(true) ) { @@ -60,14 +63,17 @@ public void testExposedHostAfterContainerIsStarted() { @Test public void testExposedHost() throws Exception { Testcontainers.exposeHostPorts(server.getAddress().getPort()); - assertResponse(new GenericContainer<>(TINY_IMAGE).withCommand("top"), server.getAddress().getPort()); + assertResponse(new GenericContainer<>(TestImages.TINY_IMAGE).withCommand("top"), server.getAddress().getPort()); } @Test public void testExposedHostWithNetwork() throws Exception { Testcontainers.exposeHostPorts(server.getAddress().getPort()); try (Network network = Network.newNetwork()) { - assertResponse(new GenericContainer<>(TINY_IMAGE).withNetwork(network).withCommand("top"), server.getAddress().getPort()); + assertResponse( + new GenericContainer<>(TestImages.TINY_IMAGE).withNetwork(network).withCommand("top"), + server.getAddress().getPort() + ); } } @@ -76,8 +82,8 @@ public void testExposedHostPortOnFixedInternalPorts() throws Exception { Testcontainers.exposeHostPorts(ImmutableMap.of(server.getAddress().getPort(), 80)); Testcontainers.exposeHostPorts(ImmutableMap.of(server.getAddress().getPort(), 81)); - assertResponse(new GenericContainer<>(TINY_IMAGE).withCommand("top"), 80); - assertResponse(new GenericContainer<>(TINY_IMAGE).withCommand("top"), 81); + assertResponse(new GenericContainer<>(TestImages.TINY_IMAGE).withCommand("top"), 80); + assertResponse(new GenericContainer<>(TestImages.TINY_IMAGE).withCommand("top"), 81); } @SneakyThrows @@ -85,7 +91,9 @@ protected void assertResponse(GenericContainer container, int port) { try { container.start(); - String response = container.execInContainer("wget", "-O", "-", "http://host.testcontainers.internal:" + port).getStdout(); + String response = container + .execInContainer("wget", "-O", "-", "http://host.testcontainers.internal:" + port) + .getStdout(); assertEquals("received response", "Hello World!", response); } finally { diff --git a/core/src/test/java/org/testcontainers/containers/FailureDetectingExternalResourceTest.java b/core/src/test/java/org/testcontainers/containers/FailureDetectingExternalResourceTest.java index 63993bc24ff..c743fcf6a43 100644 --- a/core/src/test/java/org/testcontainers/containers/FailureDetectingExternalResourceTest.java +++ b/core/src/test/java/org/testcontainers/containers/FailureDetectingExternalResourceTest.java @@ -25,5 +25,4 @@ public void finishedIsCalledForCleanupIfStartingThrows() throws Throwable { verify(res).starting(any()); verify(res).finished(any()); } - } diff --git a/core/src/test/java/org/testcontainers/containers/GenericContainerTest.java b/core/src/test/java/org/testcontainers/containers/GenericContainerTest.java index 0c30d522cd9..fdd8ac1b146 100644 --- a/core/src/test/java/org/testcontainers/containers/GenericContainerTest.java +++ b/core/src/test/java/org/testcontainers/containers/GenericContainerTest.java @@ -17,13 +17,10 @@ import org.rnorth.ducttape.unreliables.Unreliables; import org.testcontainers.DockerClientFactory; import org.testcontainers.TestImages; -import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.containers.startupcheck.StartupCheckStrategy; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; -import org.testcontainers.images.builder.Transferable; - -import java.nio.charset.StandardCharsets; import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.images.builder.Transferable; import org.testcontainers.utility.MountableFile; import java.util.Arrays; @@ -34,11 +31,9 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hamcrest.CoreMatchers.equalTo; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertThrows; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.TINY_IMAGE; public class GenericContainerTest { @@ -52,7 +47,8 @@ public void shouldReportOOMAfterWait() { .withStartupCheckStrategy(new NoopStartupCheckStrategy()) .waitingFor(new WaitForExitedState(ContainerState::getOOMKilled)) .withCreateContainerCmdModifier(it -> { - it.getHostConfig() + it + .getHostConfig() .withMemory(20 * FileUtils.ONE_MB) .withMemorySwappiness(0L) .withMemorySwap(0L) @@ -61,8 +57,7 @@ public void shouldReportOOMAfterWait() { }) .withCommand("sh", "-c", "A='0123456789'; for i in $(seq 0 32); do A=$A$A; done; sleep 10m") ) { - assertThatThrownBy(container::start) - .hasStackTraceContaining("Container crashed with out-of-memory"); + assertThatThrownBy(container::start).hasStackTraceContaining("Container crashed with out-of-memory"); } } @@ -74,8 +69,7 @@ public void shouldReportErrorAfterWait() { .waitingFor(new WaitForExitedState(state -> state.getExitCode() > 0)) .withCommand("sh", "-c", "usleep 100; exit 123") ) { - assertThatThrownBy(container::start) - .hasStackTraceContaining("Container exited with code 123"); + assertThatThrownBy(container::start).hasStackTraceContaining("Container exited with code 123"); } } @@ -88,8 +82,7 @@ public void shouldCopyTransferableAsFile() { .waitingFor(new WaitForExitedState(state -> state.getExitCodeLong() > 0)) .withCommand("sh", "-c", "grep -q test /tmp/test && exit 100") ) { - assertThatThrownBy(container::start) - .hasStackTraceContaining("Container exited with code 100"); + assertThatThrownBy(container::start).hasStackTraceContaining("Container exited with code 100"); } } @@ -98,34 +91,31 @@ public void shouldCopyTransferableAfterMountableFile() { try ( GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withStartupCheckStrategy(new NoopStartupCheckStrategy()) - .withCopyFileToContainer( - MountableFile.forClasspathResource("test_copy_to_container.txt"), - "/tmp/test" - ) + .withCopyFileToContainer(MountableFile.forClasspathResource("test_copy_to_container.txt"), "/tmp/test") .withCopyToContainer(Transferable.of("test"), "/tmp/test") .waitingFor(new WaitForExitedState(state -> state.getExitCodeLong() > 0)) .withCommand("sh", "-c", "grep -q test /tmp/test && exit 100") ) { - assertThatThrownBy(container::start) - .hasStackTraceContaining("Container exited with code 100"); + assertThatThrownBy(container::start).hasStackTraceContaining("Container exited with code 100"); } } @Test public void shouldOnlyPublishExposedPorts() { ImageFromDockerfile image = new ImageFromDockerfile("publish-multiple") - .withDockerfileFromBuilder(builder -> + .withDockerfileFromBuilder(builder -> { builder - .from("testcontainers/helloworld:1.1.0") + .from("testcontainers/helloworld:1.1.0") // .expose(8080, 8081) - .build() - ); + .build(); + }); try (GenericContainer container = new GenericContainer<>(image).withExposedPorts(8080)) { container.start(); InspectContainerResponse inspectedContainer = container.getContainerInfo(); - List exposedPorts = Arrays.stream(inspectedContainer.getConfig().getExposedPorts()) + List exposedPorts = Arrays + .stream(inspectedContainer.getConfig().getExposedPorts()) .map(ExposedPort::getPort) .collect(Collectors.toList()); @@ -135,18 +125,14 @@ public void shouldOnlyPublishExposedPorts() { exposedPorts ); - Map hostBindings = inspectedContainer.getHostConfig().getPortBindings().getBindings(); - assertEquals( - "only 1 port is bound on the host (published)", - 1, - hostBindings.size() - ); + Map hostBindings = inspectedContainer + .getHostConfig() + .getPortBindings() + .getBindings(); + assertEquals("only 1 port is bound on the host (published)", 1, hostBindings.size()); Integer mappedPort = container.getMappedPort(8080); - assertTrue( - "port 8080 is bound to a different port on the host", - mappedPort != 8080 - ); + assertTrue("port 8080 is bound to a different port on the host", mappedPort != 8080); assertThrows( "trying to get a non-bound port mapping fails", @@ -160,21 +146,19 @@ public void shouldOnlyPublishExposedPorts() { @Test public void shouldWaitUntilExposedPortIsMapped() { - ImageFromDockerfile image = new ImageFromDockerfile("publish-multiple") - .withDockerfileFromBuilder(builder -> + .withDockerfileFromBuilder(builder -> { builder .from("testcontainers/helloworld:1.1.0") .expose(8080, 8081) // one additional port exposed in image - .build() - ); + .build(); + }); try ( GenericContainer container = new GenericContainer<>(image) .withExposedPorts(8080) .withCreateContainerCmdModifier(it -> it.withExposedPorts(ExposedPort.tcp(8082))) // another port exposed by modifier ) { - container.start(); assertEquals("Only withExposedPort should be exposed", 1, container.getExposedPorts().size()); @@ -200,16 +184,20 @@ static class WaitForExitedState extends AbstractWaitStrategy { @Override @SneakyThrows protected void waitUntilReady() { - Unreliables.retryUntilTrue(5, TimeUnit.SECONDS, () -> { - ContainerState state = waitStrategyTarget.getCurrentContainerInfo().getState(); - - log.debug("Current state: {}", state); - if (!"exited".equalsIgnoreCase(state.getStatus())) { - Thread.sleep(100); - return false; + Unreliables.retryUntilTrue( + 5, + TimeUnit.SECONDS, + () -> { + ContainerState state = waitStrategyTarget.getCurrentContainerInfo().getState(); + + log.debug("Current state: {}", state); + if (!"exited".equalsIgnoreCase(state.getStatus())) { + Thread.sleep(100); + return false; + } + return predicate.test(state); } - return predicate.test(state); - }); + ); throw new IllegalStateException("Nope!"); } diff --git a/core/src/test/java/org/testcontainers/containers/NetworkTest.java b/core/src/test/java/org/testcontainers/containers/NetworkTest.java index a39f0552a5a..d783f95e6d1 100644 --- a/core/src/test/java/org/testcontainers/containers/NetworkTest.java +++ b/core/src/test/java/org/testcontainers/containers/NetworkTest.java @@ -10,7 +10,6 @@ import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertNotEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertNotNull; -import static org.testcontainers.containers.Network.newNetwork; @RunWith(Enclosed.class) public class NetworkTest { @@ -18,18 +17,18 @@ public class NetworkTest { public static class WithRules { @Rule - public Network network = newNetwork(); + public Network network = Network.newNetwork(); @Rule public GenericContainer foo = new GenericContainer<>(TestImages.TINY_IMAGE) - .withNetwork(network) - .withNetworkAliases("foo") - .withCommand("/bin/sh", "-c", "while true ; do printf 'HTTP/1.1 200 OK\\n\\nyay' | nc -l -p 8080; done"); + .withNetwork(network) + .withNetworkAliases("foo") + .withCommand("/bin/sh", "-c", "while true ; do printf 'HTTP/1.1 200 OK\\n\\nyay' | nc -l -p 8080; done"); @Rule public GenericContainer bar = new GenericContainer<>(TestImages.TINY_IMAGE) - .withNetwork(network) - .withCommand("top"); + .withNetwork(network) + .withCommand("top"); @Test public void testNetworkSupport() throws Exception { @@ -44,16 +43,18 @@ public static class WithoutRules { public void testNetworkSupport() throws Exception { // useCustomNetwork { try ( - Network network = Network.newNetwork(); - - GenericContainer foo = new GenericContainer<>(TestImages.TINY_IMAGE) - .withNetwork(network) - .withNetworkAliases("foo") - .withCommand("/bin/sh", "-c", "while true ; do printf 'HTTP/1.1 200 OK\\n\\nyay' | nc -l -p 8080; done"); - - GenericContainer bar = new GenericContainer<>(TestImages.TINY_IMAGE) - .withNetwork(network) - .withCommand("top") + Network network = Network.newNetwork(); + GenericContainer foo = new GenericContainer<>(TestImages.TINY_IMAGE) + .withNetwork(network) + .withNetworkAliases("foo") + .withCommand( + "/bin/sh", + "-c", + "while true ; do printf 'HTTP/1.1 200 OK\\n\\nyay' | nc -l -p 8080; done" + ); + GenericContainer bar = new GenericContainer<>(TestImages.TINY_IMAGE) + .withNetwork(network) + .withCommand("top") ) { foo.start(); bar.start(); @@ -66,16 +67,12 @@ public void testNetworkSupport() throws Exception { @Test public void testBuilder() { - try ( - Network network = Network.builder() - .driver("macvlan") - .build() - ) { + try (Network network = Network.builder().driver("macvlan").build()) { String id = network.getId(); assertEquals( - "Flag is set", - "macvlan", - DockerClientFactory.instance().client().inspectNetworkCmd().withNetworkId(id).exec().getDriver() + "Flag is set", + "macvlan", + DockerClientFactory.instance().client().inspectNetworkCmd().withNetworkId(id).exec().getDriver() ); } } @@ -83,15 +80,13 @@ public void testBuilder() { @Test public void testModifiers() { try ( - Network network = Network.builder() - .createNetworkCmdModifier(cmd -> cmd.withDriver("macvlan")) - .build() + Network network = Network.builder().createNetworkCmdModifier(cmd -> cmd.withDriver("macvlan")).build() ) { String id = network.getId(); assertEquals( - "Flag is set", - "macvlan", - DockerClientFactory.instance().client().inspectNetworkCmd().withNetworkId(id).exec().getDriver() + "Flag is set", + "macvlan", + DockerClientFactory.instance().client().inspectNetworkCmd().withNetworkId(id).exec().getDriver() ); } } @@ -101,16 +96,22 @@ public void testReusability() { try (Network network = Network.newNetwork()) { String firstId = network.getId(); assertNotNull( - "Network exists", - DockerClientFactory.instance().client().inspectNetworkCmd().withNetworkId(firstId).exec() + "Network exists", + DockerClientFactory.instance().client().inspectNetworkCmd().withNetworkId(firstId).exec() ); network.close(); assertNotEquals( - "New network created", - firstId, - DockerClientFactory.instance().client().inspectNetworkCmd().withNetworkId(network.getId()).exec().getId() + "New network created", + firstId, + DockerClientFactory + .instance() + .client() + .inspectNetworkCmd() + .withNetworkId(network.getId()) + .exec() + .getId() ); } } diff --git a/core/src/test/java/org/testcontainers/containers/ParsedDockerComposeFileValidationTest.java b/core/src/test/java/org/testcontainers/containers/ParsedDockerComposeFileValidationTest.java index ef70d06ada1..61955de98ba 100644 --- a/core/src/test/java/org/testcontainers/containers/ParsedDockerComposeFileValidationTest.java +++ b/core/src/test/java/org/testcontainers/containers/ParsedDockerComposeFileValidationTest.java @@ -6,9 +6,9 @@ import org.junit.Test; import java.io.File; +import java.util.Collections; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.entry; public class ParsedDockerComposeFileValidationTest { @@ -16,8 +16,7 @@ public class ParsedDockerComposeFileValidationTest { @Test public void shouldValidate() { File file = new File("src/test/resources/docker-compose-container-name-v1.yml"); - Assertions - .assertThatThrownBy(() -> { + assertThatThrownBy(() -> { new ParsedDockerComposeFile(file); }) .hasMessageContaining(file.getAbsolutePath()) @@ -26,25 +25,23 @@ public void shouldValidate() { @Test public void shouldRejectContainerNameV1() { - Assertions - .assertThatThrownBy(() -> { - new ParsedDockerComposeFile(ImmutableMap.of( - "redis", ImmutableMap.of("container_name", "redis") - )); + assertThatThrownBy(() -> { + new ParsedDockerComposeFile(ImmutableMap.of("redis", ImmutableMap.of("container_name", "redis"))); }) .hasMessageContaining("'container_name' property set for service 'redis'"); } @Test public void shouldRejectContainerNameV2() { - Assertions - .assertThatThrownBy(() -> { - new ParsedDockerComposeFile(ImmutableMap.of( - "version", "2", - "services", ImmutableMap.of( - "redis", ImmutableMap.of("container_name", "redis") + assertThatThrownBy(() -> { + new ParsedDockerComposeFile( + ImmutableMap.of( + "version", + "2", + "services", + ImmutableMap.of("redis", ImmutableMap.of("container_name", "redis")) ) - )); + ); }) .hasMessageContaining("'container_name' property set for service 'redis'"); } @@ -52,35 +49,29 @@ public void shouldRejectContainerNameV2() { @Test public void shouldIgnoreUnknownStructure() { // Everything is a list - new ParsedDockerComposeFile(emptyMap()); + new ParsedDockerComposeFile(Collections.emptyMap()); // services is not a map but List - new ParsedDockerComposeFile(ImmutableMap.of( - "version", "2", - "services", emptyList() - )); + new ParsedDockerComposeFile(ImmutableMap.of("version", "2", "services", Collections.emptyList())); // services is not a collection - new ParsedDockerComposeFile(ImmutableMap.of( - "version", "2", - "services", true - )); + new ParsedDockerComposeFile(ImmutableMap.of("version", "2", "services", true)); // no services while version is defined - new ParsedDockerComposeFile(ImmutableMap.of( - "version", "9000" - )); + new ParsedDockerComposeFile(ImmutableMap.of("version", "9000")); } @Test public void shouldObtainImageNamesV1() { File file = new File("src/test/resources/docker-compose-imagename-parsing-v1.yml"); ParsedDockerComposeFile parsedFile = new ParsedDockerComposeFile(file); - Assertions.assertThat(parsedFile.getServiceNameToImageNames()) + Assertions + .assertThat(parsedFile.getServiceNameToImageNames()) .contains( entry("mysql", Sets.newHashSet("mysql")), entry("redis", Sets.newHashSet("redis")), - entry("custom", Sets.newHashSet("postgres"))) + entry("custom", Sets.newHashSet("postgres")) + ) .as("all defined images are found"); // redis, mysql from compose file, postgres from Dockerfile build } @@ -88,11 +79,13 @@ public void shouldObtainImageNamesV1() { public void shouldObtainImageNamesV2() { File file = new File("src/test/resources/docker-compose-imagename-parsing-v2.yml"); ParsedDockerComposeFile parsedFile = new ParsedDockerComposeFile(file); - Assertions.assertThat(parsedFile.getServiceNameToImageNames()) + Assertions + .assertThat(parsedFile.getServiceNameToImageNames()) .contains( entry("mysql", Sets.newHashSet("mysql")), entry("redis", Sets.newHashSet("redis")), - entry("custom", Sets.newHashSet("postgres"))) + entry("custom", Sets.newHashSet("postgres")) + ) .as("all defined images are found"); } @@ -100,11 +93,13 @@ public void shouldObtainImageNamesV2() { public void shouldObtainImageFromDockerfileBuild() { File file = new File("src/test/resources/docker-compose-imagename-parsing-dockerfile.yml"); ParsedDockerComposeFile parsedFile = new ParsedDockerComposeFile(file); - Assertions.assertThat(parsedFile.getServiceNameToImageNames()) + Assertions + .assertThat(parsedFile.getServiceNameToImageNames()) .contains( entry("mysql", Sets.newHashSet("mysql")), entry("redis", Sets.newHashSet("redis")), - entry("custom", Sets.newHashSet("alpine:3.14"))) + entry("custom", Sets.newHashSet("alpine:3.14")) + ) .as("all defined images are found"); // r/ redis, mysql from compose file, alpine:3.14 from Dockerfile build } @@ -112,11 +107,13 @@ public void shouldObtainImageFromDockerfileBuild() { public void shouldObtainImageFromDockerfileBuildWithContext() { File file = new File("src/test/resources/docker-compose-imagename-parsing-dockerfile-with-context.yml"); ParsedDockerComposeFile parsedFile = new ParsedDockerComposeFile(file); - Assertions.assertThat(parsedFile.getServiceNameToImageNames()) + Assertions + .assertThat(parsedFile.getServiceNameToImageNames()) .contains( entry("mysql", Sets.newHashSet("mysql")), entry("redis", Sets.newHashSet("redis")), - entry("custom", Sets.newHashSet("alpine:3.14"))) + entry("custom", Sets.newHashSet("alpine:3.14")) + ) .as("all defined images are found"); // redis, mysql from compose file, alpine:3.14 from Dockerfile build } } diff --git a/core/src/test/java/org/testcontainers/containers/ReusabilityUnitTests.java b/core/src/test/java/org/testcontainers/containers/ReusabilityUnitTests.java index 9aad97d7e7b..7aafb0149bd 100644 --- a/core/src/test/java/org/testcontainers/containers/ReusabilityUnitTests.java +++ b/core/src/test/java/org/testcontainers/containers/ReusabilityUnitTests.java @@ -27,9 +27,9 @@ import org.mockito.stubbing.Answer; import org.rnorth.visibleassertions.VisibleAssertions; import org.testcontainers.DockerClientFactory; +import org.testcontainers.TestImages; import org.testcontainers.containers.startupcheck.StartupCheckStrategy; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; -import org.testcontainers.images.builder.Transferable; import org.testcontainers.utility.MockTestcontainersConfigurationRule; import org.testcontainers.utility.MountableFile; import org.testcontainers.utility.TestcontainersConfiguration; @@ -53,7 +53,6 @@ import static org.assertj.core.api.Assumptions.assumeThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; -import static org.testcontainers.TestImages.TINY_IMAGE; @RunWith(Enclosed.class) public class ReusabilityUnitTests { @@ -66,8 +65,8 @@ public static class CanBeReusedTest { @Parameterized.Parameters(name = "{0}") public static Object[][] data() { return new Object[][] { - { "generic", new GenericContainer<>(TINY_IMAGE), true }, - { "anonymous generic", new GenericContainer(TINY_IMAGE) {}, true }, + { "generic", new GenericContainer<>(TestImages.TINY_IMAGE), true }, + { "anonymous generic", new GenericContainer(TestImages.TINY_IMAGE) {}, true }, { "custom", new CustomContainer(), true }, { "anonymous custom", new CustomContainer() {}, true }, { "custom with containerIsCreated", new CustomContainerWithContainerIsCreated(), false }, @@ -90,15 +89,17 @@ public void shouldBeReusable() { } static class CustomContainer extends GenericContainer { + CustomContainer() { - super(TINY_IMAGE); + super(TestImages.TINY_IMAGE); } } - static class CustomContainerWithContainerIsCreated extends GenericContainer { + static class CustomContainerWithContainerIsCreated + extends GenericContainer { CustomContainerWithContainerIsCreated() { - super(TINY_IMAGE); + super(TestImages.TINY_IMAGE); } @Override @@ -114,29 +115,30 @@ public static class HooksTest extends AbstractReusabilityTest { List script = new ArrayList<>(); - GenericContainer container = makeReusable(new GenericContainer(TINY_IMAGE) { - - @Override - protected boolean canBeReused() { - // Because we override "containerIsCreated" - return true; - } + GenericContainer container = makeReusable( + new GenericContainer(TestImages.TINY_IMAGE) { + @Override + protected boolean canBeReused() { + // Because we override "containerIsCreated" + return true; + } - @Override - protected void containerIsCreated(String containerId) { - script.add("containerIsCreated"); - } + @Override + protected void containerIsCreated(String containerId) { + script.add("containerIsCreated"); + } - @Override - protected void containerIsStarting(InspectContainerResponse containerInfo, boolean reused) { - script.add("containerIsStarting(reused=" + reused + ")"); - } + @Override + protected void containerIsStarting(InspectContainerResponse containerInfo, boolean reused) { + script.add("containerIsStarting(reused=" + reused + ")"); + } - @Override - protected void containerIsStarted(InspectContainerResponse containerInfo, boolean reused) { - script.add("containerIsStarted(reused=" + reused + ")"); + @Override + protected void containerIsStarted(InspectContainerResponse containerInfo, boolean reused) { + script.add("containerIsStarted(reused=" + reused + ")"); + } } - }); + ); @Test public void shouldSetLabelsIfEnvironmentDoesNotSupportReuse() { @@ -149,11 +151,12 @@ public void shouldSetLabelsIfEnvironmentDoesNotSupportReuse() { when(client.inspectContainerCmd(containerId)).then(inspectContainerAnswer()); container.start(); - assertThat(script).containsExactly( - "containerIsCreated", - "containerIsStarting(reused=false)", - "containerIsStarted(reused=false)" - ); + assertThat(script) + .containsExactly( + "containerIsCreated", + "containerIsStarting(reused=false)", + "containerIsStarted(reused=false)" + ); } @Test @@ -166,10 +169,7 @@ public void shouldCallHookIfReused() { when(client.inspectContainerCmd(existingContainerId)).then(inspectContainerAnswer()); container.start(); - assertThat(script).containsExactly( - "containerIsStarting(reused=true)", - "containerIsStarted(reused=true)" - ); + assertThat(script).containsExactly("containerIsStarting(reused=true)", "containerIsStarted(reused=true)"); } @Test @@ -181,11 +181,12 @@ public void shouldNotCallHookIfNotReused() { when(client.inspectContainerCmd(containerId)).then(inspectContainerAnswer()); container.start(); - assertThat(script).containsExactly( - "containerIsCreated", - "containerIsStarting(reused=false)", - "containerIsStarted(reused=false)" - ); + assertThat(script) + .containsExactly( + "containerIsCreated", + "containerIsStarting(reused=false)", + "containerIsStarted(reused=false)" + ); } } @@ -193,12 +194,14 @@ public void shouldNotCallHookIfNotReused() { @FieldDefaults(makeFinal = true) public static class HashTest extends AbstractReusabilityTest { - protected GenericContainer container = makeReusable(new GenericContainer(TINY_IMAGE) { - @Override - public void copyFileToContainer(MountableFile mountableFile, String containerPath) { - // NOOP + protected GenericContainer container = makeReusable( + new GenericContainer(TestImages.TINY_IMAGE) { + @Override + public void copyFileToContainer(MountableFile mountableFile, String containerPath) { + // NOOP + } } - }); + ); @Test public void shouldStartIfListReturnsEmpty() { @@ -260,8 +263,7 @@ public void shouldSetCopiedFilesHashLabel() { container.start(); assertThat(commandRef).isNotNull(); - assertThat(commandRef.get().getLabels()) - .containsKeys(GenericContainer.COPIED_FILES_HASH_LABEL); + assertThat(commandRef.get().getLabels()).containsKeys(GenericContainer.COPIED_FILES_HASH_LABEL); } @Test @@ -292,15 +294,20 @@ public void shouldHashCopiedFiles() { ); container.start(); - assertThat(commandRef.get().getLabels()).hasEntrySatisfying(GenericContainer.COPIED_FILES_HASH_LABEL, newHash -> { - assertThat(newHash).as("new hash").isNotEqualTo(oldHash); - }); + assertThat(commandRef.get().getLabels()) + .hasEntrySatisfying( + GenericContainer.COPIED_FILES_HASH_LABEL, + newHash -> { + assertThat(newHash).as("new hash").isNotEqualTo(oldHash); + } + ); } } @RunWith(Parameterized.class) @FieldDefaults(makeFinal = true) public static class CopyFilesHashTest { + private final TestStrategy strategy; interface TestStrategy { @@ -310,6 +317,7 @@ interface TestStrategy { } private static class MountableFileTestStrategy implements TestStrategy { + private final GenericContainer container; private MountableFileTestStrategy(GenericContainer container) { @@ -328,6 +336,7 @@ public void clear() { } private static class TransferableTestStrategy implements TestStrategy { + private final GenericContainer container; private TransferableTestStrategy(GenericContainer container) { @@ -350,8 +359,7 @@ public static List, TestStrategy>> strategies() { return Arrays.asList(MountableFileTestStrategy::new, TransferableTestStrategy::new); } - - GenericContainer container = new GenericContainer<>(TINY_IMAGE); + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE); public CopyFilesHashTest(Function, TestStrategy> strategyFactory) { this.strategy = strategyFactory.apply(container); @@ -499,7 +507,7 @@ public void folderPermissions() throws Exception { } @FieldDefaults(makeFinal = true) - public static abstract class AbstractReusabilityTest { + public abstract static class AbstractReusabilityTest { @Rule public MockTestcontainersConfigurationRule configurationMock = new MockTestcontainersConfigurationRule(); @@ -509,25 +517,26 @@ public static abstract class AbstractReusabilityTest { protected > T makeReusable(T container) { container.dockerClient = client; container.withNetworkMode("none"); // to disable the port forwarding - container.withStartupCheckStrategy(new StartupCheckStrategy() { - - @Override - public boolean waitUntilStartupSuccessful(DockerClient dockerClient, String containerId) { - // Skip DockerClient rate limiter - return true; + container.withStartupCheckStrategy( + new StartupCheckStrategy() { + @Override + public boolean waitUntilStartupSuccessful(DockerClient dockerClient, String containerId) { + // Skip DockerClient rate limiter + return true; + } + + @Override + public StartupStatus checkStartupState(DockerClient dockerClient, String containerId) { + return StartupStatus.SUCCESSFUL; + } } - - @Override - public StartupStatus checkStartupState(DockerClient dockerClient, String containerId) { - return StartupStatus.SUCCESSFUL; - } - }); - container.waitingFor(new AbstractWaitStrategy() { - @Override - protected void waitUntilReady() { - + ); + container.waitingFor( + new AbstractWaitStrategy() { + @Override + protected void waitUntilReady() {} } - }); + ); container.withReuse(true); return container; } @@ -539,12 +548,11 @@ protected String randomContainerId() { protected Answer listContainersAnswer(String... ids) { return invocation -> { ListContainersCmd.Exec exec = command -> { - return new ObjectMapper().convertValue( - Stream.of(ids) - .map(id -> Collections.singletonMap("Id", id)) - .collect(Collectors.toList()), - new TypeReference>() {} - ); + return new ObjectMapper() + .convertValue( + Stream.of(ids).map(id -> Collections.singletonMap("Id", id)).collect(Collectors.toList()), + new TypeReference>() {} + ); }; return new ListContainersCmdImpl(exec); }; @@ -554,7 +562,10 @@ protected Answer createContainerAnswer(String containerId) { return createContainerAnswer(containerId, command -> {}); } - protected Answer createContainerAnswer(String containerId, Consumer cmdConsumer) { + protected Answer createContainerAnswer( + String containerId, + Consumer cmdConsumer + ) { return invocation -> { CreateContainerCmd.Exec exec = command -> { cmdConsumer.accept(command); @@ -578,7 +589,10 @@ protected Answer startContainerAnswer() { protected Answer inspectContainerAnswer() { return invocation -> { InspectContainerCmd.Exec exec = command -> { - InspectContainerResponse stubResponse = Mockito.mock(InspectContainerResponse.class, Answers.RETURNS_DEEP_STUBS); + InspectContainerResponse stubResponse = Mockito.mock( + InspectContainerResponse.class, + Answers.RETURNS_DEEP_STUBS + ); when(stubResponse.getNetworkSettings().getPorts().getBindings()).thenReturn(Collections.emptyMap()); return stubResponse; }; diff --git a/core/src/test/java/org/testcontainers/containers/output/ContainerLogsTest.java b/core/src/test/java/org/testcontainers/containers/output/ContainerLogsTest.java index 05ef7373293..a860b7802ec 100644 --- a/core/src/test/java/org/testcontainers/containers/output/ContainerLogsTest.java +++ b/core/src/test/java/org/testcontainers/containers/output/ContainerLogsTest.java @@ -2,14 +2,12 @@ import org.junit.Ignore; import org.junit.Test; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.ALPINE_IMAGE; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDERR; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; public class ContainerLogsTest { @@ -43,7 +41,7 @@ public void getLogsReturnsStdOutToDate() { container.start(); // docsGetStdOut { - final String logs = container.getLogs(STDOUT); + final String logs = container.getLogs(OutputFrame.OutputType.STDOUT); // } assertTrue("stdout is reflected in the returned logs", logs.contains("stdout")); } @@ -55,7 +53,7 @@ public void getLogsReturnsStdErrToDate() { container.start(); // docsGetStdErr { - final String logs = container.getLogs(STDERR); + final String logs = container.getLogs(OutputFrame.OutputType.STDERR); // } assertTrue("stderr is reflected in the returned logs", logs.contains("stderr")); } @@ -68,19 +66,18 @@ public void getLogsForLongRunningContainer() throws InterruptedException { Thread.sleep(1000L); - final String logs = container.getLogs(STDOUT); + final String logs = container.getLogs(OutputFrame.OutputType.STDOUT); assertTrue("stdout is reflected in the returned logs for a running container", logs.contains("seq=0")); } } private static GenericContainer shortLivedContainer() { - return new GenericContainer<>(ALPINE_IMAGE) + return new GenericContainer<>(TestImages.ALPINE_IMAGE) .withCommand("/bin/sh", "-c", "echo -n 'stdout' && echo -n 'stderr' 1>&2") .withStartupCheckStrategy(new OneShotStartupCheckStrategy()); } private static GenericContainer longRunningContainer() { - return new GenericContainer<>(ALPINE_IMAGE) - .withCommand("ping -c 100 127.0.0.1"); + return new GenericContainer<>(TestImages.ALPINE_IMAGE).withCommand("ping -c 100 127.0.0.1"); } } diff --git a/core/src/test/java/org/testcontainers/containers/output/FrameConsumerResultCallbackTest.java b/core/src/test/java/org/testcontainers/containers/output/FrameConsumerResultCallbackTest.java index 325cccdd378..5282712b733 100644 --- a/core/src/test/java/org/testcontainers/containers/output/FrameConsumerResultCallbackTest.java +++ b/core/src/test/java/org/testcontainers/containers/output/FrameConsumerResultCallbackTest.java @@ -12,17 +12,19 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.testcontainers.containers.output.OutputFrame.OutputType; public class FrameConsumerResultCallbackTest { - private static final String FRAME_PAYLOAD = "\u001B[0;32mТест1\u001B[0m\n\u001B[1;33mTest2\u001B[0m\n\u001B[0;31mTest3\u001B[0m"; + + private static final String FRAME_PAYLOAD = + "\u001B[0;32mТест1\u001B[0m\n\u001B[1;33mTest2\u001B[0m\n\u001B[0;31mTest3\u001B[0m"; + private static final String LOG_RESULT = "Тест1\nTest2\nTest3"; @Test public void passStderrFrameWithoutColors() { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer(); - callback.addConsumer(OutputType.STDERR, consumer); + callback.addConsumer(OutputFrame.OutputType.STDERR, consumer); callback.onNext(new Frame(StreamType.STDERR, FRAME_PAYLOAD.getBytes())); assertEquals(LOG_RESULT, consumer.toUtf8String()); } @@ -31,7 +33,7 @@ public void passStderrFrameWithoutColors() { public void passStderrFrameWithColors() { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDERR, consumer); + callback.addConsumer(OutputFrame.OutputType.STDERR, consumer); callback.onNext(new Frame(StreamType.STDERR, FRAME_PAYLOAD.getBytes())); assertEquals(FRAME_PAYLOAD, consumer.toUtf8String()); } @@ -40,7 +42,7 @@ public void passStderrFrameWithColors() { public void passStdoutFrameWithoutColors() { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer(); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.STDOUT, FRAME_PAYLOAD.getBytes())); assertEquals(LOG_RESULT, consumer.toUtf8String()); } @@ -49,7 +51,7 @@ public void passStdoutFrameWithoutColors() { public void passStdoutFrameWithColors() { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.STDOUT, FRAME_PAYLOAD.getBytes())); assertEquals(FRAME_PAYLOAD, consumer.toUtf8String()); } @@ -58,7 +60,7 @@ public void passStdoutFrameWithColors() { public void basicConsumer() { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); BasicConsumer consumer = new BasicConsumer(); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.STDOUT, FRAME_PAYLOAD.getBytes())); assertEquals(LOG_RESULT, consumer.toString()); } @@ -67,7 +69,7 @@ public void basicConsumer() { public void passStdoutNull() { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.STDOUT, null)); assertEquals("", consumer.toUtf8String()); } @@ -77,7 +79,7 @@ public void passStdoutEmptyLine() { String payload = ""; FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.STDOUT, payload.getBytes())); assertEquals(payload, consumer.toUtf8String()); } @@ -87,7 +89,7 @@ public void passStdoutSingleLine() { String payload = "Test"; FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.STDOUT, payload.getBytes())); assertEquals(payload, consumer.toUtf8String()); } @@ -97,7 +99,7 @@ public void passStdoutSingleLineWithNewline() { String payload = "Test\n"; FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.STDOUT, payload.getBytes())); assertEquals(payload, consumer.toUtf8String()); } @@ -106,38 +108,90 @@ public void passStdoutSingleLineWithNewline() { public void passRawFrameWithoutColors() throws TimeoutException, IOException { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); WaitingConsumer waitConsumer = new WaitingConsumer(); - callback.addConsumer(OutputType.STDOUT, waitConsumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, waitConsumer); callback.onNext(new Frame(StreamType.RAW, FRAME_PAYLOAD.getBytes())); - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("Test2"), 1, TimeUnit.SECONDS); - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("Тест1"), 1, TimeUnit.SECONDS); + waitConsumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().equals("Test2"), + 1, + TimeUnit.SECONDS + ); + waitConsumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().equals("Тест1"), + 1, + TimeUnit.SECONDS + ); Exception exception = null; try { - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("Test3"), 1, TimeUnit.SECONDS); + waitConsumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().equals("Test3"), + 1, + TimeUnit.SECONDS + ); } catch (Exception e) { exception = e; } assertTrue(exception instanceof TimeoutException); callback.close(); - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("Test3"), 1, TimeUnit.SECONDS); + waitConsumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().equals("Test3"), + 1, + TimeUnit.SECONDS + ); } @Test public void passRawFrameWithColors() throws TimeoutException, IOException { FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); WaitingConsumer waitConsumer = new WaitingConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDOUT, waitConsumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, waitConsumer); callback.onNext(new Frame(StreamType.RAW, FRAME_PAYLOAD.getBytes())); - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("\u001B[1;33mTest2\u001B[0m"), 1, TimeUnit.SECONDS); - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("\u001B[0;32mТест1\u001B[0m"), 1, TimeUnit.SECONDS); + waitConsumer.waitUntil( + frame -> { + return ( + frame.getType() == OutputFrame.OutputType.STDOUT && + frame.getUtf8String().equals("\u001B[1;33mTest2\u001B[0m") + ); + }, + 1, + TimeUnit.SECONDS + ); + waitConsumer.waitUntil( + frame -> { + return ( + frame.getType() == OutputFrame.OutputType.STDOUT && + frame.getUtf8String().equals("\u001B[0;32mТест1\u001B[0m") + ); + }, + 1, + TimeUnit.SECONDS + ); Exception exception = null; try { - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("\u001B[0;31mTest3\u001B[0m"), 1, TimeUnit.SECONDS); + waitConsumer.waitUntil( + frame -> { + return ( + frame.getType() == OutputFrame.OutputType.STDOUT && + frame.getUtf8String().equals("\u001B[0;31mTest3\u001B[0m") + ); + }, + 1, + TimeUnit.SECONDS + ); } catch (Exception e) { exception = e; } assertTrue(exception instanceof TimeoutException); callback.close(); - waitConsumer.waitUntil(frame -> frame.getType() == OutputType.STDOUT && frame.getUtf8String().equals("\u001B[0;31mTest3\u001B[0m"), 1, TimeUnit.SECONDS); + waitConsumer.waitUntil( + frame -> { + return ( + frame.getType() == OutputFrame.OutputType.STDOUT && + frame.getUtf8String().equals("\u001B[0;31mTest3\u001B[0m") + ); + }, + 1, + TimeUnit.SECONDS + ); } @Test @@ -150,7 +204,7 @@ public void reconstructBreakedUnicode() throws IOException { System.arraycopy(payloadBytes, bytes1.length, bytes2, 0, bytes2.length); FrameConsumerResultCallback callback = new FrameConsumerResultCallback(); ToStringConsumer consumer = new ToStringConsumer().withRemoveAnsiCodes(false); - callback.addConsumer(OutputType.STDOUT, consumer); + callback.addConsumer(OutputFrame.OutputType.STDOUT, consumer); callback.onNext(new Frame(StreamType.RAW, bytes1)); callback.onNext(new Frame(StreamType.RAW, bytes2)); callback.close(); @@ -158,7 +212,9 @@ public void reconstructBreakedUnicode() throws IOException { } private static class BasicConsumer implements Consumer { + private boolean firstLine = true; + private StringBuilder input = new StringBuilder(); @Override diff --git a/core/src/test/java/org/testcontainers/containers/output/ToStringConsumerTest.java b/core/src/test/java/org/testcontainers/containers/output/ToStringConsumerTest.java index 1760a8031b2..08973f2d601 100644 --- a/core/src/test/java/org/testcontainers/containers/output/ToStringConsumerTest.java +++ b/core/src/test/java/org/testcontainers/containers/output/ToStringConsumerTest.java @@ -1,7 +1,5 @@ package org.testcontainers.containers.output; -import static org.assertj.core.api.Assertions.assertThat; - import org.apache.commons.lang3.RandomStringUtils; import org.assertj.core.api.Assertions; import org.junit.Test; @@ -9,12 +7,14 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; +import static org.assertj.core.api.Assertions.assertThat; + public class ToStringConsumerTest { private static final String LARGE_PAYLOAD; static { - StringBuilder builder = new StringBuilder(10_003 * 10);; + StringBuilder builder = new StringBuilder(10_003 * 10); for (int i = 0; i < 10; i++) { builder.append(' ').append(i).append(RandomStringUtils.randomAlphabetic(10000)); } @@ -29,9 +29,7 @@ public void newlines_are_not_added_to_exec_output() throws Exception { container.start(); ExecResult build = container.execInContainer("echo", "-n", LARGE_PAYLOAD); - Assertions.assertThat(build.getStdout()) - .doesNotContain("\n") - .isEqualTo(LARGE_PAYLOAD); + Assertions.assertThat(build.getStdout()).doesNotContain("\n").isEqualTo(LARGE_PAYLOAD); } } @@ -39,18 +37,13 @@ public void newlines_are_not_added_to_exec_output() throws Exception { public void newlines_are_not_added_to_exec_output_with_tty() throws Exception { try (GenericContainer container = new GenericContainer<>("alpine:3.14")) { container.withCreateContainerCmdModifier(cmd -> { - cmd - .withAttachStdin(true) - .withStdinOpen(true) - .withTty(true); + cmd.withAttachStdin(true).withStdinOpen(true).withTty(true); }); container.withCommand("sleep", "2m"); container.start(); ExecResult build = container.execInContainer("echo", "-n", LARGE_PAYLOAD); - assertThat(build.getStdout()) - .isEqualTo(LARGE_PAYLOAD) - .doesNotContain("\n"); + assertThat(build.getStdout()).isEqualTo(LARGE_PAYLOAD).doesNotContain("\n"); } } @@ -63,9 +56,7 @@ public void newlines_are_not_added_to_container_output() { container.getDockerClient().waitContainerCmd(container.getContainerId()).start().awaitStatusCode(); - assertThat(container.getLogs()) - .isEqualTo(LARGE_PAYLOAD) - .doesNotContain("\n"); + assertThat(container.getLogs()).isEqualTo(LARGE_PAYLOAD).doesNotContain("\n"); } } @@ -81,9 +72,7 @@ public void newlines_are_not_added_to_container_output_with_tty() { container.getDockerClient().waitContainerCmd(container.getContainerId()).start().awaitStatusCode(); - assertThat(container.getLogs()) - .isEqualTo(LARGE_PAYLOAD) - .doesNotContain("\n"); + assertThat(container.getLogs()).isEqualTo(LARGE_PAYLOAD).doesNotContain("\n"); } } } diff --git a/core/src/test/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheckTest.java b/core/src/test/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheckTest.java index 19f3a772d41..c76d2481c7c 100644 --- a/core/src/test/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheckTest.java +++ b/core/src/test/java/org/testcontainers/containers/wait/internal/ExternalPortListeningCheckTest.java @@ -16,8 +16,11 @@ public class ExternalPortListeningCheckTest { private ServerSocket listeningSocket1; + private ServerSocket listeningSocket2; + private ServerSocket nonListeningSocket; + private WaitStrategyTarget mockContainer; @Before @@ -34,8 +37,10 @@ public void setUp() throws Exception { @Test public void singleListening() { - - final ExternalPortListeningCheck check = new ExternalPortListeningCheck(mockContainer, ImmutableSet.of(listeningSocket1.getLocalPort())); + final ExternalPortListeningCheck check = new ExternalPortListeningCheck( + mockContainer, + ImmutableSet.of(listeningSocket1.getLocalPort()) + ); final Boolean result = check.call(); @@ -44,8 +49,10 @@ public void singleListening() { @Test public void multipleListening() { - - final ExternalPortListeningCheck check = new ExternalPortListeningCheck(mockContainer, ImmutableSet.of(listeningSocket1.getLocalPort(), listeningSocket2.getLocalPort())); + final ExternalPortListeningCheck check = new ExternalPortListeningCheck( + mockContainer, + ImmutableSet.of(listeningSocket1.getLocalPort(), listeningSocket2.getLocalPort()) + ); final Boolean result = check.call(); @@ -54,13 +61,16 @@ public void multipleListening() { @Test public void oneNotListening() { - - final ExternalPortListeningCheck check = new ExternalPortListeningCheck(mockContainer, ImmutableSet.of(listeningSocket1.getLocalPort(), nonListeningSocket.getLocalPort())); - - assertThrows("ExternalPortListeningCheck detects a non-listening port among many", - IllegalStateException.class, - (Runnable) check::call); - + final ExternalPortListeningCheck check = new ExternalPortListeningCheck( + mockContainer, + ImmutableSet.of(listeningSocket1.getLocalPort(), nonListeningSocket.getLocalPort()) + ); + + assertThrows( + "ExternalPortListeningCheck detects a non-listening port among many", + IllegalStateException.class, + (Runnable) check::call + ); } @After diff --git a/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java b/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java index 22014cd097a..6f2a5d3158c 100644 --- a/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java +++ b/core/src/test/java/org/testcontainers/containers/wait/internal/InternalCommandPortListeningCheckTest.java @@ -11,36 +11,41 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.images.builder.ImageFromDockerfile; +import java.util.Arrays; import java.util.concurrent.TimeUnit; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class InternalCommandPortListeningCheckTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"internal-port-check-dockerfile/Dockerfile-tcp"}, - {"internal-port-check-dockerfile/Dockerfile-nc"}, - {"internal-port-check-dockerfile/Dockerfile-bash"}, - }); + return Arrays.asList( + new Object[][] { + { "internal-port-check-dockerfile/Dockerfile-tcp" }, + { "internal-port-check-dockerfile/Dockerfile-nc" }, + { "internal-port-check-dockerfile/Dockerfile-bash" }, + } + ); } @Rule public GenericContainer container; public InternalCommandPortListeningCheckTest(String dockerfile) { - container = new GenericContainer(new ImageFromDockerfile() - .withFileFromClasspath("Dockerfile", dockerfile) - .withFileFromClasspath("nginx.conf", "internal-port-check-dockerfile/nginx.conf") - ); + container = + new GenericContainer( + new ImageFromDockerfile() + .withFileFromClasspath("Dockerfile", dockerfile) + .withFileFromClasspath("nginx.conf", "internal-port-check-dockerfile/nginx.conf") + ); } @Test public void singleListening() { - final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(container, ImmutableSet.of(8080)); + final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck( + container, + ImmutableSet.of(8080) + ); Unreliables.retryUntilTrue(5, TimeUnit.SECONDS, check); @@ -49,18 +54,23 @@ public void singleListening() { @Test public void nonListening() { - final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(container, ImmutableSet.of(8080, 1234)); + final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck( + container, + ImmutableSet.of(8080, 1234) + ); try { Unreliables.retryUntilTrue(5, TimeUnit.SECONDS, check); VisibleAssertions.fail("expected to fail"); - } catch (TimeoutException e) { - } + } catch (TimeoutException e) {} } @Test public void lowAndHighPortListening() { - final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck(container, ImmutableSet.of(100, 8080)); + final InternalCommandPortListeningCheck check = new InternalCommandPortListeningCheck( + container, + ImmutableSet.of(100, 8080) + ); Unreliables.retryUntilTrue(5, TimeUnit.SECONDS, check); diff --git a/core/src/test/java/org/testcontainers/containers/wait/strategy/DockerHealthcheckWaitStrategyTest.java b/core/src/test/java/org/testcontainers/containers/wait/strategy/DockerHealthcheckWaitStrategyTest.java index d867233f5d7..0d102def5a9 100644 --- a/core/src/test/java/org/testcontainers/containers/wait/strategy/DockerHealthcheckWaitStrategyTest.java +++ b/core/src/test/java/org/testcontainers/containers/wait/strategy/DockerHealthcheckWaitStrategyTest.java @@ -17,10 +17,16 @@ public class DockerHealthcheckWaitStrategyTest { @Before public void setUp() { // Using a Dockerfile here, since Dockerfile builder DSL doesn't support HEALTHCHECK - container = new GenericContainer(new ImageFromDockerfile() - .withFileFromClasspath("write_file_and_loop.sh", "health-wait-strategy-dockerfile/write_file_and_loop.sh") - .withFileFromClasspath("Dockerfile", "health-wait-strategy-dockerfile/Dockerfile")) - .waitingFor(Wait.forHealthcheck().withStartupTimeout(Duration.ofSeconds(3))); + container = + new GenericContainer( + new ImageFromDockerfile() + .withFileFromClasspath( + "write_file_and_loop.sh", + "health-wait-strategy-dockerfile/write_file_and_loop.sh" + ) + .withFileFromClasspath("Dockerfile", "health-wait-strategy-dockerfile/Dockerfile") + ) + .waitingFor(Wait.forHealthcheck().withStartupTimeout(Duration.ofSeconds(3))); } @Test diff --git a/core/src/test/java/org/testcontainers/containers/wait/strategy/WaitAllStrategyTest.java b/core/src/test/java/org/testcontainers/containers/wait/strategy/WaitAllStrategyTest.java index 897293282bd..2b8ba7c33ec 100644 --- a/core/src/test/java/org/testcontainers/containers/wait/strategy/WaitAllStrategyTest.java +++ b/core/src/test/java/org/testcontainers/containers/wait/strategy/WaitAllStrategyTest.java @@ -19,10 +19,13 @@ public class WaitAllStrategyTest { @Mock private GenericContainer container; + @Mock private WaitStrategy strategy1; + @Mock private WaitStrategy strategy2; + @Mock private WaitStrategy strategy3; @@ -36,32 +39,25 @@ public void setUp() { */ @Test public void parentTimeoutApplies() { - DummyStrategy child1 = new DummyStrategy(Duration.ofMillis(10)); child1.withStartupTimeout(Duration.ofMillis(20)); assertEquals("withStartupTimeout directly sets the timeout", 20L, child1.startupTimeout.toMillis()); - new WaitAllStrategy() - .withStrategy(child1) - .withStartupTimeout(Duration.ofMillis(30)); + new WaitAllStrategy().withStrategy(child1).withStartupTimeout(Duration.ofMillis(30)); assertEquals("WaitAllStrategy overrides a child's timeout", 30L, child1.startupTimeout.toMillis()); } @Test public void parentTimeoutAppliesToMultipleChildren() { - Duration defaultInnerWait = Duration.ofMillis(2); Duration outerWait = Duration.ofMillis(6); DummyStrategy child1 = new DummyStrategy(defaultInnerWait); DummyStrategy child2 = new DummyStrategy(defaultInnerWait); - new WaitAllStrategy() - .withStrategy(child1) - .withStrategy(child2) - .withStartupTimeout(outerWait); + new WaitAllStrategy().withStrategy(child1).withStrategy(child2).withStartupTimeout(outerWait); assertEquals("WaitAllStrategy overrides a child's timeout (1st)", 6L, child1.startupTimeout.toMillis()); assertEquals("WaitAllStrategy overrides a child's timeout (2nd)", 6L, child2.startupTimeout.toMillis()); @@ -69,20 +65,20 @@ public void parentTimeoutAppliesToMultipleChildren() { @Test public void parentTimeoutAppliesToAdditionalChildren() { - Duration defaultInnerWait = Duration.ofMillis(2); Duration outerWait = Duration.ofMillis(20); DummyStrategy child1 = new DummyStrategy(defaultInnerWait); DummyStrategy child2 = new DummyStrategy(defaultInnerWait); - new WaitAllStrategy() - .withStrategy(child1) - .withStartupTimeout(outerWait) - .withStrategy(child2); + new WaitAllStrategy().withStrategy(child1).withStartupTimeout(outerWait).withStrategy(child2); assertEquals("WaitAllStrategy overrides a child's timeout (1st)", 20L, child1.startupTimeout.toMillis()); - assertEquals("WaitAllStrategy overrides a child's timeout (2nd, additional)", 20L, child2.startupTimeout.toMillis()); + assertEquals( + "WaitAllStrategy overrides a child's timeout (2nd, additional)", + 20L, + child2.startupTimeout.toMillis() + ); } /* @@ -90,10 +86,7 @@ public void parentTimeoutAppliesToAdditionalChildren() { */ @Test public void childExecutionTest() { - - final WaitStrategy underTest = new WaitAllStrategy() - .withStrategy(strategy1) - .withStrategy(strategy2); + final WaitStrategy underTest = new WaitAllStrategy().withStrategy(strategy1).withStrategy(strategy2); doNothing().when(strategy1).waitUntilReady(eq(container)); doNothing().when(strategy2).waitUntilReady(eq(container)); @@ -107,7 +100,6 @@ public void childExecutionTest() { @Test public void withoutOuterTimeoutShouldRelyOnInnerStrategies() { - final WaitStrategy underTest = new WaitAllStrategy(WaitAllStrategy.Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY) .withStrategy(strategy1) .withStrategy(strategy2) @@ -116,9 +108,13 @@ public void withoutOuterTimeoutShouldRelyOnInnerStrategies() { doNothing().when(strategy1).waitUntilReady(eq(container)); doThrow(TimeoutException.class).when(strategy2).waitUntilReady(eq(container)); - assertThrows("The outer strategy timeout applies", TimeoutException.class, () -> { - underTest.waitUntilReady(container); - }); + assertThrows( + "The outer strategy timeout applies", + TimeoutException.class, + () -> { + underTest.waitUntilReady(container); + } + ); InOrder inOrder = inOrder(strategy1, strategy2, strategy3); inOrder.verify(strategy1).waitUntilReady(any()); @@ -128,17 +124,19 @@ public void withoutOuterTimeoutShouldRelyOnInnerStrategies() { @Test public void timeoutChangeShouldNotBePossibleWithIndividualTimeoutMode() { - final WaitStrategy underTest = new WaitAllStrategy(WaitAllStrategy.Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY); - assertThrows("Cannot change timeout for individual timeouts", IllegalStateException.class, () -> { - underTest.withStartupTimeout(Duration.ofSeconds(42)); - }); + assertThrows( + "Cannot change timeout for individual timeouts", + IllegalStateException.class, + () -> { + underTest.withStartupTimeout(Duration.ofSeconds(42)); + } + ); } @Test public void shouldNotMessWithIndividualTimeouts() { - new WaitAllStrategy(WaitAllStrategy.Mode.WITH_INDIVIDUAL_TIMEOUTS_ONLY) .withStrategy(strategy1) .withStrategy(strategy2); @@ -149,18 +147,15 @@ public void shouldNotMessWithIndividualTimeouts() { @Test public void shouldOverwriteIndividualTimeouts() { - Duration someSeconds = Duration.ofSeconds(23); - new WaitAllStrategy() - .withStartupTimeout(someSeconds) - .withStrategy(strategy1) - .withStrategy(strategy2); + new WaitAllStrategy().withStartupTimeout(someSeconds).withStrategy(strategy1).withStrategy(strategy2); verify(strategy1).withStartupTimeout(someSeconds); verify(strategy1).withStartupTimeout(someSeconds); } static class DummyStrategy extends AbstractWaitStrategy { + DummyStrategy(Duration defaultInnerWait) { super.startupTimeout = defaultInnerWait; } diff --git a/core/src/test/java/org/testcontainers/dockerclient/AmbiguousImagePullTest.java b/core/src/test/java/org/testcontainers/dockerclient/AmbiguousImagePullTest.java index 2e39b367c46..f67ad212d77 100644 --- a/core/src/test/java/org/testcontainers/dockerclient/AmbiguousImagePullTest.java +++ b/core/src/test/java/org/testcontainers/dockerclient/AmbiguousImagePullTest.java @@ -14,8 +14,7 @@ public void testNotUsingParse() { DockerImageName imageName = registryContainer.createImage("latest"); String imageNameWithoutTag = imageName.getRegistry() + "/" + imageName.getRepository(); try ( - final GenericContainer container = new GenericContainer<>(imageNameWithoutTag) - .withExposedPorts(8080) + final GenericContainer container = new GenericContainer<>(imageNameWithoutTag).withExposedPorts(8080) ) { container.start(); // do nothing other than start and stop diff --git a/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java b/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java index 442c2efd950..39e1338bc46 100644 --- a/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java +++ b/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java @@ -17,29 +17,39 @@ public class DockerClientConfigUtilsTest { @Test public void getDockerHostIpAddressShouldReturnLocalhostWhenUnixSocket() { - Assumptions.assumeThat(DockerClientConfigUtils.IN_A_CONTAINER) - .as("in a container") - .isFalse(); + Assumptions.assumeThat(DockerClientConfigUtils.IN_A_CONTAINER).as("in a container").isFalse(); - String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress(client, URI.create("unix:///var/run/docker.sock")); + String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress( + client, + URI.create("unix:///var/run/docker.sock") + ); assertEquals("localhost", actual); } @Test public void getDockerHostIpAddressShouldReturnDockerHostIpWhenHttpsUri() { - String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress(client, URI.create("http://12.23.34.45")); + String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress( + client, + URI.create("http://12.23.34.45") + ); assertEquals("12.23.34.45", actual); } @Test public void getDockerHostIpAddressShouldReturnDockerHostIpWhenTcpUri() { - String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress(client, URI.create("tcp://12.23.34.45")); + String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress( + client, + URI.create("tcp://12.23.34.45") + ); assertEquals("12.23.34.45", actual); } @Test public void getDockerHostIpAddressShouldReturnNullWhenUnsupportedUriScheme() { - String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress(client, URI.create("gopher://12.23.34.45")); + String actual = DockerClientProviderStrategy.resolveDockerHostIpAddress( + client, + URI.create("gopher://12.23.34.45") + ); assertNull(actual); } diff --git a/core/src/test/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategyTest.java b/core/src/test/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategyTest.java index a6bd68be745..b2ab27aad27 100644 --- a/core/src/test/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategyTest.java +++ b/core/src/test/java/org/testcontainers/dockerclient/EnvironmentAndSystemPropertyClientProviderStrategyTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -35,7 +34,9 @@ public class EnvironmentAndSystemPropertyClientProviderStrategyTest { @Rule public MockTestcontainersConfigurationRule mockConfig = new MockTestcontainersConfigurationRule(); + private URI defaultDockerHost; + private com.github.dockerjava.core.SSLConfig defaultSSLConfig; @Before @@ -48,10 +49,22 @@ public void checkEnvironmentClear() { @Test public void testWhenConfigAbsent() { - Mockito.doReturn("auto").when(TestcontainersConfiguration.getInstance()).getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); - Mockito.doReturn(null).when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.host"), isNull()); - Mockito.doReturn(null).when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.tls.verify"), isNull()); - Mockito.doReturn(null).when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.cert.path"), isNull()); + Mockito + .doReturn("auto") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); + Mockito + .doReturn(null) + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.host"), isNull()); + Mockito + .doReturn(null) + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.tls.verify"), isNull()); + Mockito + .doReturn(null) + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.cert.path"), isNull()); EnvironmentAndSystemPropertyClientProviderStrategy strategy = new EnvironmentAndSystemPropertyClientProviderStrategy(); @@ -62,10 +75,22 @@ public void testWhenConfigAbsent() { @Test public void testWhenDockerHostPresent() { - Mockito.doReturn("auto").when(TestcontainersConfiguration.getInstance()).getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); - Mockito.doReturn("tcp://1.2.3.4:2375").when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.host"), isNull()); - Mockito.doReturn(null).when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.tls.verify"), isNull()); - Mockito.doReturn(null).when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.cert.path"), isNull()); + Mockito + .doReturn("auto") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); + Mockito + .doReturn("tcp://1.2.3.4:2375") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.host"), isNull()); + Mockito + .doReturn(null) + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.tls.verify"), isNull()); + Mockito + .doReturn(null) + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.cert.path"), isNull()); EnvironmentAndSystemPropertyClientProviderStrategy strategy = new EnvironmentAndSystemPropertyClientProviderStrategy(); @@ -79,10 +104,22 @@ public void testWhenDockerHostAndSSLConfigPresent() throws IOException { Path tempDir = Files.createTempDirectory("testcontainers-test"); String tempDirPath = tempDir.toAbsolutePath().toString(); - Mockito.doReturn("auto").when(TestcontainersConfiguration.getInstance()).getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); - Mockito.doReturn("tcp://1.2.3.4:2375").when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.host"), isNull()); - Mockito.doReturn("1").when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.tls.verify"), isNull()); - Mockito.doReturn(tempDirPath).when(TestcontainersConfiguration.getInstance()).getEnvVarOrUserProperty(eq("docker.cert.path"), isNull()); + Mockito + .doReturn("auto") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); + Mockito + .doReturn("tcp://1.2.3.4:2375") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.host"), isNull()); + Mockito + .doReturn("1") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.tls.verify"), isNull()); + Mockito + .doReturn(tempDirPath) + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrUserProperty(eq("docker.cert.path"), isNull()); EnvironmentAndSystemPropertyClientProviderStrategy strategy = new EnvironmentAndSystemPropertyClientProviderStrategy(); @@ -90,14 +127,15 @@ public void testWhenDockerHostAndSSLConfigPresent() throws IOException { assertEquals("tcp://1.2.3.4:2375", transportConfig.getDockerHost().toString()); SSLConfig sslConfig = transportConfig.getSslConfig(); - Assertions.assertThat(sslConfig) - .extracting("dockerCertPath") - .isEqualTo(tempDirPath); + Assertions.assertThat(sslConfig).extracting("dockerCertPath").isEqualTo(tempDirPath); } @Test public void applicableWhenIgnoringUserPropertiesAndConfigured() { - Mockito.doReturn("autoIgnoringUserProperties").when(TestcontainersConfiguration.getInstance()).getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); + Mockito + .doReturn("autoIgnoringUserProperties") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); Properties oldProperties = System.getProperties(); try { @@ -112,7 +150,10 @@ public void applicableWhenIgnoringUserPropertiesAndConfigured() { @Test public void notApplicableWhenIgnoringUserPropertiesAndNotConfigured() { - Mockito.doReturn("autoIgnoringUserProperties").when(TestcontainersConfiguration.getInstance()).getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); + Mockito + .doReturn("autoIgnoringUserProperties") + .when(TestcontainersConfiguration.getInstance()) + .getEnvVarOrProperty(eq("dockerconfig.source"), anyString()); EnvironmentAndSystemPropertyClientProviderStrategy strategy = new EnvironmentAndSystemPropertyClientProviderStrategy(); diff --git a/core/src/test/java/org/testcontainers/dockerclient/EventStreamTest.java b/core/src/test/java/org/testcontainers/dockerclient/EventStreamTest.java index a43a001ca5b..642eb6d7390 100644 --- a/core/src/test/java/org/testcontainers/dockerclient/EventStreamTest.java +++ b/core/src/test/java/org/testcontainers/dockerclient/EventStreamTest.java @@ -8,6 +8,7 @@ import org.junit.Test; import org.junit.rules.Timeout; import org.testcontainers.DockerClientFactory; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; @@ -16,8 +17,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static org.testcontainers.TestImages.TINY_IMAGE; - /** * Test that event streaming from the {@link DockerClient} works correctly */ @@ -34,7 +33,7 @@ public void test() throws IOException, InterruptedException { CountDownLatch latch = new CountDownLatch(1); try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withCommand("true") .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) ) { @@ -43,24 +42,31 @@ public void test() throws IOException, InterruptedException { // Request all events between startTime and endTime for the container try ( - EventsResultCallback response = DockerClientFactory.instance().client().eventsCmd() + EventsResultCallback response = DockerClientFactory + .instance() + .client() + .eventsCmd() .withContainerFilter(container.getContainerId()) .withEventFilter("create") .withSince(Instant.parse(createdAt).getEpochSecond() + "") - .exec(new EventsResultCallback() { - @Override - public void onNext(@NotNull Event event) { - // Check that a create event for the container is received - if (event.getId().equals(container.getContainerId()) && event.getStatus().equals("create")) { - latch.countDown(); + .exec( + new EventsResultCallback() { + @Override + public void onNext(@NotNull Event event) { + // Check that a create event for the container is received + if ( + event.getId().equals(container.getContainerId()) && + event.getStatus().equals("create") + ) { + latch.countDown(); + } } } - }) + ) ) { response.awaitStarted(5, TimeUnit.SECONDS); latch.await(5, TimeUnit.SECONDS); } } } - } diff --git a/core/src/test/java/org/testcontainers/dockerclient/ImagePullTest.java b/core/src/test/java/org/testcontainers/dockerclient/ImagePullTest.java index 8691e8f5f56..730208c553f 100644 --- a/core/src/test/java/org/testcontainers/dockerclient/ImagePullTest.java +++ b/core/src/test/java/org/testcontainers/dockerclient/ImagePullTest.java @@ -22,7 +22,7 @@ public static String[] parameters() { "quay.io/testcontainers/ryuk:latest", "quay.io/testcontainers/ryuk:0.2.3", "quay.io/testcontainers/ryuk@sha256:bb5a635cac4bd96c93cc476969ce11dc56436238ec7cd028d0524462f4739dd9", -// "ibmcom/db2express-c", // Big image for testing with slow networks + // "ibmcom/db2express-c", // Big image for testing with slow networks }; } @@ -32,9 +32,11 @@ public ImagePullTest(String image) { @Test public void test() { - try (final GenericContainer container = new GenericContainer<>(DockerImageName.parse(image)) - .withCommand("/bin/sh", "-c", "sleep 0") - .withStartupCheckStrategy(new OneShotStartupCheckStrategy())) { + try ( + final GenericContainer container = new GenericContainer<>(DockerImageName.parse(image)) + .withCommand("/bin/sh", "-c", "sleep 0") + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) + ) { container.start(); // do nothing other than start and stop } diff --git a/core/src/test/java/org/testcontainers/images/AgeBasedPullPolicyTest.java b/core/src/test/java/org/testcontainers/images/AgeBasedPullPolicyTest.java index e073fa0522a..96fdfa4010b 100644 --- a/core/src/test/java/org/testcontainers/images/AgeBasedPullPolicyTest.java +++ b/core/src/test/java/org/testcontainers/images/AgeBasedPullPolicyTest.java @@ -1,15 +1,15 @@ package org.testcontainers.images; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.testcontainers.utility.DockerImageName; import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.UUID; -import org.junit.Test; -import org.testcontainers.utility.DockerImageName; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class AgeBasedPullPolicyTest { @@ -17,9 +17,7 @@ public class AgeBasedPullPolicyTest { @Test public void shouldPull() { - ImageData imageData = ImageData.builder() - .createdAt(Instant.now().minus(2, ChronoUnit.HOURS)) - .build(); + ImageData imageData = ImageData.builder().createdAt(Instant.now().minus(2, ChronoUnit.HOURS)).build(); AgeBasedPullPolicy oneHour = new AgeBasedPullPolicy(Duration.of(1L, ChronoUnit.HOURS)); assertTrue(oneHour.shouldPullCached(imageName, imageData)); diff --git a/core/src/test/java/org/testcontainers/images/ImageDataTest.java b/core/src/test/java/org/testcontainers/images/ImageDataTest.java index 3b473cf7ffd..6ff75e9e355 100644 --- a/core/src/test/java/org/testcontainers/images/ImageDataTest.java +++ b/core/src/test/java/org/testcontainers/images/ImageDataTest.java @@ -1,12 +1,11 @@ package org.testcontainers.images; -import static org.assertj.core.api.Assertions.assertThat; +import com.github.dockerjava.api.command.InspectImageResponse; +import org.junit.Test; import java.time.Instant; -import org.junit.Test; - -import com.github.dockerjava.api.command.InspectImageResponse; +import static org.assertj.core.api.Assertions.assertThat; public class ImageDataTest { @@ -23,5 +22,4 @@ public void shouldReadTimestampWithOffsetFromInspectImageResponse() { final ImageData imageData = ImageData.from(new InspectImageResponse().withCreated(timestamp)); assertThat(imageData.getCreatedAt()).isEqualTo(Instant.parse("2020-07-27T16:23:31.365190246Z")); } - } diff --git a/core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java b/core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java index 9d5ed400d32..0b0ee5f1b70 100644 --- a/core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java +++ b/core/src/test/java/org/testcontainers/images/ImagePullPolicyTest.java @@ -24,29 +24,20 @@ public class ImagePullPolicyTest { @Test public void pullsByDefault() { - try ( - GenericContainer container = new GenericContainer<>(imageName) - .withExposedPorts(8080) - ) { + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { container.start(); } } @Test public void shouldAlwaysPull() { - try ( - GenericContainer container = new GenericContainer<>(imageName) - .withExposedPorts(8080) - ) { + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { container.start(); } removeImage(); - try ( - GenericContainer container = new GenericContainer<>(imageName) - .withExposedPorts(8080) - ) { + try (GenericContainer container = new GenericContainer<>(imageName).withExposedPorts(8080)) { expectToFailWithNotFoundException(container); } @@ -66,12 +57,14 @@ public void shouldSupportCustomPolicies() { try ( // custom_image_pull_policy { GenericContainer container = new GenericContainer<>(imageName) - .withImagePullPolicy(new AbstractImagePullPolicy() { - @Override - protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) { - return System.getenv("ALWAYS_PULL_IMAGE") != null; + .withImagePullPolicy( + new AbstractImagePullPolicy() { + @Override + protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) { + return System.getenv("ALWAYS_PULL_IMAGE") != null; + } } - }) + ) // } ) { container.withExposedPorts(8080); @@ -81,12 +74,14 @@ protected boolean shouldPullCached(DockerImageName imageName, ImageData localIma @Test public void shouldCheckPolicy() { - ImagePullPolicy policy = Mockito.spy(new AbstractImagePullPolicy() { - @Override - protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) { - return false; + ImagePullPolicy policy = Mockito.spy( + new AbstractImagePullPolicy() { + @Override + protected boolean shouldPullCached(DockerImageName imageName, ImageData localImageData) { + return false; + } } - }); + ); try ( GenericContainer container = new GenericContainer<>(imageName) .withImagePullPolicy(policy) @@ -128,11 +123,12 @@ private void expectToFailWithNotFoundException(GenericContainer container) { private void removeImage() { try { - DockerClientFactory.instance().client() + DockerClientFactory + .instance() + .client() .removeImageCmd(imageName.asCanonicalNameString()) .withForce(true) .exec(); - } catch (NotFoundException ignored) { - } + } catch (NotFoundException ignored) {} } } diff --git a/core/src/test/java/org/testcontainers/images/ParsedDockerfileTest.java b/core/src/test/java/org/testcontainers/images/ParsedDockerfileTest.java index 52a22c83b00..cd4509965e6 100644 --- a/core/src/test/java/org/testcontainers/images/ParsedDockerfileTest.java +++ b/core/src/test/java/org/testcontainers/images/ParsedDockerfileTest.java @@ -4,69 +4,119 @@ import org.junit.Test; import java.nio.file.Paths; +import java.util.Arrays; -import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; public class ParsedDockerfileTest { @Test public void doesSimpleParsing() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("FROM someimage", "RUN something")); - assertEquals("extracts a single image name", Sets.newHashSet("someimage"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("FROM someimage", "RUN something") + ); + assertEquals( + "extracts a single image name", + Sets.newHashSet("someimage"), + parsedDockerfile.getDependencyImageNames() + ); } @Test public void isCaseInsensitive() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("from someimage", "RUN something")); - assertEquals("extracts a single image name", Sets.newHashSet("someimage"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("from someimage", "RUN something") + ); + assertEquals( + "extracts a single image name", + Sets.newHashSet("someimage"), + parsedDockerfile.getDependencyImageNames() + ); } @Test public void handlesTags() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("FROM someimage:tag", "RUN something")); - assertEquals("retains tags in image names", Sets.newHashSet("someimage:tag"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("FROM someimage:tag", "RUN something") + ); + assertEquals( + "retains tags in image names", + Sets.newHashSet("someimage:tag"), + parsedDockerfile.getDependencyImageNames() + ); } @Test public void handlesDigests() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("FROM someimage@sha256:abc123", "RUN something")); - assertEquals("retains digests in image names", Sets.newHashSet("someimage@sha256:abc123"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("FROM someimage@sha256:abc123", "RUN something") + ); + assertEquals( + "retains digests in image names", + Sets.newHashSet("someimage@sha256:abc123"), + parsedDockerfile.getDependencyImageNames() + ); } @Test public void ignoringCommentedFromLines() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("FROM someimage", "#FROM somethingelse")); - assertEquals("ignores commented from lines", Sets.newHashSet("someimage"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("FROM someimage", "#FROM somethingelse") + ); + assertEquals( + "ignores commented from lines", + Sets.newHashSet("someimage"), + parsedDockerfile.getDependencyImageNames() + ); } @Test public void ignoringBuildStageNames() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("FROM someimage --as=base", "RUN something", "FROM nextimage", "RUN something")); - assertEquals("ignores build stage names and allows multiple images to be extracted", Sets.newHashSet("someimage", "nextimage"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("FROM someimage --as=base", "RUN something", "FROM nextimage", "RUN something") + ); + assertEquals( + "ignores build stage names and allows multiple images to be extracted", + Sets.newHashSet("someimage", "nextimage"), + parsedDockerfile.getDependencyImageNames() + ); } @Test public void ignoringPlatformArgs() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("FROM --platform=linux/amd64 someimage", "RUN something")); - assertEquals("ignores platform args", Sets.newHashSet("someimage"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("FROM --platform=linux/amd64 someimage", "RUN something") + ); + assertEquals("ignores platform args", Sets.newHashSet("someimage"), parsedDockerfile.getDependencyImageNames()); } @Test public void ignoringExtraPlatformArgs() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("FROM --platform=linux/amd64 --somethingelse=value someimage", "RUN something")); - assertEquals("ignores platform args", Sets.newHashSet("someimage"), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("FROM --platform=linux/amd64 --somethingelse=value someimage", "RUN something") + ); + assertEquals("ignores platform args", Sets.newHashSet("someimage"), parsedDockerfile.getDependencyImageNames()); } @Test public void handlesGracefullyIfNoFromLine() { - final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(asList("RUN something", "# is this even a valid Dockerfile?")); - assertEquals("handles invalid Dockerfiles gracefully", Sets.newHashSet(), parsedDockerfile.getDependencyImageNames()); + final ParsedDockerfile parsedDockerfile = new ParsedDockerfile( + Arrays.asList("RUN something", "# is this even a valid Dockerfile?") + ); + assertEquals( + "handles invalid Dockerfiles gracefully", + Sets.newHashSet(), + parsedDockerfile.getDependencyImageNames() + ); } @Test public void handlesGracefullyIfDockerfileNotFound() { final ParsedDockerfile parsedDockerfile = new ParsedDockerfile(Paths.get("nonexistent.Dockerfile")); - assertEquals("handles missing Dockerfiles gracefully", Sets.newHashSet(), parsedDockerfile.getDependencyImageNames()); + assertEquals( + "handles missing Dockerfiles gracefully", + Sets.newHashSet(), + parsedDockerfile.getDependencyImageNames() + ); } } diff --git a/core/src/test/java/org/testcontainers/images/RemoteDockerImageTest.java b/core/src/test/java/org/testcontainers/images/RemoteDockerImageTest.java index d2ea3e7188a..592d46f33d1 100644 --- a/core/src/test/java/org/testcontainers/images/RemoteDockerImageTest.java +++ b/core/src/test/java/org/testcontainers/images/RemoteDockerImageTest.java @@ -9,7 +9,7 @@ import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; @@ -23,7 +23,7 @@ public void toStringContainsOnlyImageName() { } @Test - public void toStringWithExceptionContainsOnlyImageNameFuture() { + public void toStringWithExceptionContainsOnlyImageNameFuture() { CompletableFuture imageNameFuture = new CompletableFuture<>(); imageNameFuture.completeExceptionally(new RuntimeException("arbitrary")); @@ -31,8 +31,8 @@ public void toStringWithExceptionContainsOnlyImageNameFuture() { assertThat(remoteDockerImage.toString(), containsString("imageName=java.lang.RuntimeException: arbitrary")); } - @Test(timeout=5000L) - public void toStringDoesntResolveImageNameFuture() { + @Test(timeout = 5000L) + public void toStringDoesntResolveImageNameFuture() { CompletableFuture imageNameFuture = new CompletableFuture<>(); // verify that we've set up the test properly @@ -49,7 +49,7 @@ public void toStringDoesntResolveImageNameFuture() { assertThat(remoteDockerImage.toString(), containsString("imageName=" + imageName)); } - @Test(timeout=5000L) + @Test(timeout = 5000L) public void toStringDoesntResolveLazyFuture() throws Exception { String imageName = Base58.randomString(8).toLowerCase(); AtomicBoolean resolved = new AtomicBoolean(false); diff --git a/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java b/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java index 9a9d647d71b..29cf4fcf6a7 100644 --- a/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/DockerfileBuildTest.java @@ -6,7 +6,6 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; -import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; @@ -18,39 +17,41 @@ public class DockerfileBuildTest { static final Path RESOURCE_PATH = Paths.get("src/test/resources/dockerfile-build-test"); public String expectedFileContent; + public ImageFromDockerfile image; @Parameterized.Parameters public static Object[][] parameters() { - return new Object[][]{ + return new Object[][] { // Dockerfile build without explicit per-file inclusion - new Object[]{"test1234", + new Object[] { + "test1234", + // spotless:off // docsShowRecursiveFileInclusion { new ImageFromDockerfile() - .withFileFromPath(".", RESOURCE_PATH) + .withFileFromPath(".", RESOURCE_PATH), // } + // spotless:on }, - // Dockerfile build using a non-standard Dockerfile - new Object[]{"test4567", - new ImageFromDockerfile() - .withFileFromPath(".", RESOURCE_PATH) - .withDockerfilePath("./Dockerfile-alt") + new Object[] { + "test4567", + new ImageFromDockerfile().withFileFromPath(".", RESOURCE_PATH).withDockerfilePath("./Dockerfile-alt"), }, - // Dockerfile build using build args - new Object[]{"test7890", + new Object[] { + "test7890", new ImageFromDockerfile() .withFileFromPath(".", RESOURCE_PATH) .withDockerfilePath("./Dockerfile-buildarg") - .withBuildArg("CUSTOM_ARG", "test7890") + .withBuildArg("CUSTOM_ARG", "test7890"), }, - - // Dockerfile build using withDockerfile(File) - new Object[]{"test4567", + // Dockerfile build using withDockerfile(File) + new Object[] { + "test4567", new ImageFromDockerfile() .withFileFromPath(".", RESOURCE_PATH) - .withDockerfile(RESOURCE_PATH.resolve("Dockerfile-alt")) + .withDockerfile(RESOURCE_PATH.resolve("Dockerfile-alt")), }, }; } @@ -62,14 +63,18 @@ public DockerfileBuildTest(String expectedFileContent, ImageFromDockerfile image @Test public void performTest() { - try (final GenericContainer container = new GenericContainer(image) - .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) - .withCommand("cat", "/test.txt")) { + try ( + final GenericContainer container = new GenericContainer(image) + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) + .withCommand("cat", "/test.txt") + ) { container.start(); final String logs = container.getLogs(); - assertTrue("expected file content indicates that dockerfile build steps have been run", logs.contains(expectedFileContent)); + assertTrue( + "expected file content indicates that dockerfile build steps have been run", + logs.contains(expectedFileContent) + ); } } - } diff --git a/core/src/test/java/org/testcontainers/images/builder/DockerignoreTest.java b/core/src/test/java/org/testcontainers/images/builder/DockerignoreTest.java index b99a70a7650..513b1ce1784 100644 --- a/core/src/test/java/org/testcontainers/images/builder/DockerignoreTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/DockerignoreTest.java @@ -24,10 +24,10 @@ public void testInvalidDockerignore() throws Exception { .withDockerfile(INVALID_DOCKERIGNORE_PATH.resolve("Dockerfile")) .get(); fail("Should not be able to build an image with an invalid .dockerignore file"); - } - catch (DockerClientException e) { - if (!e.getMessage().contains("Invalid pattern")) + } catch (DockerClientException e) { + if (!e.getMessage().contains("Invalid pattern")) { throw e; + } } } @@ -35,22 +35,24 @@ public void testInvalidDockerignore() throws Exception { @Test public void testValidDockerignore() throws Exception { ImageFromDockerfile img = new ImageFromDockerfile() - .withFileFromPath(".", DockerfileBuildTest.RESOURCE_PATH) - .withDockerfile(DockerfileBuildTest.RESOURCE_PATH.resolve("Dockerfile-currentdir")); - try( + .withFileFromPath(".", DockerfileBuildTest.RESOURCE_PATH) + .withDockerfile(DockerfileBuildTest.RESOURCE_PATH.resolve("Dockerfile-currentdir")); + try ( final GenericContainer container = new GenericContainer(DockerImageName.parse(img.get())) - .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) - .withCommand("ls", "/") + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) + .withCommand("ls", "/") ) { - container.start(); final String logs = container.getLogs(); - assertTrue("Files in the container indicated the .dockerignore was not applied. Output was: " + logs, - logs.contains("should_not_be_ignored.txt")); - assertTrue("Files in the container indicated the .dockerignore was not applied. Output was: " + logs, - !logs.contains("should_be_ignored.txt")); + assertTrue( + "Files in the container indicated the .dockerignore was not applied. Output was: " + logs, + logs.contains("should_not_be_ignored.txt") + ); + assertTrue( + "Files in the container indicated the .dockerignore was not applied. Output was: " + logs, + !logs.contains("should_be_ignored.txt") + ); } } - } diff --git a/core/src/test/java/org/testcontainers/images/builder/ImageFromDockerfileTest.java b/core/src/test/java/org/testcontainers/images/builder/ImageFromDockerfileTest.java index da3509cea7b..abc05eb567c 100644 --- a/core/src/test/java/org/testcontainers/images/builder/ImageFromDockerfileTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/ImageFromDockerfileTest.java @@ -12,8 +12,7 @@ public class ImageFromDockerfileTest { @Test public void shouldAddDefaultLabels() { - ImageFromDockerfile image = new ImageFromDockerfile() - .withDockerfileFromBuilder(it -> it.from("scratch")); + ImageFromDockerfile image = new ImageFromDockerfile().withDockerfileFromBuilder(it -> it.from("scratch")); String imageId = image.resolve(); @@ -27,7 +26,10 @@ public void shouldAddDefaultLabels() { @Test public void shouldNotAddSessionLabelIfDeleteOnExitIsFalse() { - ImageFromDockerfile image = new ImageFromDockerfile("localhost/testcontainers/" + Base58.randomString(16).toLowerCase(), false) + ImageFromDockerfile image = new ImageFromDockerfile( + "localhost/testcontainers/" + Base58.randomString(16).toLowerCase(), + false + ) .withDockerfileFromBuilder(it -> it.from("scratch")); String imageId = image.resolve(); DockerClient dockerClient = DockerClientFactory.instance().client(); @@ -40,7 +42,5 @@ public void shouldNotAddSessionLabelIfDeleteOnExitIsFalse() { // ensure the image is deleted, even if the test fails dockerClient.removeImageCmd(imageId).exec(); } - } - } diff --git a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/AbstractStatementTest.java b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/AbstractStatementTest.java index 15c73cadb5f..69d9a1b6840 100644 --- a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/AbstractStatementTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/AbstractStatementTest.java @@ -19,7 +19,6 @@ public abstract class AbstractStatementTest { public TestName testName = new TestName(); protected void assertStatement(Statement statement) { - String[] expectedLines = new String[0]; try { String path = "fixtures/statements/" + getClass().getSimpleName() + "/" + testName.getMethodName(); @@ -39,7 +38,9 @@ protected void assertStatement(Statement statement) { String[] resultLines = StringUtils.chomp(builder.toString().trim()).split("\n"); if (expectedLines.length != resultLines.length) { - fail("number of lines is not the same. Expected " + expectedLines.length + " but got " + resultLines.length); + fail( + "number of lines is not the same. Expected " + expectedLines.length + " but got " + resultLines.length + ); } if (!Arrays.equals(expectedLines, resultLines)) { @@ -59,7 +60,6 @@ protected void assertStatement(Statement statement) { failureBuilder.append(expectedLine); failureBuilder.append(">\n"); } - } fail(failureBuilder.toString()); diff --git a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/KeyValuesStatementTest.java b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/KeyValuesStatementTest.java index 6add9d462f2..f446e48b42c 100644 --- a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/KeyValuesStatementTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/KeyValuesStatementTest.java @@ -9,11 +9,12 @@ public class KeyValuesStatementTest extends AbstractStatementTest { @Test public void multilineTest() throws Exception { - ImmutableMap pairs = ImmutableMap.builder() - .put("line1", "1") - .put("line2", "2") - .put("line3", "3") - .build(); + ImmutableMap pairs = ImmutableMap + .builder() + .put("line1", "1") + .put("line2", "2") + .put("line3", "3") + .build(); assertStatement(new KeyValuesStatement("TEST", pairs)); } @@ -35,12 +36,13 @@ public void keyWithTabsTest() throws Exception { @Test public void valueIsEscapedTest() throws Exception { - ImmutableMap pairs = ImmutableMap.builder() - .put("1", "value with spaces") - .put("2", "value\nwith\nnewlines") - .put("3", "value\twith\ttab") - .build(); + ImmutableMap pairs = ImmutableMap + .builder() + .put("1", "value with spaces") + .put("2", "value\nwith\nnewlines") + .put("3", "value\twith\ttab") + .build(); assertStatement(new KeyValuesStatement("TEST", pairs)); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/MultiArgsStatementTest.java b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/MultiArgsStatementTest.java index 3b36af8861e..50bc8bedd96 100644 --- a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/MultiArgsStatementTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/MultiArgsStatementTest.java @@ -13,4 +13,4 @@ public void simpleTest() throws Exception { public void multilineTest() throws Exception { assertStatement(new MultiArgsStatement("TEST", "some\nmultiline\nargument")); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/RawStatementTest.java b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/RawStatementTest.java index a600451bd71..70724a03f09 100644 --- a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/RawStatementTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/RawStatementTest.java @@ -8,5 +8,4 @@ public class RawStatementTest extends AbstractStatementTest { public void simpleTest() throws Exception { assertStatement(new RawStatement("TEST", "value\nas\t\\\nis")); } - -} \ No newline at end of file +} diff --git a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/SingleArgumentStatementTest.java b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/SingleArgumentStatementTest.java index 75d290b240d..dbdabab9fff 100644 --- a/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/SingleArgumentStatementTest.java +++ b/core/src/test/java/org/testcontainers/images/builder/dockerfile/statement/SingleArgumentStatementTest.java @@ -13,4 +13,4 @@ public void simpleTest() throws Exception { public void multilineTest() throws Exception { assertStatement(new SingleArgumentStatement("TEST", "hello\nworld")); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/testcontainers/junit/BaseDockerComposeTest.java b/core/src/test/java/org/testcontainers/junit/BaseDockerComposeTest.java index 7f8b5d79953..dd62ace1fac 100644 --- a/core/src/test/java/org/testcontainers/junit/BaseDockerComposeTest.java +++ b/core/src/test/java/org/testcontainers/junit/BaseDockerComposeTest.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.stream.Collectors; -import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.is; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; @@ -37,7 +37,10 @@ public static void checkVersion() { @Test public void simpleTest() { - Jedis jedis = new Jedis(getEnvironment().getServiceHost("redis_1", REDIS_PORT), getEnvironment().getServicePort("redis_1", REDIS_PORT)); + Jedis jedis = new Jedis( + getEnvironment().getServiceHost("redis_1", REDIS_PORT), + getEnvironment().getServicePort("redis_1", REDIS_PORT) + ); jedis.incr("test"); jedis.incr("test"); @@ -49,7 +52,10 @@ public void simpleTest() { @Test public void secondTest() { // used in manual checking for cleanup in between tests - Jedis jedis = new Jedis(getEnvironment().getServiceHost("redis_1", REDIS_PORT), getEnvironment().getServicePort("redis_1", REDIS_PORT)); + Jedis jedis = new Jedis( + getEnvironment().getServiceHost("redis_1", REDIS_PORT), + getEnvironment().getServicePort("redis_1", REDIS_PORT) + ); jedis.incr("test"); jedis.incr("test"); @@ -62,18 +68,23 @@ public void secondTest() { @Before public void captureNetworks() { - existingNetworks.addAll(findAllNetworks()); + existingNetworks.addAll(findAllNetworks()); } @After public void verifyNoNetworks() { - assertThat("The networks", findAllNetworks(), is(existingNetworks)); + assertThat("The networks", findAllNetworks(), is(existingNetworks)); } private List findAllNetworks() { - return DockerClientFactory.instance().client().listNetworksCmd().exec().stream() - .map(Network::getName) - .sorted() - .collect(Collectors.toList()); + return DockerClientFactory + .instance() + .client() + .listNetworksCmd() + .exec() + .stream() + .map(Network::getName) + .sorted() + .collect(Collectors.toList()); } } diff --git a/core/src/test/java/org/testcontainers/junit/CopyFileToContainerTest.java b/core/src/test/java/org/testcontainers/junit/CopyFileToContainerTest.java index b0ed90d9c9e..7041e74912a 100644 --- a/core/src/test/java/org/testcontainers/junit/CopyFileToContainerTest.java +++ b/core/src/test/java/org/testcontainers/junit/CopyFileToContainerTest.java @@ -1,6 +1,7 @@ package org.testcontainers.junit; import org.junit.Test; +import org.testcontainers.TestImages; import org.testcontainers.containers.BindMode; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.SelinuxContext; @@ -11,16 +12,17 @@ import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.TINY_IMAGE; public class CopyFileToContainerTest { + private static String containerPath = "/tmp/mappable-resource/"; + private static String fileName = "test-resource.txt"; @Test public void checkFileCopied() throws IOException, InterruptedException { try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withCommand("sleep", "3000") .withCopyFileToContainer(MountableFile.forClasspathResource("/mappable-resource/"), containerPath) ) { @@ -33,7 +35,7 @@ public void checkFileCopied() throws IOException, InterruptedException { @Test public void shouldUseCopyForReadOnlyClasspathResources() throws Exception { try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withCommand("sleep", "3000") .withClasspathResourceMapping("/mappable-resource/", containerPath, BindMode.READ_ONLY) ) { @@ -46,10 +48,9 @@ public void shouldUseCopyForReadOnlyClasspathResources() throws Exception { @Test public void shouldUseCopyOnlyWithReadOnlyClasspathResources() { String resource = "/test_copy_to_container.txt"; - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withClasspathResourceMapping(resource, "/readOnly", BindMode.READ_ONLY) .withClasspathResourceMapping(resource, "/readOnlyNoSelinux", BindMode.READ_ONLY) - .withClasspathResourceMapping(resource, "/readOnlyShared", BindMode.READ_ONLY, SelinuxContext.SHARED) .withClasspathResourceMapping(resource, "/readWrite", BindMode.READ_WRITE); @@ -65,7 +66,7 @@ public void shouldUseCopyOnlyWithReadOnlyClasspathResources() { public void shouldCreateFoldersStructureWithCopy() throws Exception { String resource = "/test_copy_to_container.txt"; try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withCommand("sleep", "3000") .withClasspathResourceMapping(resource, "/a/b/c/file", BindMode.READ_ONLY) ) { diff --git a/core/src/test/java/org/testcontainers/junit/DependenciesTest.java b/core/src/test/java/org/testcontainers/junit/DependenciesTest.java index bd82c58a7f7..78e55335d9a 100644 --- a/core/src/test/java/org/testcontainers/junit/DependenciesTest.java +++ b/core/src/test/java/org/testcontainers/junit/DependenciesTest.java @@ -3,6 +3,7 @@ import lombok.Getter; import org.junit.Test; import org.rnorth.visibleassertions.VisibleAssertions; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.lifecycle.Startable; @@ -16,8 +17,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.testcontainers.TestImages.TINY_IMAGE; - public class DependenciesTest { @Test @@ -25,7 +24,7 @@ public void shouldWorkWithSimpleDependency() { InvocationCountingStartable startable = new InvocationCountingStartable(); try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .dependsOn(startable) ) { @@ -42,7 +41,7 @@ public void shouldWorkWithMutlipleDependencies() { InvocationCountingStartable startable2 = new InvocationCountingStartable(); try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .dependsOn(startable1, startable2) ) { @@ -58,7 +57,7 @@ public void shouldStartEveryTime() { InvocationCountingStartable startable = new InvocationCountingStartable(); try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .dependsOn(startable) ) { @@ -85,7 +84,7 @@ public void shouldStartTransitiveDependencies() { startable.getDependencies().add(transitiveStartable); try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .dependsOn(startable) ) { @@ -94,8 +93,16 @@ public void shouldStartTransitiveDependencies() { } VisibleAssertions.assertEquals("Root started", 1, startable.getStartInvocationCount().intValue()); - VisibleAssertions.assertEquals("Transitive started", 1, transitiveStartable.getStartInvocationCount().intValue()); - VisibleAssertions.assertEquals("Transitive of transitive started", 1, transitiveOfTransitiveStartable.getStartInvocationCount().intValue()); + VisibleAssertions.assertEquals( + "Transitive started", + 1, + transitiveStartable.getStartInvocationCount().intValue() + ); + VisibleAssertions.assertEquals( + "Transitive of transitive started", + 1, + transitiveOfTransitiveStartable.getStartInvocationCount().intValue() + ); } @Test @@ -123,7 +130,8 @@ public void shouldHandleDiamondDependencies() throws Exception { @Test public void shouldHandleParallelStream() throws Exception { - List startables = Stream.generate(InvocationCountingStartable::new) + List startables = Stream + .generate(InvocationCountingStartable::new) .limit(10) .collect(Collectors.toList()); diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerScalingTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerScalingTest.java index a44d8de49f4..651696696c7 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerScalingTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerScalingTest.java @@ -24,25 +24,26 @@ public static void checkVersion() { } @Rule - public DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/scaled-compose-test.yml")) - .withScaledService("redis", 3) - .withExposedService("redis", REDIS_PORT) // implicit '_1' - .withExposedService("redis_2", REDIS_PORT) // explicit service index - .withExposedService("redis", 3, REDIS_PORT); // explicit service index via parameter + public DockerComposeContainer environment = new DockerComposeContainer( + new File("src/test/resources/scaled-compose-test.yml") + ) + .withScaledService("redis", 3) + .withExposedService("redis", REDIS_PORT) // implicit '_1' + .withExposedService("redis_2", REDIS_PORT) // explicit service index + .withExposedService("redis", 3, REDIS_PORT); // explicit service index via parameter @Before public void setupClients() { for (int i = 0; i < 3; i++) { - String name = String.format("redis_%d", i + 1); - clients[i] = new Jedis(environment.getServiceHost(name, REDIS_PORT), environment.getServicePort(name, REDIS_PORT)); + clients[i] = + new Jedis(environment.getServiceHost(name, REDIS_PORT), environment.getServicePort(name, REDIS_PORT)); } } @Test public void simpleTest() { - for (int i = 0; i < 3; i++) { clients[i].incr("somekey"); diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerTest.java index 17a9b665513..c49663a4e35 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerTest.java @@ -9,10 +9,9 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.util.Collections; import java.util.Optional; -import static java.lang.String.format; -import static java.util.Collections.singletonList; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertNotNull; @@ -24,7 +23,9 @@ public class DockerComposeContainerTest extends BaseDockerComposeTest { @Rule - public DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/compose-test.yml")) + public DockerComposeContainer environment = new DockerComposeContainer( + new File("src/test/resources/compose-test.yml") + ) .withExposedService("redis_1", REDIS_PORT) .withExposedService("db_1", 3306); @@ -46,34 +47,46 @@ public void testGetServicePort() { public void shouldRetrieveContainerByServiceName() { String existingServiceName = "db_1"; Optional result = environment.getContainerByServiceName(existingServiceName); - assertTrue(format("Container should be found by service name %s", existingServiceName), result.isPresent()); - assertEquals("Mapped port for result container was wrong, probably wrong container found", result.get().getExposedPorts(), singletonList(3306)); + assertTrue( + String.format("Container should be found by service name %s", existingServiceName), + result.isPresent() + ); + assertEquals( + "Mapped port for result container was wrong, probably wrong container found", + result.get().getExposedPorts(), + Collections.singletonList(3306) + ); } @Test public void shouldReturnEmptyResultOnNoneExistingService() { String notExistingServiceName = "db_256"; Optional result = environment.getContainerByServiceName(notExistingServiceName); - assertFalse(format("No container should be found under service name %s", notExistingServiceName), result.isPresent()); + assertFalse( + String.format("No container should be found under service name %s", notExistingServiceName), + result.isPresent() + ); } @Test public void shouldCreateContainerWhenFileNotPrefixedWithPath() throws IOException { String validYaml = "version: '2.2'\n" + - "services:\n" + - " http:\n" + - " build: .\n" + - " image: python:latest\n" + - " ports:\n" + - " - 8080:8080"; + "services:\n" + + " http:\n" + + " build: .\n" + + " image: python:latest\n" + + " ports:\n" + + " - 8080:8080"; File filePathNotStartWithDotSlash = new File("docker-compose-test.yml"); filePathNotStartWithDotSlash.createNewFile(); filePathNotStartWithDotSlash.deleteOnExit(); Files.write(filePathNotStartWithDotSlash.toPath(), validYaml.getBytes(StandardCharsets.UTF_8)); - final DockerComposeContainer dockerComposeContainer = new DockerComposeContainer<>(filePathNotStartWithDotSlash); + final DockerComposeContainer dockerComposeContainer = new DockerComposeContainer<>( + filePathNotStartWithDotSlash + ); assertNotNull("Container could not be created using docker compose file", dockerComposeContainer); } } diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithBuildTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithBuildTest.java index 1b1efc878af..e0705a2c73b 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithBuildTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithBuildTest.java @@ -14,30 +14,32 @@ import java.util.stream.Stream; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.containers.DockerComposeContainer.RemoveImages.ALL; -import static org.testcontainers.containers.DockerComposeContainer.RemoveImages.LOCAL; @RunWith(Parameterized.class) public class DockerComposeContainerWithBuildTest { - public DockerComposeContainerWithBuildTest(final DockerComposeContainer.RemoveImages removeMode, - final boolean shouldBuiltImageBePresentAfterRunning, - final boolean shouldPulledImageBePresentAfterRunning) { + public DockerComposeContainerWithBuildTest( + final DockerComposeContainer.RemoveImages removeMode, + final boolean shouldBuiltImageBePresentAfterRunning, + final boolean shouldPulledImageBePresentAfterRunning + ) { this.removeMode = removeMode; this.shouldBuiltImageBePresentAfterRunning = shouldBuiltImageBePresentAfterRunning; this.shouldPulledImageBePresentAfterRunning = shouldPulledImageBePresentAfterRunning; } public final DockerComposeContainer.RemoveImages removeMode; + public final boolean shouldBuiltImageBePresentAfterRunning; + public final boolean shouldPulledImageBePresentAfterRunning; @Parameterized.Parameters(name = "removeMode = {0}") public static Object[][] params() { - return new Object[][]{ - {null, true, true}, - {LOCAL, false, true}, - {ALL, false, false}, + return new Object[][] { + { null, true, true }, + { DockerComposeContainer.RemoveImages.LOCAL, false, true }, + { DockerComposeContainer.RemoveImages.ALL, false, false }, }; } @@ -47,11 +49,12 @@ public void performTest() { final AtomicReference builtImageName = new AtomicReference<>(""); final AtomicReference pulledImageName = new AtomicReference<>(""); - try (DockerComposeContainer environment = new DockerComposeContainer<>(composeFile) - .withExposedService("customredis", 6379) - .withBuild(true) - .withRemoveImages(removeMode)) { - + try ( + DockerComposeContainer environment = new DockerComposeContainer<>(composeFile) + .withExposedService("customredis", 6379) + .withBuild(true) + .withRemoveImages(removeMode) + ) { environment.start(); builtImageName.set(imageNameForRunningContainer("_customredis_1")); @@ -63,21 +66,42 @@ public void performTest() { assertEquals("the pulled image is present while running", true, isPulledImagePresentWhileRunning); } - Unreliables.retryUntilSuccess(10, TimeUnit.SECONDS, () -> { - final boolean isBuiltImagePresentAfterRunning = isImagePresent(builtImageName.get()); - assertEquals("the built image is not present after running", shouldBuiltImageBePresentAfterRunning, isBuiltImagePresentAfterRunning); - return null; - }); - - Unreliables.retryUntilSuccess(10, TimeUnit.SECONDS, () -> { - final boolean isPulledImagePresentAfterRunning = isImagePresent(pulledImageName.get()); - assertEquals("the pulled image is present after running", shouldPulledImageBePresentAfterRunning, isPulledImagePresentAfterRunning); - return null; - }); + Unreliables.retryUntilSuccess( + 10, + TimeUnit.SECONDS, + () -> { + final boolean isBuiltImagePresentAfterRunning = isImagePresent(builtImageName.get()); + assertEquals( + "the built image is not present after running", + shouldBuiltImageBePresentAfterRunning, + isBuiltImagePresentAfterRunning + ); + return null; + } + ); + + Unreliables.retryUntilSuccess( + 10, + TimeUnit.SECONDS, + () -> { + final boolean isPulledImagePresentAfterRunning = isImagePresent(pulledImageName.get()); + assertEquals( + "the pulled image is present after running", + shouldPulledImageBePresentAfterRunning, + isPulledImagePresentAfterRunning + ); + return null; + } + ); } private String imageNameForRunningContainer(final String containerNameSuffix) { - return DockerClientFactory.instance().client().listContainersCmd().exec().stream() + return DockerClientFactory + .instance() + .client() + .listContainersCmd() + .exec() + .stream() .filter(it -> Stream.of(it.getNames()).anyMatch(name -> name.endsWith(containerNameSuffix))) .findFirst() .map(Container::getImage) @@ -85,7 +109,13 @@ private String imageNameForRunningContainer(final String containerNameSuffix) { } private boolean isImagePresent(final String imageName) { - return DockerClientFactory.instance().client().listImagesCmd().withImageNameFilter(imageName).exec().stream() + return DockerClientFactory + .instance() + .client() + .listImagesCmd() + .withImageNameFilter(imageName) + .exec() + .stream() .findFirst() .isPresent(); } diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java index 375c9baa070..77e60580b39 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java @@ -17,7 +17,12 @@ @RunWith(Parameterized.class) public class DockerComposeContainerWithOptionsTest { - public DockerComposeContainerWithOptionsTest(final File composeFile, final boolean local, final Set options, final boolean expectError) { + public DockerComposeContainerWithOptionsTest( + final File composeFile, + final boolean local, + final Set options, + final boolean expectError + ) { this.composeFile = composeFile; this.local = local; this.options = options; @@ -25,38 +30,60 @@ public DockerComposeContainerWithOptionsTest(final File composeFile, final boole } private final File composeFile; + private final boolean local; private final Set options; - private final boolean expectError; - @Parameterized.Parameters(name = "docker-compose test [compose file: {0}, local: {1}, options: {2}, expected result: {3}]") + private final boolean expectError; + @Parameterized.Parameters( + name = "docker-compose test [compose file: {0}, local: {1}, options: {2}, expected result: {3}]" + ) public static Object[][] params() { - return new Object[][]{ + return new Object[][] { // Test the happy day case. THe compatibility option should be accepted by docker-compose. - {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), false, ImmutableSet.of("--compatibility"), false}, + { + new File("src/test/resources/compose-options-test/with-deploy-block.yml"), + false, + ImmutableSet.of("--compatibility"), + false, + }, // Test with flags absent. Docker compose will warn but continue, ignoring the deploy block. - {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), false, ImmutableSet.of(""), false}, + { + new File("src/test/resources/compose-options-test/with-deploy-block.yml"), + false, + ImmutableSet.of(""), + false, + }, // Test with a bad option. Compose will complain. - {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), false, ImmutableSet.of("--bad-option"), true}, + { + new File("src/test/resources/compose-options-test/with-deploy-block.yml"), + false, + ImmutableSet.of("--bad-option"), + true, + }, // Local compose - {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), true, ImmutableSet.of("--compatibility"), false}, + { + new File("src/test/resources/compose-options-test/with-deploy-block.yml"), + true, + ImmutableSet.of("--compatibility"), + false, + }, }; } @Test public void performTest() { - - try (DockerComposeContainer environment = new DockerComposeContainer<>(composeFile) + try ( + DockerComposeContainer environment = new DockerComposeContainer<>(composeFile) .withOptions(options.stream().toArray(String[]::new)) - .withLocalCompose(local)) { + .withLocalCompose(local) + ) { environment.start(); assertThat(expectError).isEqualTo(false); } catch (Exception e) { assertThat(expectError).isEqualTo(true); } - } - } diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeErrorHandlingTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeErrorHandlingTest.java index b8e26ffd3f1..51f09bdb095 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeErrorHandlingTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeErrorHandlingTest.java @@ -10,11 +10,15 @@ public class DockerComposeErrorHandlingTest { @Test public void simpleTest() { - VisibleAssertions.assertThrows("starting with an invalid docker-compose file throws an exception", + VisibleAssertions.assertThrows( + "starting with an invalid docker-compose file throws an exception", IllegalArgumentException.class, - () -> { - DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/invalid-compose.yml")) - .withExposedService("something", 123); - }); + () -> { + DockerComposeContainer environment = new DockerComposeContainer( + new File("src/test/resources/invalid-compose.yml") + ) + .withExposedService("something", 123); + } + ); } } diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeLocalImageTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeLocalImageTest.java index 890fa34b0f8..dd2054e1e2e 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeLocalImageTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeLocalImageTest.java @@ -14,7 +14,9 @@ public class DockerComposeLocalImageTest { public void usesLocalImageEvenWhenPullFails() throws InterruptedException { tagImage("redis:4.0.10", "redis-local", "latest"); - DockerComposeContainer composeContainer = new DockerComposeContainer(new File("src/test/resources/local-compose-test.yml")) + DockerComposeContainer composeContainer = new DockerComposeContainer( + new File("src/test/resources/local-compose-test.yml") + ) .withExposedService("redis", 6379); composeContainer.start(); } diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeLogConsumerTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeLogConsumerTest.java index 6cd90d3cd9c..97e686a9b92 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeLogConsumerTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeLogConsumerTest.java @@ -3,26 +3,36 @@ import org.junit.Test; import org.junit.runner.Description; import org.testcontainers.containers.DockerComposeContainer; +import org.testcontainers.containers.output.OutputFrame.OutputType; import org.testcontainers.containers.output.WaitingConsumer; import java.io.File; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; - public class DockerComposeLogConsumerTest { @Test public void testLogConsumer() throws TimeoutException { WaitingConsumer logConsumer = new WaitingConsumer(); - DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/v2-compose-test.yml")) + DockerComposeContainer environment = new DockerComposeContainer( + new File("src/test/resources/v2-compose-test.yml") + ) .withExposedService("redis_1", 6379) .withLogConsumer("redis_1", logConsumer); try { environment.starting(Description.EMPTY); - logConsumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("Ready to accept connections"), 5, TimeUnit.SECONDS); + logConsumer.waitUntil( + frame -> { + return ( + frame.getType() == OutputType.STDOUT && + frame.getUtf8String().contains("Ready to accept connections") + ); + }, + 5, + TimeUnit.SECONDS + ); } finally { environment.finished(Description.EMPTY); } diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposePassthroughTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposePassthroughTest.java index cdeea00d201..c026bcaa741 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposePassthroughTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposePassthroughTest.java @@ -13,7 +13,7 @@ import java.util.Arrays; import java.util.Objects; -import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.Matchers.hasItem; import static org.rnorth.visibleassertions.VisibleAssertions.assertNotNull; import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; @@ -30,25 +30,27 @@ public static void checkVersion() { } @Rule - public DockerComposeContainer compose = - new DockerComposeContainer(new File("src/test/resources/v2-compose-test-passthrough.yml")) - .withEnv("foo", "bar") - .withExposedService("alpine_1", 3000, waitStrategy); - + public DockerComposeContainer compose = new DockerComposeContainer( + new File("src/test/resources/v2-compose-test-passthrough.yml") + ) + .withEnv("foo", "bar") + .withExposedService("alpine_1", 3000, waitStrategy); @Test public void testContainerInstanceProperties() { final ContainerState container = waitStrategy.getContainer(); //check environment variable was set - assertThat("Environment variable set correctly", Arrays.asList(Objects.requireNonNull(container.getContainerInfo() - .getConfig().getEnv())), hasItem("bar=bar")); + assertThat( + "Environment variable set correctly", + Arrays.asList(Objects.requireNonNull(container.getContainerInfo().getConfig().getEnv())), + hasItem("bar=bar") + ); //check other container properties assertNotNull("Container id is not null", container.getContainerId()); assertNotNull("Port mapped", container.getMappedPort(3000)); assertThat("Exposed Ports", container.getExposedPorts(), hasItem(3000)); - } /* diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeServiceTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeServiceTest.java index ec8c50d42ab..5e6ba4cc30f 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeServiceTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeServiceTest.java @@ -4,17 +4,18 @@ import org.junit.Test; import org.testcontainers.containers.DockerComposeContainer; -import static org.rnorth.visibleassertions.VisibleAssertions.assertNotNull; - import java.io.File; +import static org.rnorth.visibleassertions.VisibleAssertions.assertNotNull; + public class DockerComposeServiceTest extends BaseDockerComposeTest { @Rule - public DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/compose-test.yml")) - .withServices("redis") - .withExposedService("redis_1", REDIS_PORT); - + public DockerComposeContainer environment = new DockerComposeContainer( + new File("src/test/resources/compose-test.yml") + ) + .withServices("redis") + .withExposedService("redis_1", REDIS_PORT); @Override protected DockerComposeContainer getEnvironment() { diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeV2FormatTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeV2FormatTest.java index bed19bd0d09..f3dc2ee3cc8 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeV2FormatTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeV2FormatTest.java @@ -11,8 +11,10 @@ public class DockerComposeV2FormatTest extends BaseDockerComposeTest { @Rule - public DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/v2-compose-test.yml")) - .withExposedService("redis_1", REDIS_PORT); + public DockerComposeContainer environment = new DockerComposeContainer( + new File("src/test/resources/v2-compose-test.yml") + ) + .withExposedService("redis_1", REDIS_PORT); @Override protected DockerComposeContainer getEnvironment() { diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeV2WithNetworkTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeV2WithNetworkTest.java index 26764476687..b28dfc3ee51 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeV2WithNetworkTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeV2WithNetworkTest.java @@ -1,21 +1,20 @@ package org.testcontainers.junit; -import java.io.File; - import org.junit.Rule; import org.testcontainers.containers.DockerComposeContainer; +import java.io.File; + public class DockerComposeV2WithNetworkTest extends BaseDockerComposeTest { @Rule - public DockerComposeContainer environment = new DockerComposeContainer(new File("src/test/resources/v2-compose-test-with-network.yml")) - .withExposedService("redis_1", REDIS_PORT); + public DockerComposeContainer environment = new DockerComposeContainer( + new File("src/test/resources/v2-compose-test-with-network.yml") + ) + .withExposedService("redis_1", REDIS_PORT); @Override protected DockerComposeContainer getEnvironment() { return environment; } - - - } diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeWaitStrategyTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeWaitStrategyTest.java index 32465010700..a30c716964e 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerComposeWaitStrategyTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeWaitStrategyTest.java @@ -1,10 +1,5 @@ package org.testcontainers.junit; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - -import java.io.File; -import java.time.Duration; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -15,6 +10,12 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import java.io.File; +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + public class DockerComposeWaitStrategyTest { private static final int REDIS_PORT = 6379; @@ -23,8 +24,7 @@ public class DockerComposeWaitStrategyTest { @Before public final void setUp() { - environment = new DockerComposeContainer<>( - new File("src/test/resources/compose-test.yml")); + environment = new DockerComposeContainer<>(new File("src/test/resources/compose-test.yml")); } @After @@ -34,14 +34,15 @@ public final void cleanUp() { @Test public void testWaitOnListeningPort() { - environment - .withExposedService("redis_1", REDIS_PORT, Wait.forListeningPort()); + environment.withExposedService("redis_1", REDIS_PORT, Wait.forListeningPort()); try { environment.starting(Description.createTestDescription(Object.class, "name")); VisibleAssertions.pass("Docker compose should start after waiting for listening port"); } catch (RuntimeException e) { - VisibleAssertions.fail("Docker compose should start after waiting for listening port with failed with: " + e); + VisibleAssertions.fail( + "Docker compose should start after waiting for listening port with failed with: " + e + ); } } @@ -56,29 +57,45 @@ public void testWaitOnMultipleStrategiesPassing() { environment.starting(Description.createTestDescription(Object.class, "name")); VisibleAssertions.pass("Docker compose should start after waiting for listening port"); } catch (RuntimeException e) { - VisibleAssertions.fail("Docker compose should start after waiting for listening port with failed with: " + e); + VisibleAssertions.fail( + "Docker compose should start after waiting for listening port with failed with: " + e + ); } } @Test public void testWaitingFails() { - environment - .withExposedService("redis_1", REDIS_PORT, Wait.forHttp("/test").withStartupTimeout(Duration.ofSeconds(10))); - VisibleAssertions.assertThrows("waiting on an invalid http path times out", + environment.withExposedService( + "redis_1", + REDIS_PORT, + Wait.forHttp("/test").withStartupTimeout(Duration.ofSeconds(10)) + ); + VisibleAssertions.assertThrows( + "waiting on an invalid http path times out", RuntimeException.class, - () -> environment.starting(Description.createTestDescription(Object.class, "name"))); + () -> environment.starting(Description.createTestDescription(Object.class, "name")) + ); } @Test public void testWaitOnOneOfMultipleStrategiesFailing() { environment - .withExposedService("redis_1", REDIS_PORT, Wait.forListeningPort().withStartupTimeout(Duration.ofSeconds(10))) - .waitingFor("db_1", Wait.forLogMessage(".*test test test.*\\s", 1).withStartupTimeout(Duration.ofSeconds(10))) + .withExposedService( + "redis_1", + REDIS_PORT, + Wait.forListeningPort().withStartupTimeout(Duration.ofSeconds(10)) + ) + .waitingFor( + "db_1", + Wait.forLogMessage(".*test test test.*\\s", 1).withStartupTimeout(Duration.ofSeconds(10)) + ) .withTailChildContainers(true); - VisibleAssertions.assertThrows("waiting on one failing strategy to time out", + VisibleAssertions.assertThrows( + "waiting on one failing strategy to time out", RuntimeException.class, - () -> environment.starting(Description.createTestDescription(Object.class, "name"))); + () -> environment.starting(Description.createTestDescription(Object.class, "name")) + ); } @Test @@ -93,14 +110,11 @@ public void testWaitingForNonexistentServices() { .waitingFor(nonexistentServiceName1, someWaitStrategy) .waitingFor(nonexistentServiceName2, someWaitStrategy); - Throwable thrownWhenRequestedToWaitForNonexistentService = - catchThrowable(environment::start); + Throwable thrownWhenRequestedToWaitForNonexistentService = catchThrowable(environment::start); assertThat(thrownWhenRequestedToWaitForNonexistentService) .isInstanceOf(IllegalStateException.class) - .hasMessageContaining( - nonexistentServiceName1, - nonexistentServiceName2) + .hasMessageContaining(nonexistentServiceName1, nonexistentServiceName2) .hasMessageNotContaining(existentServiceName); } } diff --git a/core/src/test/java/org/testcontainers/junit/DockerNetworkModeTest.java b/core/src/test/java/org/testcontainers/junit/DockerNetworkModeTest.java index 59c2a63127c..7962b87e157 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerNetworkModeTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerNetworkModeTest.java @@ -3,12 +3,12 @@ import com.github.dockerjava.api.model.NetworkSettings; import lombok.extern.slf4j.Slf4j; import org.junit.Test; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.TINY_IMAGE; /** * Simple tests of named network modes - more may be possible, but may not be reproducible @@ -20,7 +20,7 @@ public class DockerNetworkModeTest { @Test public void testNoNetworkContainer() { try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .withCommand("true") .withNetworkMode("none") @@ -36,7 +36,7 @@ public void testNoNetworkContainer() { @Test public void testHostNetworkContainer() { try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .withCommand("true") .withNetworkMode("host") diff --git a/core/src/test/java/org/testcontainers/junit/DockerfileContainerTest.java b/core/src/test/java/org/testcontainers/junit/DockerfileContainerTest.java index 6ad7c3ea26e..715ba3f64a1 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerfileContainerTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerfileContainerTest.java @@ -21,13 +21,16 @@ public class DockerfileContainerTest { @Rule public GenericContainer dslContainer = new GenericContainer( - new ImageFromDockerfile("tcdockerfile/nginx", false).withDockerfileFromBuilder(builder -> { - builder - .from("alpine:3.2") - .run("apk add --update nginx") - .cmd("nginx", "-g", "daemon off;") - .build(); })) - .withExposedPorts(80); + new ImageFromDockerfile("tcdockerfile/nginx", false) + .withDockerfileFromBuilder(builder -> { + builder + .from("alpine:3.2") // + .run("apk add --update nginx") + .cmd("nginx", "-g", "daemon off;") + .build(); + }) + ) + .withExposedPorts(80); @Test public void simpleDslTest() throws IOException { @@ -37,11 +40,15 @@ public void simpleDslTest() throws IOException { HttpGet get = new HttpGet(address); try (CloseableHttpResponse response = httpClient.execute(get)) { - assertEquals("A container built from a dockerfile can run nginx as expected, and returns a good status code", - 200, - response.getStatusLine().getStatusCode()); - assertTrue("A container built from a dockerfile can run nginx as expected, and returns an expected Server header", - response.getHeaders("Server")[0].getValue().contains("nginx")); + assertEquals( + "A container built from a dockerfile can run nginx as expected, and returns a good status code", + 200, + response.getStatusLine().getStatusCode() + ); + assertTrue( + "A container built from a dockerfile can run nginx as expected, and returns an expected Server header", + response.getHeaders("Server")[0].getValue().contains("nginx") + ); } } } diff --git a/core/src/test/java/org/testcontainers/junit/DockerfileTest.java b/core/src/test/java/org/testcontainers/junit/DockerfileTest.java index 2197d7be0e7..e121e7db5a4 100644 --- a/core/src/test/java/org/testcontainers/junit/DockerfileTest.java +++ b/core/src/test/java/org/testcontainers/junit/DockerfileTest.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.OutputFrame; import org.testcontainers.containers.output.WaitingConsumer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.images.builder.ImageFromDockerfile; @@ -16,7 +17,6 @@ import java.util.concurrent.TimeoutException; import static org.rnorth.visibleassertions.VisibleAssertions.pass; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; public class DockerfileTest { @@ -25,9 +25,9 @@ public class DockerfileTest { @Test public void simpleDockerfileWorks() { ImageFromDockerfile image = new ImageFromDockerfile() - .withFileFromString("folder/someFile.txt", "hello") - .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt") - .withFileFromClasspath("Dockerfile", "mappable-dockerfile/Dockerfile"); + .withFileFromString("folder/someFile.txt", "hello") + .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt") + .withFileFromClasspath("Dockerfile", "mappable-dockerfile/Dockerfile"); verifyImage(image); } @@ -40,9 +40,9 @@ protected void configure(BuildImageCmd buildImageCmd) { super.configure(buildImageCmd); List dockerfile = Arrays.asList( - "FROM alpine:3.14", - "RUN echo 'hello from Docker build process'", - "CMD yes" + "FROM alpine:3.14", + "RUN echo 'hello from Docker build process'", + "CMD yes" ); withFileFromString("Dockerfile", String.join("\n", dockerfile)); @@ -56,28 +56,30 @@ protected void configure(BuildImageCmd buildImageCmd) { @Test public void dockerfileBuilderWorks() { ImageFromDockerfile image = new ImageFromDockerfile() - .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt") - .withFileFromString("folder/someFile.txt", "hello") - .withDockerfileFromBuilder(builder -> builder - .from("alpine:3.14") - .workDir("/app") - .add("test.txt", "test file.txt") - .run("ls", "-la", "/app/test file.txt") - .copy("folder/someFile.txt", "/someFile.txt") - .expose(80, 8080) - .cmd("while true; do cat /someFile.txt | nc -l -p 80; done") - ); + .withFileFromClasspath("test.txt", "mappable-resource/test-resource.txt") + .withFileFromString("folder/someFile.txt", "hello") + .withDockerfileFromBuilder(builder -> { + builder + .from("alpine:3.14") + .workDir("/app") + .add("test.txt", "test file.txt") + .run("ls", "-la", "/app/test file.txt") + .copy("folder/someFile.txt", "/someFile.txt") + .expose(80, 8080) + .cmd("while true; do cat /someFile.txt | nc -l -p 80; done"); + }); verifyImage(image); } @Test public void filePermissions() throws TimeoutException { - WaitingConsumer consumer = new WaitingConsumer(); ImageFromDockerfile image = new ImageFromDockerfile() - .withFileFromTransferable("/someFile.txt", new Transferable() { + .withFileFromTransferable( + "/someFile.txt", + new Transferable() { @Override public long getSize() { return 0; @@ -97,23 +99,27 @@ public String getDescription() { public int getFileMode() { return 0123; } - - - }) - .withDockerfileFromBuilder(builder -> builder - .from("alpine:3.14") - .copy("someFile.txt", "/someFile.txt") - .cmd("stat -c \"%a\" /someFile.txt") - ); + } + ) + .withDockerfileFromBuilder(builder -> { + builder + .from("alpine:3.14") // + .copy("someFile.txt", "/someFile.txt") + .cmd("stat -c \"%a\" /someFile.txt"); + }); GenericContainer container = new GenericContainer(image) - .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) - .withLogConsumer(consumer); + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) + .withLogConsumer(consumer); try { container.start(); - consumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("123"), 5, TimeUnit.SECONDS); + consumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("123"), + 5, + TimeUnit.SECONDS + ); } finally { container.stop(); } diff --git a/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java b/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java index beca4a8a49f..e61721f80c4 100644 --- a/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java +++ b/core/src/test/java/org/testcontainers/junit/FileOperationsTest.java @@ -7,6 +7,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.utility.MountableFile; @@ -16,7 +17,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.ALPINE_IMAGE; public class FileOperationsTest { @@ -26,7 +26,7 @@ public class FileOperationsTest { @Test public void copyFileToContainerFileTest() throws Exception { try ( - GenericContainer alpineCopyToContainer = new GenericContainer(ALPINE_IMAGE) + GenericContainer alpineCopyToContainer = new GenericContainer(TestImages.ALPINE_IMAGE) // .withCommand("top") ) { alpineCopyToContainer.start(); @@ -44,7 +44,7 @@ public void copyFileToContainerFileTest() throws Exception { @Test public void copyFileToContainerFolderTest() throws Exception { try ( - GenericContainer alpineCopyToContainer = new GenericContainer(ALPINE_IMAGE) + GenericContainer alpineCopyToContainer = new GenericContainer(TestImages.ALPINE_IMAGE) // .withCommand("top") ) { alpineCopyToContainer.start(); @@ -62,10 +62,9 @@ public void copyFileToContainerFolderTest() throws Exception { @Test public void copyFolderToContainerFolderTest() throws Exception { try ( - GenericContainer alpineCopyToContainer = new GenericContainer(ALPINE_IMAGE) + GenericContainer alpineCopyToContainer = new GenericContainer(TestImages.ALPINE_IMAGE) // .withCommand("top") ) { - alpineCopyToContainer.start(); final MountableFile mountableFile = MountableFile.forClasspathResource("mappable-resource/"); alpineCopyToContainer.copyFileToContainer(mountableFile, "/home/test/"); @@ -81,7 +80,7 @@ public void copyFolderToContainerFolderTest() throws Exception { @Test(expected = NotFoundException.class) public void copyFromContainerShouldFailBecauseNoFileTest() throws NotFoundException { try ( - GenericContainer alpineCopyToContainer = new GenericContainer(ALPINE_IMAGE) + GenericContainer alpineCopyToContainer = new GenericContainer(TestImages.ALPINE_IMAGE) // .withCommand("top") ) { alpineCopyToContainer.start(); @@ -92,10 +91,9 @@ public void copyFromContainerShouldFailBecauseNoFileTest() throws NotFoundExcept @Test public void shouldCopyFileFromContainerTest() throws IOException { try ( - GenericContainer alpineCopyToContainer = new GenericContainer(ALPINE_IMAGE) + GenericContainer alpineCopyToContainer = new GenericContainer(TestImages.ALPINE_IMAGE) // .withCommand("top") ) { - alpineCopyToContainer.start(); final MountableFile mountableFile = MountableFile.forClasspathResource("test_copy_to_container.txt"); alpineCopyToContainer.copyFileToContainer(mountableFile, "/home/"); @@ -110,7 +108,7 @@ public void shouldCopyFileFromContainerTest() throws IOException { @Test public void copyFileOperationsShouldFailWhenNotStartedTest() { - try (GenericContainer container = new GenericContainer<>(ALPINE_IMAGE).withCommand("top")) { + try (GenericContainer container = new GenericContainer<>(TestImages.ALPINE_IMAGE).withCommand("top")) { Assertions .assertThatThrownBy(() -> { MountableFile mountableFile = MountableFile.forClasspathResource("test_copy_to_container.txt"); @@ -121,10 +119,7 @@ public void copyFileOperationsShouldFailWhenNotStartedTest() { Assertions .assertThatThrownBy(() -> { - container.copyFileFromContainer( - "/home/test_copy_to_container.txt", - IOUtils::toByteArray - ); + container.copyFileFromContainer("/home/test_copy_to_container.txt", IOUtils::toByteArray); }) .isInstanceOf(IllegalStateException.class) .hasMessageContaining("can only be used when the Container is created"); @@ -134,18 +129,17 @@ public void copyFileOperationsShouldFailWhenNotStartedTest() { @Test public void shouldCopyFileFromExitedContainerTest() throws IOException { try ( - GenericContainer container = new GenericContainer<>(ALPINE_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.ALPINE_IMAGE) .withCommand("sh", "-c", "echo -n 'Hello!' > /home/file_in_container.txt") .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) ) { container.start(); - assertThat(container.getDockerClient().waitContainerCmd(container.getContainerId()).start().awaitStatusCode()) + assertThat( + container.getDockerClient().waitContainerCmd(container.getContainerId()).start().awaitStatusCode() + ) .isEqualTo(0); - container.copyFileFromContainer( - "/home/file_in_container.txt", - IOUtils::toByteArray - ); + container.copyFileFromContainer("/home/file_in_container.txt", IOUtils::toByteArray); container.copyFileToContainer( MountableFile.forClasspathResource("test_copy_to_container.txt"), diff --git a/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java b/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java index 02fad53fb1e..a6bb13d160c 100644 --- a/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java +++ b/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java @@ -3,6 +3,7 @@ import com.google.common.util.concurrent.Uninterruptibles; import org.junit.Test; import org.rnorth.ducttape.unreliables.Unreliables; +import org.testcontainers.TestImages; import org.testcontainers.containers.FixedHostPortGenericContainer; import org.testcontainers.containers.GenericContainer; @@ -12,9 +13,8 @@ import java.net.Socket; import java.util.concurrent.TimeUnit; -import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; -import static org.testcontainers.TestImages.TINY_IMAGE; +import static org.hamcrest.Matchers.equalTo; /** * Test of {@link FixedHostPortGenericContainer}. Note that this is not an example of typical use (usually, a container @@ -39,15 +39,18 @@ public class FixedHostPortContainerTest { /** * *nix pipe to fire test response on test port */ - private static final String HTTP_ECHO_CMD = - String.format("while true; do echo \"%s\" | nc -l -p %d; done", TEST_RESPONSE, TEST_PORT); + private static final String HTTP_ECHO_CMD = String.format( + "while true; do echo \"%s\" | nc -l -p %d; done", + TEST_RESPONSE, + TEST_PORT + ); @Test public void testFixedHostPortMapping() throws IOException { // first find a free port on the docker host that will work for testing final Integer unusedHostPort; try ( - final GenericContainer echoServer = new GenericContainer(TINY_IMAGE) + final GenericContainer echoServer = new GenericContainer(TestImages.TINY_IMAGE) .withExposedPorts(TEST_PORT) .withCommand("/bin/sh", "-c", HTTP_ECHO_CMD) ) { @@ -58,15 +61,18 @@ public void testFixedHostPortMapping() throws IOException { // now starting echo server container mapped to known-as-free host port try ( final GenericContainer echoServer = new FixedHostPortGenericContainer(TEST_IMAGE) - // using workaround for port bind+expose - .withFixedExposedPort(unusedHostPort, TEST_PORT) - .withExposedPorts(TEST_PORT) - .withCommand("/bin/sh", "-c", HTTP_ECHO_CMD) + // using workaround for port bind+expose + .withFixedExposedPort(unusedHostPort, TEST_PORT) + .withExposedPorts(TEST_PORT) + .withCommand("/bin/sh", "-c", HTTP_ECHO_CMD) ) { echoServer.start(); - assertThat("Port mapping does not seem to match given fixed port", - echoServer.getMappedPort(TEST_PORT), equalTo(unusedHostPort)); + assertThat( + "Port mapping does not seem to match given fixed port", + echoServer.getMappedPort(TEST_PORT), + equalTo(unusedHostPort) + ); final String content = this.readResponse(echoServer, unusedHostPort); assertThat("Returned echo from fixed port does not match expected", content, equalTo(TEST_RESPONSE)); @@ -83,7 +89,9 @@ public void testFixedHostPortMapping() throws IOException { */ private String readResponse(GenericContainer container, Integer port) throws IOException { try ( - final BufferedReader reader = Unreliables.retryUntilSuccess(10, TimeUnit.SECONDS, + final BufferedReader reader = Unreliables.retryUntilSuccess( + 10, + TimeUnit.SECONDS, () -> { Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); final Socket socket = new Socket(container.getHost(), port); diff --git a/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java b/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java index c13421029e0..8c696585902 100644 --- a/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java +++ b/core/src/test/java/org/testcontainers/junit/GenericContainerRuleTest.java @@ -21,8 +21,11 @@ import org.junit.Test; import org.rnorth.ducttape.RetryCountExceededException; import org.rnorth.ducttape.unreliables.Unreliables; +import org.testcontainers.TestImages; +import org.testcontainers.containers.BindMode; import org.testcontainers.containers.Container; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.SelinuxContext; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import org.testcontainers.utility.Base58; import org.testcontainers.utility.TestEnvironment; @@ -37,27 +40,19 @@ import java.net.Socket; import java.time.Duration; import java.util.Arrays; +import java.util.Collections; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static java.util.Collections.singletonMap; -import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.Matchers.equalTo; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; import static org.rnorth.visibleassertions.VisibleAssertions.assertThrows; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.ALPINE_IMAGE; -import static org.testcontainers.TestImages.MONGODB_IMAGE; -import static org.testcontainers.TestImages.RABBITMQ_IMAGE; -import static org.testcontainers.TestImages.REDIS_IMAGE; -import static org.testcontainers.TestImages.TINY_IMAGE; -import static org.testcontainers.containers.BindMode.READ_ONLY; -import static org.testcontainers.containers.BindMode.READ_WRITE; -import static org.testcontainers.containers.SelinuxContext.SHARED; /** * Tests for GenericContainerRules @@ -65,12 +60,16 @@ public class GenericContainerRuleTest { private static final int REDIS_PORT = 6379; + private static final String RABBIQMQ_TEST_EXCHANGE = "TestExchange"; + private static final String RABBITMQ_TEST_ROUTING_KEY = "TestRoutingKey"; + private static final String RABBITMQ_TEST_MESSAGE = "Hello world"; + private static final int RABBITMQ_PORT = 5672; - private static final int MONGO_PORT = 27017; + private static final int MONGO_PORT = 27017; /* * Test data setup @@ -86,77 +85,79 @@ public static void setupContent() throws FileNotFoundException { * Redis */ @ClassRule - public static GenericContainer redis = new GenericContainer<>(REDIS_IMAGE) - .withExposedPorts(REDIS_PORT); + public static GenericContainer redis = new GenericContainer<>(TestImages.REDIS_IMAGE) + .withExposedPorts(REDIS_PORT); /** * RabbitMQ */ @ClassRule - public static GenericContainer rabbitMq = new GenericContainer<>(RABBITMQ_IMAGE) - .withExposedPorts(RABBITMQ_PORT); + public static GenericContainer rabbitMq = new GenericContainer<>(TestImages.RABBITMQ_IMAGE) + .withExposedPorts(RABBITMQ_PORT); + /** * MongoDB */ @ClassRule - public static GenericContainer mongo = new GenericContainer<>(MONGODB_IMAGE) - .withExposedPorts(MONGO_PORT); + public static GenericContainer mongo = new GenericContainer<>(TestImages.MONGODB_IMAGE) + .withExposedPorts(MONGO_PORT); + /** * Pass an environment variable to the container, then run a shell script that exposes the variable in a quick and * dirty way for testing. */ @ClassRule - public static GenericContainer alpineEnvVar = new GenericContainer<>(ALPINE_IMAGE) - .withExposedPorts(80) - .withEnv("MAGIC_NUMBER", "4") - .withEnv("MAGIC_NUMBER", oldValue -> oldValue.orElse("") + "2") - .withCommand("/bin/sh", "-c", "while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"); + public static GenericContainer alpineEnvVar = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withExposedPorts(80) + .withEnv("MAGIC_NUMBER", "4") + .withEnv("MAGIC_NUMBER", oldValue -> oldValue.orElse("") + "2") + .withCommand("/bin/sh", "-c", "while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"); /** * Pass environment variables to the container, then run a shell script that exposes the variables in a quick and * dirty way for testing. */ @ClassRule - public static GenericContainer alpineEnvVarFromMap = new GenericContainer<>(ALPINE_IMAGE) - .withExposedPorts(80) - .withEnv(ImmutableMap.of( - "FIRST", "42", - "SECOND", "50" - )) - .withCommand("/bin/sh", "-c", "while true; do echo \"$FIRST and $SECOND\" | nc -l -p 80; done"); + public static GenericContainer alpineEnvVarFromMap = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withExposedPorts(80) + .withEnv(ImmutableMap.of("FIRST", "42", "SECOND", "50")) + .withCommand("/bin/sh", "-c", "while true; do echo \"$FIRST and $SECOND\" | nc -l -p 80; done"); /** * Map a file on the classpath to a file in the container, and then expose the content for testing. */ @ClassRule - public static GenericContainer alpineClasspathResource = new GenericContainer<>(ALPINE_IMAGE) - .withExposedPorts(80) - .withClasspathResourceMapping("mappable-resource/test-resource.txt", "/content.txt", READ_ONLY) - .withCommand("/bin/sh", "-c", "while true; do cat /content.txt | nc -l -p 80; done"); + public static GenericContainer alpineClasspathResource = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withExposedPorts(80) + .withClasspathResourceMapping("mappable-resource/test-resource.txt", "/content.txt", BindMode.READ_ONLY) + .withCommand("/bin/sh", "-c", "while true; do cat /content.txt | nc -l -p 80; done"); /** * Map a file on the classpath to a file in the container, and then expose the content for testing. */ @ClassRule - public static GenericContainer alpineClasspathResourceSelinux = new GenericContainer<>(ALPINE_IMAGE) - .withExposedPorts(80) - .withClasspathResourceMapping("mappable-resource/test-resource.txt", "/content.txt", READ_WRITE, SHARED) - .withCommand("/bin/sh", "-c", "while true; do cat /content.txt | nc -l -p 80; done"); + public static GenericContainer alpineClasspathResourceSelinux = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withExposedPorts(80) + .withClasspathResourceMapping( + "mappable-resource/test-resource.txt", + "/content.txt", + BindMode.READ_WRITE, + SelinuxContext.SHARED + ) + .withCommand("/bin/sh", "-c", "while true; do cat /content.txt | nc -l -p 80; done"); /** * Create a container with an extra host entry and expose the content of /etc/hosts for testing. */ @ClassRule - public static GenericContainer alpineExtrahost = new GenericContainer<>(ALPINE_IMAGE) - .withExposedPorts(80) - .withExtraHost("somehost", "192.168.1.10") - .withCommand("/bin/sh", "-c", "while true; do cat /etc/hosts | nc -l -p 80; done"); + public static GenericContainer alpineExtrahost = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withExposedPorts(80) + .withExtraHost("somehost", "192.168.1.10") + .withCommand("/bin/sh", "-c", "while true; do cat /etc/hosts | nc -l -p 80; done"); @Test public void testIsRunning() { - try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) - .withCommand("top")) { + try (GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE).withCommand("top")) { assertFalse("Container is not started and not running", container.isRunning()); container.start(); assertTrue("Container is started and running", container.isRunning()); @@ -166,16 +167,19 @@ public void testIsRunning() { @Test public void withTmpFsTest() throws Exception { try ( - GenericContainer container = new GenericContainer<>(TINY_IMAGE) + GenericContainer container = new GenericContainer<>(TestImages.TINY_IMAGE) .withCommand("top") - .withTmpFs(singletonMap("/testtmpfs", "rw")) + .withTmpFs(Collections.singletonMap("/testtmpfs", "rw")) ) { container.start(); // check file doesn't exist String path = "/testtmpfs/test.file"; Container.ExecResult execResult = container.execInContainer("ls", path); - assertEquals("tmpfs inside container works fine", execResult.getStderr(), - "ls: /testtmpfs/test.file: No such file or directory\n"); + assertEquals( + "tmpfs inside container works fine", + execResult.getStderr(), + "ls: /testtmpfs/test.file: No such file or directory\n" + ); // touch && check file does exist container.execInContainer("touch", path); execResult = container.execInContainer("ls", path); @@ -183,7 +187,6 @@ public void withTmpFsTest() throws Exception { } } - @Test public void simpleRabbitMqTest() throws IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); @@ -198,23 +201,39 @@ public void simpleRabbitMqTest() throws IOException, TimeoutException { // Set up a consumer on the queue final boolean[] messageWasReceived = new boolean[1]; - channel.basicConsume(queueName, false, new DefaultConsumer(channel) { - @Override - public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { - messageWasReceived[0] = Arrays.equals(body, RABBITMQ_TEST_MESSAGE.getBytes()); + channel.basicConsume( + queueName, + false, + new DefaultConsumer(channel) { + @Override + public void handleDelivery( + String consumerTag, + Envelope envelope, + AMQP.BasicProperties properties, + byte[] body + ) throws IOException { + messageWasReceived[0] = Arrays.equals(body, RABBITMQ_TEST_MESSAGE.getBytes()); + } } - }); + ); // post a message channel.basicPublish(RABBIQMQ_TEST_EXCHANGE, RABBITMQ_TEST_ROUTING_KEY, null, RABBITMQ_TEST_MESSAGE.getBytes()); // check the message was received - assertTrue("The message was received", Unreliables.retryUntilSuccess(5, TimeUnit.SECONDS, () -> { - if (!messageWasReceived[0]) { - throw new IllegalStateException("Message not received yet"); - } - return true; - })); + assertTrue( + "The message was received", + Unreliables.retryUntilSuccess( + 5, + TimeUnit.SECONDS, + () -> { + if (!messageWasReceived[0]) { + throw new IllegalStateException("Message not received yet"); + } + return true; + } + ) + ); } @Test @@ -223,8 +242,7 @@ public void simpleMongoDbTest() { MongoDatabase database = mongoClient.getDatabase("test"); MongoCollection collection = database.getCollection("testCollection"); - Document doc = new Document("name", "foo") - .append("value", 1); + Document doc = new Document("name", "foo").append("value", 1); collection.insertOne(doc); Document doc2 = collection.find(new Document("name", "foo")).first(); @@ -247,10 +265,11 @@ public void environmentFromMapTest() throws IOException { @Test public void customLabelTest() { - try (final GenericContainer alpineCustomLabel = new GenericContainer<>(ALPINE_IMAGE) - .withLabel("our.custom", "label") - .withCommand("top")) { - + try ( + final GenericContainer alpineCustomLabel = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withLabel("our.custom", "label") + .withCommand("top") + ) { alpineCustomLabel.start(); Map labels = alpineCustomLabel.getCurrentContainerInfo().getConfig().getLabels(); @@ -262,11 +281,11 @@ public void customLabelTest() { @Test public void exceptionThrownWhenTryingToOverrideTestcontainersLabels() { - assertThrows("When trying to overwrite an 'org.testcontainers' label, withLabel() throws an exception", + assertThrows( + "When trying to overwrite an 'org.testcontainers' label, withLabel() throws an exception", IllegalArgumentException.class, () -> { - new GenericContainer<>(ALPINE_IMAGE) - .withLabel("org.testcontainers.foo", "false"); + new GenericContainer<>(TestImages.ALPINE_IMAGE).withLabel("org.testcontainers.foo", "false"); } ); } @@ -277,25 +296,36 @@ public void customClasspathResourceMappingTest() throws IOException { // in that case this test will fail. String line = getReaderForContainerPort80(alpineClasspathResource).readLine(); - assertEquals("Resource on the classpath can be mapped using calls to withClasspathResourceMapping", "FOOBAR", line); + assertEquals( + "Resource on the classpath can be mapped using calls to withClasspathResourceMapping", + "FOOBAR", + line + ); } @Test public void customClasspathResourceMappingWithSelinuxTest() throws IOException { String line = getReaderForContainerPort80(alpineClasspathResourceSelinux).readLine(); - assertEquals("Resource on the classpath can be mapped using calls to withClasspathResourceMappingSelinux", "FOOBAR", line); + assertEquals( + "Resource on the classpath can be mapped using calls to withClasspathResourceMappingSelinux", + "FOOBAR", + line + ); } @Test public void exceptionThrownWhenMappedPortNotFound() { - assertThrows("When the requested port is not mapped, getMappedPort() throws an exception", - IllegalArgumentException.class, - () -> { - return redis.getMappedPort(666); - }); + assertThrows( + "When the requested port is not mapped, getMappedPort() throws an exception", + IllegalArgumentException.class, + () -> { + return redis.getMappedPort(666); + } + ); } - protected static void writeStringToFile(File contentFolder, String filename, String string) throws FileNotFoundException { + protected static void writeStringToFile(File contentFolder, String filename, String string) + throws FileNotFoundException { File file = new File(contentFolder, filename); PrintStream printStream = new PrintStream(new FileOutputStream(file)); @@ -303,32 +333,34 @@ protected static void writeStringToFile(File contentFolder, String filename, Str printStream.close(); } - @Test @Ignore //TODO investigate intermittent failures + @Test + @Ignore //TODO investigate intermittent failures public void failFastWhenContainerHaltsImmediately() { - long startingTimeMs = System.currentTimeMillis(); - final GenericContainer failsImmediately = new GenericContainer<>(ALPINE_IMAGE) - .withCommand("/bin/sh", "-c", "return false") - .withMinimumRunningDuration(Duration.ofMillis(100)); + final GenericContainer failsImmediately = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withCommand("/bin/sh", "-c", "return false") + .withMinimumRunningDuration(Duration.ofMillis(100)); try { assertThrows( - "When we start a container that halts immediately, an exception is thrown", - RetryCountExceededException.class, - () -> { - failsImmediately.start(); - return null; - }); + "When we start a container that halts immediately, an exception is thrown", + RetryCountExceededException.class, + () -> { + failsImmediately.start(); + return null; + } + ); // Check how long it took, to verify that we ARE bailing out early. // Want to strike a balance here; too short and this test will fail intermittently // on slow systems and/or due to GC variation, too long and we won't properly test // what we're intending to test. - int allowedSecondsToFailure = - GenericContainer.CONTAINER_RUNNING_TIMEOUT_SEC / 2; + int allowedSecondsToFailure = GenericContainer.CONTAINER_RUNNING_TIMEOUT_SEC / 2; long completedTimeMs = System.currentTimeMillis(); - assertTrue("container should not take long to start up", - completedTimeMs - startingTimeMs < 1000L * allowedSecondsToFailure); + assertTrue( + "container should not take long to start up", + completedTimeMs - startingTimeMs < 1000L * allowedSecondsToFailure + ); } finally { failsImmediately.stop(); } @@ -336,19 +368,20 @@ public void failFastWhenContainerHaltsImmediately() { @Test public void testExecInContainer() throws Exception { - // The older "lxc" execution driver doesn't support "exec". At the time of writing (2016/03/29), // that's the case for CircleCI. // Once they resolve the issue, this clause can be removed. Assume.assumeTrue(TestEnvironment.dockerExecutionDriverSupportsExec()); final GenericContainer.ExecResult result = redis.execInContainer("redis-cli", "role"); - assertTrue("Output for \"redis-cli role\" command should start with \"master\"", result.getStdout().startsWith("master")); + assertTrue( + "Output for \"redis-cli role\" command should start with \"master\"", + result.getStdout().startsWith("master") + ); assertEquals("Stderr for \"redis-cli role\" command should be empty", "", result.getStderr()); // We expect to reach this point for modern Docker versions. } - @Test public void extraHostTest() throws IOException { BufferedReader br = getReaderForContainerPort80(alpineExtrahost); @@ -370,30 +403,37 @@ public void extraHostTest() throws IOException { public void createContainerCmdHookTest() { // Use random name to avoid the conflicts between the tests String randomName = Base58.randomString(5); - try( - GenericContainer container = new GenericContainer<>(REDIS_IMAGE) - .withCommand("redis-server", "--help") - .withCreateContainerCmdModifier(cmd -> cmd.withName("overrideMe")) - // Preserves the order - .withCreateContainerCmdModifier(cmd -> cmd.withName(randomName)) - // Allows to override pre-configured values by GenericContainer - .withCreateContainerCmdModifier(cmd -> cmd.withCmd("redis-server", "--port", "6379")) + try ( + GenericContainer container = new GenericContainer<>(TestImages.REDIS_IMAGE) + .withCommand("redis-server", "--help") + .withCreateContainerCmdModifier(cmd -> cmd.withName("overrideMe")) + // Preserves the order + .withCreateContainerCmdModifier(cmd -> cmd.withName(randomName)) + // Allows to override pre-configured values by GenericContainer + .withCreateContainerCmdModifier(cmd -> cmd.withCmd("redis-server", "--port", "6379")) ) { container.start(); assertEquals("Name is configured", "/" + randomName, container.getContainerInfo().getName()); - assertEquals("Command is configured", "[redis-server, --port, 6379]", Arrays.toString(container.getContainerInfo().getConfig().getCmd())); + assertEquals( + "Command is configured", + "[redis-server, --port, 6379]", + Arrays.toString(container.getContainerInfo().getConfig().getCmd()) + ); } } private BufferedReader getReaderForContainerPort80(GenericContainer container) { + return Unreliables.retryUntilSuccess( + 10, + TimeUnit.SECONDS, + () -> { + Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - return Unreliables.retryUntilSuccess(10, TimeUnit.SECONDS, () -> { - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - - Socket socket = new Socket(container.getHost(), container.getFirstMappedPort()); - return new BufferedReader(new InputStreamReader(socket.getInputStream())); - }); + Socket socket = new Socket(container.getHost(), container.getFirstMappedPort()); + return new BufferedReader(new InputStreamReader(socket.getInputStream())); + } + ); } @Test @@ -415,10 +455,11 @@ public void addingExposedPortTwiceShouldNotFail() { @Test public void sharedMemorySetTest() { - try (GenericContainer containerWithSharedMemory = new GenericContainer<>(TINY_IMAGE) - .withSharedMemorySize(42L * FileUtils.ONE_MB) - .withStartupCheckStrategy(new OneShotStartupCheckStrategy())) { - + try ( + GenericContainer containerWithSharedMemory = new GenericContainer<>(TestImages.TINY_IMAGE) + .withSharedMemorySize(42L * FileUtils.ONE_MB) + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) + ) { containerWithSharedMemory.start(); HostConfig hostConfig = containerWithSharedMemory.getContainerInfo().getHostConfig(); diff --git a/core/src/test/java/org/testcontainers/junit/NonExistentImagePullTest.java b/core/src/test/java/org/testcontainers/junit/NonExistentImagePullTest.java index 95047779551..33909e2ed27 100644 --- a/core/src/test/java/org/testcontainers/junit/NonExistentImagePullTest.java +++ b/core/src/test/java/org/testcontainers/junit/NonExistentImagePullTest.java @@ -14,10 +14,12 @@ public class NonExistentImagePullTest { @Test(timeout = 60_000L) public void pullingNonExistentImageFailsGracefully() { - - assertThrows("Pulling a nonexistent container will cause an exception to be thrown", - ContainerFetchException.class, () -> { - new GenericContainer<>(DockerImageName.parse("testcontainers/nonexistent:latest")).getDockerImageName(); - }); + assertThrows( + "Pulling a nonexistent container will cause an exception to be thrown", + ContainerFetchException.class, + () -> { + new GenericContainer<>(DockerImageName.parse("testcontainers/nonexistent:latest")).getDockerImageName(); + } + ); } } diff --git a/core/src/test/java/org/testcontainers/junit/OutputStreamTest.java b/core/src/test/java/org/testcontainers/junit/OutputStreamTest.java index 649a0b56fc4..104fb78fe48 100644 --- a/core/src/test/java/org/testcontainers/junit/OutputStreamTest.java +++ b/core/src/test/java/org/testcontainers/junit/OutputStreamTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.OutputFrame; import org.testcontainers.containers.output.Slf4jLogConsumer; @@ -17,8 +18,6 @@ import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertThrows; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.ALPINE_IMAGE; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; /** * Simple test for following container output. @@ -26,61 +25,74 @@ public class OutputStreamTest { @Rule - public GenericContainer container = new GenericContainer(ALPINE_IMAGE) - .withCommand("ping -c 5 127.0.0.1"); + public GenericContainer container = new GenericContainer(TestImages.ALPINE_IMAGE) + .withCommand("ping -c 5 127.0.0.1"); private static final Logger LOGGER = LoggerFactory.getLogger(OutputStreamTest.class); @Test(timeout = 60_000L) public void testFetchStdout() throws TimeoutException { - WaitingConsumer consumer = new WaitingConsumer(); - container.followOutput(consumer, STDOUT); + container.followOutput(consumer, OutputFrame.OutputType.STDOUT); - consumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("seq=2"), - 30, TimeUnit.SECONDS); + consumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("seq=2"), + 30, + TimeUnit.SECONDS + ); } @Test(timeout = 60_000L) public void testFetchStdoutWithTimeout() { - WaitingConsumer consumer = new WaitingConsumer(); - container.followOutput(consumer, STDOUT); - - assertThrows("a TimeoutException should be thrown", TimeoutException.class, () -> { - consumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("seq=5"), - 2, TimeUnit.SECONDS); - return true; - }); + container.followOutput(consumer, OutputFrame.OutputType.STDOUT); + + assertThrows( + "a TimeoutException should be thrown", + TimeoutException.class, + () -> { + consumer.waitUntil( + frame -> { + return ( + frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("seq=5") + ); + }, + 2, + TimeUnit.SECONDS + ); + return true; + } + ); } @Test(timeout = 60_000L) public void testFetchStdoutWithNoLimit() throws TimeoutException { - WaitingConsumer consumer = new WaitingConsumer(); - container.followOutput(consumer, STDOUT); + container.followOutput(consumer, OutputFrame.OutputType.STDOUT); - consumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("seq=2")); + consumer.waitUntil(frame -> { + return frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("seq=2"); + }); } @Test(timeout = 60_000L) public void testLogConsumer() throws TimeoutException { - WaitingConsumer waitingConsumer = new WaitingConsumer(); Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER); Consumer composedConsumer = logConsumer.andThen(waitingConsumer); container.followOutput(composedConsumer); - waitingConsumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("seq=2")); + waitingConsumer.waitUntil(frame -> { + return frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("seq=2"); + }); } @Test(timeout = 60_000L) public void testToStringConsumer() throws TimeoutException { - WaitingConsumer waitingConsumer = new WaitingConsumer(); ToStringConsumer toStringConsumer = new ToStringConsumer(); @@ -95,4 +107,3 @@ public void testToStringConsumer() throws TimeoutException { assertFalse("a non-expected value was found", utf8String.contains("seq=42")); } } - diff --git a/core/src/test/java/org/testcontainers/junit/OutputStreamWithTTYTest.java b/core/src/test/java/org/testcontainers/junit/OutputStreamWithTTYTest.java index b15f63f4158..a87dbef3990 100644 --- a/core/src/test/java/org/testcontainers/junit/OutputStreamWithTTYTest.java +++ b/core/src/test/java/org/testcontainers/junit/OutputStreamWithTTYTest.java @@ -4,6 +4,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.OutputFrame; import org.testcontainers.containers.output.Slf4jLogConsumer; @@ -18,14 +19,12 @@ import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertThrows; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.ALPINE_IMAGE; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; @Slf4j public class OutputStreamWithTTYTest { @Rule - public GenericContainer container = new GenericContainer<>(ALPINE_IMAGE) + public GenericContainer container = new GenericContainer<>(TestImages.ALPINE_IMAGE) .withCommand("ls -1") .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) .withCreateContainerCmdModifier(command -> command.withTty(true)); @@ -37,30 +36,44 @@ public class OutputStreamWithTTYTest { public void testFetchStdout() throws TimeoutException { WaitingConsumer consumer = new WaitingConsumer(); - container.followOutput(consumer, STDOUT); + container.followOutput(consumer, OutputFrame.OutputType.STDOUT); - consumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("home"), 4, TimeUnit.SECONDS); + consumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("home"), + 4, + TimeUnit.SECONDS + ); } @Test public void testFetchStdoutWithTimeout() { WaitingConsumer consumer = new WaitingConsumer(); - container.followOutput(consumer, STDOUT); - - assertThrows("a TimeoutException should be thrown", TimeoutException.class, () -> { - consumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("qqq"), 1, TimeUnit.SECONDS); - return true; - }); + container.followOutput(consumer, OutputFrame.OutputType.STDOUT); + + assertThrows( + "a TimeoutException should be thrown", + TimeoutException.class, + () -> { + consumer.waitUntil( + frame -> frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("qqq"), + 1, + TimeUnit.SECONDS + ); + return true; + } + ); } @Test public void testFetchStdoutWithNoLimit() throws TimeoutException { WaitingConsumer consumer = new WaitingConsumer(); - container.followOutput(consumer, STDOUT); + container.followOutput(consumer, OutputFrame.OutputType.STDOUT); - consumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("home")); + consumer.waitUntil(frame -> { + return frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("home"); + }); } @Test @@ -71,7 +84,9 @@ public void testLogConsumer() throws TimeoutException { Consumer composedConsumer = logConsumer.andThen(waitingConsumer); container.followOutput(composedConsumer); - waitingConsumer.waitUntil(frame -> frame.getType() == STDOUT && frame.getUtf8String().contains("home")); + waitingConsumer.waitUntil(frame -> { + return frame.getType() == OutputFrame.OutputType.STDOUT && frame.getUtf8String().contains("home"); + }); } @Test diff --git a/core/src/test/java/org/testcontainers/junit/ParameterizedDockerfileContainerTest.java b/core/src/test/java/org/testcontainers/junit/ParameterizedDockerfileContainerTest.java index 969d2836b2e..62eccc2000c 100644 --- a/core/src/test/java/org/testcontainers/junit/ParameterizedDockerfileContainerTest.java +++ b/core/src/test/java/org/testcontainers/junit/ParameterizedDockerfileContainerTest.java @@ -22,22 +22,27 @@ public class ParameterizedDockerfileContainerTest { public GenericContainer container; public ParameterizedDockerfileContainerTest(String baseImage, String expectedVersion) { - container = new GenericContainer(new ImageFromDockerfile().withDockerfileFromBuilder(builder -> { - builder - .from(baseImage) - // Could potentially customise the image here, e.g. adding files, running - // commands, etc. - .build(); - })).withCommand("top"); + container = + new GenericContainer( + new ImageFromDockerfile() + .withDockerfileFromBuilder(builder -> { + builder + .from(baseImage) + // Could potentially customise the image here, e.g. adding files, running + // commands, etc. + .build(); + }) + ) + .withCommand("top"); this.expectedVersion = expectedVersion; } @Parameterized.Parameters(name = "{0}") public static Object[][] data() { - return new Object[][] { - { "alpine:3.12", "3.12"}, - { "alpine:3.13", "3.13"}, - { "alpine:3.14", "3.14"} + return new Object[][] { // + { "alpine:3.12", "3.12" }, + { "alpine:3.13", "3.13" }, + { "alpine:3.14", "3.14" }, }; } @@ -45,7 +50,6 @@ public static Object[][] data() { public void simpleTest() throws Exception { final String release = container.execInContainer("cat", "/etc/alpine-release").getStdout(); - assertTrue("/etc/alpine-release starts with " + expectedVersion, - release.startsWith(expectedVersion)); + assertTrue("/etc/alpine-release starts with " + expectedVersion, release.startsWith(expectedVersion)); } } diff --git a/core/src/test/java/org/testcontainers/junit/WorkingDirectoryTest.java b/core/src/test/java/org/testcontainers/junit/WorkingDirectoryTest.java index b23ddf2ca1c..0be4022c171 100644 --- a/core/src/test/java/org/testcontainers/junit/WorkingDirectoryTest.java +++ b/core/src/test/java/org/testcontainers/junit/WorkingDirectoryTest.java @@ -2,11 +2,11 @@ import org.junit.ClassRule; import org.junit.Test; +import org.testcontainers.TestImages; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.TestImages.ALPINE_IMAGE; /** * Created by rnorth on 26/07/2016. @@ -14,10 +14,10 @@ public class WorkingDirectoryTest { @ClassRule - public static GenericContainer container = new GenericContainer(ALPINE_IMAGE) - .withWorkingDirectory("/etc") - .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) - .withCommand("ls", "-al"); + public static GenericContainer container = new GenericContainer(TestImages.ALPINE_IMAGE) + .withWorkingDirectory("/etc") + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()) + .withCommand("ls", "-al"); @Test public void checkOutput() { @@ -27,5 +27,4 @@ public void checkOutput() { assertTrue("Directory listing contains expected /etc content", listing.contains("init.d")); assertTrue("Directory listing contains expected /etc content", listing.contains("passwd")); } - } diff --git a/core/src/test/java/org/testcontainers/junit/wait/strategy/AbstractWaitStrategyTest.java b/core/src/test/java/org/testcontainers/junit/wait/strategy/AbstractWaitStrategyTest.java index 480536a54ef..de16eb0e582 100644 --- a/core/src/test/java/org/testcontainers/junit/wait/strategy/AbstractWaitStrategyTest.java +++ b/core/src/test/java/org/testcontainers/junit/wait/strategy/AbstractWaitStrategyTest.java @@ -20,6 +20,7 @@ * @author Pete Cornish {@literal } */ public abstract class AbstractWaitStrategyTest { + static final long WAIT_TIMEOUT_MILLIS = 3000; /** @@ -65,12 +66,16 @@ protected GenericContainer startContainerWithCommand(String shellCommand, Wai return startContainerWithCommand(shellCommand, waitStrategy, 8080); } - protected GenericContainer startContainerWithCommand(String shellCommand, WaitStrategy waitStrategy, Integer... ports) { + protected GenericContainer startContainerWithCommand( + String shellCommand, + WaitStrategy waitStrategy, + Integer... ports + ) { // apply WaitStrategy to container return new GenericContainer<>(TestImages.ALPINE_IMAGE) - .withExposedPorts(ports) - .withCommand("sh", "-c", shellCommand) - .waitingFor(waitStrategy.withStartupTimeout(Duration.ofMillis(WAIT_TIMEOUT_MILLIS))); + .withExposedPorts(ports) + .withCommand("sh", "-c", shellCommand) + .waitingFor(waitStrategy.withStartupTimeout(Duration.ofMillis(WAIT_TIMEOUT_MILLIS))); } /** @@ -100,10 +105,11 @@ protected void waitUntilReadyAndTimeout(String shellCommand) { */ protected void waitUntilReadyAndTimeout(GenericContainer container) { // start() blocks until successful or timeout - VisibleAssertions.assertThrows("an exception is thrown when timeout occurs (" + WAIT_TIMEOUT_MILLIS + "ms)", - ContainerLaunchException.class, - container::start); - + VisibleAssertions.assertThrows( + "an exception is thrown when timeout occurs (" + WAIT_TIMEOUT_MILLIS + "ms)", + ContainerLaunchException.class, + container::start + ); } /** @@ -115,7 +121,9 @@ protected void waitUntilReadyAndSucceed(GenericContainer container) { // start() blocks until successful or timeout container.start(); - assertTrue(String.format("Expected container to be ready after timeout of %sms", - WAIT_TIMEOUT_MILLIS), ready.get()); + assertTrue( + String.format("Expected container to be ready after timeout of %sms", WAIT_TIMEOUT_MILLIS), + ready.get() + ); } } diff --git a/core/src/test/java/org/testcontainers/junit/wait/strategy/HostPortWaitStrategyTest.java b/core/src/test/java/org/testcontainers/junit/wait/strategy/HostPortWaitStrategyTest.java index 5c7d37a7da3..4b5f43a4d4b 100644 --- a/core/src/test/java/org/testcontainers/junit/wait/strategy/HostPortWaitStrategyTest.java +++ b/core/src/test/java/org/testcontainers/junit/wait/strategy/HostPortWaitStrategyTest.java @@ -17,7 +17,8 @@ public class HostPortWaitStrategyTest { @ClassRule - public static GenericContainer container = new GenericContainer<>(TestImages.ALPINE_IMAGE).withExposedPorts() + public static GenericContainer container = new GenericContainer<>(TestImages.ALPINE_IMAGE) + .withExposedPorts() .withCommand("sh", "-c", "while true; do nc -lp 8080; done") .withExposedPorts(8080) .waitingFor(Wait.forListeningPort().withStartupTimeout(Duration.ofSeconds(10))); diff --git a/core/src/test/java/org/testcontainers/junit/wait/strategy/HttpWaitStrategyTest.java b/core/src/test/java/org/testcontainers/junit/wait/strategy/HttpWaitStrategyTest.java index 82207b4537e..7014749115e 100644 --- a/core/src/test/java/org/testcontainers/junit/wait/strategy/HttpWaitStrategyTest.java +++ b/core/src/test/java/org/testcontainers/junit/wait/strategy/HttpWaitStrategyTest.java @@ -1,9 +1,5 @@ package org.testcontainers.junit.wait.strategy; -import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertThat; - -import java.util.HashMap; import org.jetbrains.annotations.NotNull; import org.junit.Test; import org.rnorth.ducttape.RetryCountExceededException; @@ -11,15 +7,20 @@ import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import java.time.Duration; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; + /** * Tests for {@link HttpWaitStrategy}. * * @author Pete Cornish {@literal } */ public class HttpWaitStrategyTest extends AbstractWaitStrategyTest { + /** * newline sequence indicating end of the HTTP header. */ @@ -44,10 +45,9 @@ public void testWaitUntilReadyWithSuccess() { public void testWaitUntilReadyWithSuccessWithCustomHeaders() { HashMap headers = new HashMap<>(); headers.put("baz", "boo"); - GenericContainer container = startContainerWithCommand(createShellCommand("200 OK", GOOD_RESPONSE_BODY), - createHttpWaitStrategy(ready) - .withHeader("foo", "bar") - .withHeaders(headers) + GenericContainer container = startContainerWithCommand( + createShellCommand("200 OK", GOOD_RESPONSE_BODY), + createHttpWaitStrategy(ready).withHeader("foo", "bar").withHeaders(headers) ); waitUntilReadyAndSucceed(container); @@ -58,14 +58,17 @@ public void testWaitUntilReadyWithSuccessWithCustomHeaders() { } /** - * Ensures that HTTPS requests made with the HttpWaitStrategy can skip the - * certificate validation chains (to support self-signed certificates for example). + * Ensures that HTTPS requests made with the HttpWaitStrategy can skip the + * certificate validation chains (to support self-signed certificates for example). */ @Test public void testWaitUntilReadyWithTlsAndAllowUnsecure() { - waitUntilReadyAndSucceed(startContainerWithCommand(createHttpsShellCommand("200 OK", GOOD_RESPONSE_BODY, 8080), - createHttpWaitStrategy(ready).usingTls().allowInsecure() - )); + waitUntilReadyAndSucceed( + startContainerWithCommand( + createHttpsShellCommand("200 OK", GOOD_RESPONSE_BODY, 8080), + createHttpWaitStrategy(ready).usingTls().allowInsecure() + ) + ); } /** @@ -74,10 +77,12 @@ public void testWaitUntilReadyWithTlsAndAllowUnsecure() { */ @Test public void testWaitUntilReadyWithUnauthorizedWithLambda() { - waitUntilReadyAndSucceed(startContainerWithCommand(createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), - createHttpWaitStrategy(ready) - .forStatusCodeMatching(it -> it >= 200 && it < 300 || it == 401) - )); + waitUntilReadyAndSucceed( + startContainerWithCommand( + createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), + createHttpWaitStrategy(ready).forStatusCodeMatching(it -> it >= 200 && it < 300 || it == 401) + ) + ); } /** @@ -86,12 +91,12 @@ public void testWaitUntilReadyWithUnauthorizedWithLambda() { */ @Test public void testWaitUntilReadyWithManyStatusCodes() { - waitUntilReadyAndSucceed(startContainerWithCommand(createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), - createHttpWaitStrategy(ready) - .forStatusCode(300) - .forStatusCode(401) - .forStatusCode(500) - )); + waitUntilReadyAndSucceed( + startContainerWithCommand( + createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), + createHttpWaitStrategy(ready).forStatusCode(300).forStatusCode(401).forStatusCode(500) + ) + ); } /** @@ -101,12 +106,15 @@ public void testWaitUntilReadyWithManyStatusCodes() { */ @Test public void testWaitUntilReadyWithManyStatusCodesAndLambda() { - waitUntilReadyAndSucceed(startContainerWithCommand(createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), - createHttpWaitStrategy(ready) - .forStatusCode(300) - .forStatusCode(500) - .forStatusCodeMatching(it -> it == 401) - )); + waitUntilReadyAndSucceed( + startContainerWithCommand( + createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), + createHttpWaitStrategy(ready) + .forStatusCode(300) + .forStatusCode(500) + .forStatusCodeMatching(it -> it == 401) + ) + ); } /** @@ -116,11 +124,12 @@ public void testWaitUntilReadyWithManyStatusCodesAndLambda() { */ @Test public void testWaitUntilReadyWithTimeoutAndWithManyStatusCodesAndLambda() { - waitUntilReadyAndTimeout(startContainerWithCommand(createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), - createHttpWaitStrategy(ready) - .forStatusCode(300) - .forStatusCodeMatching(it -> it == 500) - )); + waitUntilReadyAndTimeout( + startContainerWithCommand( + createShellCommand("401 UNAUTHORIZED", GOOD_RESPONSE_BODY), + createHttpWaitStrategy(ready).forStatusCode(300).forStatusCodeMatching(it -> it == 500) + ) + ); } /** @@ -132,10 +141,12 @@ public void testWaitUntilReadyWithTimeoutAndWithManyStatusCodesAndLambda() { */ @Test public void testWaitUntilReadyWithTimeoutAndWithLambdaShouldNotMatchOk() { - waitUntilReadyAndTimeout(startContainerWithCommand(createShellCommand("200 OK", GOOD_RESPONSE_BODY), - createHttpWaitStrategy(ready) - .forStatusCodeMatching(it -> it >= 300) - )); + waitUntilReadyAndTimeout( + startContainerWithCommand( + createShellCommand("200 OK", GOOD_RESPONSE_BODY), + createHttpWaitStrategy(ready).forStatusCodeMatching(it -> it >= 300) + ) + ); } /** @@ -156,27 +167,31 @@ public void testWaitUntilReadyWithTimeoutAndBadResponseBody() { waitUntilReadyAndTimeout(createShellCommand("200 OK", "Bad Response")); } - /** * Expects the WaitStrategy probing the right port. */ @Test public void testWaitUntilReadyWithSpecificPort() { - waitUntilReadyAndSucceed(startContainerWithCommand( - createShellCommand("200 OK", GOOD_RESPONSE_BODY, 9090), - createHttpWaitStrategy(ready) - .forPort(9090), - 7070, 8080, 9090 - )); + waitUntilReadyAndSucceed( + startContainerWithCommand( + createShellCommand("200 OK", GOOD_RESPONSE_BODY, 9090), + createHttpWaitStrategy(ready).forPort(9090), + 7070, + 8080, + 9090 + ) + ); } @Test public void testWaitUntilReadyWithTimoutCausedByReadTimeout() { waitUntilReadyAndTimeout( - startContainerWithCommand(createShellCommand("0 Connection Refused", GOOD_RESPONSE_BODY, 9090), + startContainerWithCommand( + createShellCommand("0 Connection Refused", GOOD_RESPONSE_BODY, 9090), createHttpWaitStrategy(ready).forPort(9090).withReadTimeout(Duration.ofMillis(1)), 9090 - )); + ) + ); } /** @@ -185,8 +200,7 @@ public void testWaitUntilReadyWithTimoutCausedByReadTimeout() { */ @NotNull protected HttpWaitStrategy buildWaitStrategy(final AtomicBoolean ready) { - return createHttpWaitStrategy(ready) - .forResponsePredicate(s -> s.equals(GOOD_RESPONSE_BODY)); + return createHttpWaitStrategy(ready).forResponsePredicate(s -> s.equals(GOOD_RESPONSE_BODY)); } /** @@ -212,17 +226,41 @@ private String createShellCommand(String header, String responseBody) { private String createShellCommand(String header, String responseBody, int port) { int length = responseBody.getBytes().length; - return "while true; do { echo -e \"HTTP/1.1 " + header + NEWLINE + - "Content-Type: text/html" + NEWLINE + - "Content-Length: " + length + NEWLINE + "\";" - + " echo \"" + responseBody + "\";} | nc -lp " + port + "; done"; + return ( + "while true; do { echo -e \"HTTP/1.1 " + + header + + NEWLINE + + "Content-Type: text/html" + + NEWLINE + + "Content-Length: " + + length + + NEWLINE + + "\";" + + " echo \"" + + responseBody + + "\";} | nc -lp " + + port + + "; done" + ); } - + private String createHttpsShellCommand(String header, String responseBody, int port) { int length = responseBody.getBytes().length; - return "apk add nmap-ncat; while true; do { echo -e \"HTTP/1.1 " + header + NEWLINE + - "Content-Type: text/html" + NEWLINE + - "Content-Length: " + length + NEWLINE + "\";" - + " echo \"" + responseBody + "\";} | ncat -lp " + port + " --ssl; done"; + return ( + "apk add nmap-ncat; while true; do { echo -e \"HTTP/1.1 " + + header + + NEWLINE + + "Content-Type: text/html" + + NEWLINE + + "Content-Length: " + + length + + NEWLINE + + "\";" + + " echo \"" + + responseBody + + "\";} | ncat -lp " + + port + + " --ssl; done" + ); } } diff --git a/core/src/test/java/org/testcontainers/junit/wait/strategy/LogMessageWaitStrategyTest.java b/core/src/test/java/org/testcontainers/junit/wait/strategy/LogMessageWaitStrategyTest.java index a6ef9f11ba4..5dd9623107b 100644 --- a/core/src/test/java/org/testcontainers/junit/wait/strategy/LogMessageWaitStrategyTest.java +++ b/core/src/test/java/org/testcontainers/junit/wait/strategy/LogMessageWaitStrategyTest.java @@ -19,9 +19,9 @@ public class LogMessageWaitStrategyTest extends AbstractWaitStrategyTest { - builder.from(DOCKER_REGISTRY_IMAGE.asCanonicalNameString()) - .run("htpasswd -Bbn testuser notasecret > /htpasswd") - .env("REGISTRY_AUTH", "htpasswd") - .env("REGISTRY_AUTH_HTPASSWD_PATH", "/htpasswd") - .env("REGISTRY_AUTH_HTPASSWD_REALM", "Test"); - })); + public static DockerRegistryContainer authenticatedRegistry = new DockerRegistryContainer( + new ImageFromDockerfile() + .withDockerfileFromBuilder(builder -> { + builder + .from(TestImages.DOCKER_REGISTRY_IMAGE.asCanonicalNameString()) + .run("htpasswd -Bbn testuser notasecret > /htpasswd") + .env("REGISTRY_AUTH", "htpasswd") + .env("REGISTRY_AUTH_HTPASSWD_PATH", "/htpasswd") + .env("REGISTRY_AUTH_HTPASSWD_REALM", "Test"); + }) + ); private static RegistryAuthLocator originalAuthLocatorSingleton; @@ -65,7 +68,12 @@ public static void beforeClass() throws Exception { // Replace the RegistryAuthLocator singleton with our mock, for the duration of this test final RegistryAuthLocator mockAuthLocator = Mockito.mock(RegistryAuthLocator.class); RegistryAuthLocator.setInstance(mockAuthLocator); - when(mockAuthLocator.lookupAuthConfig(argThat(argument -> testRegistryAddress.equals(argument.getRegistry())), any())) + when( + mockAuthLocator.lookupAuthConfig( + argThat(argument -> testRegistryAddress.equals(argument.getRegistry())), + any() + ) + ) .thenReturn(authConfig); } @@ -77,8 +85,10 @@ public static void tearDown() { @Test public void testThatAuthLocatorIsUsedForContainerCreation() { // actually start a container, which will require an authenticated pull - try (final GenericContainer container = new GenericContainer<>(testImageName) - .withCommand("/bin/sh", "-c", "sleep 10")) { + try ( + final GenericContainer container = new GenericContainer<>(testImageName) + .withCommand("/bin/sh", "-c", "sleep 10") + ) { container.start(); assertTrue("container started following an authenticated pull", container.isRunning()); @@ -93,11 +103,12 @@ public void testThatAuthLocatorIsUsedForDockerfileBuild() throws IOException { Files.write(tempFile, dockerFileContent.getBytes()); // Start a container built from a derived image, which will require an authenticated pull - try (final GenericContainer container = new GenericContainer<>( - new ImageFromDockerfile() - .withDockerfile(tempFile) - ) - .withCommand("/bin/sh", "-c", "sleep 10")) { + try ( + final GenericContainer container = new GenericContainer<>( + new ImageFromDockerfile().withDockerfile(tempFile) + ) + .withCommand("/bin/sh", "-c", "sleep 10") + ) { container.start(); assertTrue("container started following an authenticated pull", container.isRunning()); @@ -108,23 +119,23 @@ public void testThatAuthLocatorIsUsedForDockerfileBuild() throws IOException { public void testThatAuthLocatorIsUsedForDockerComposePull() throws IOException { // Prepare a simple temporary Docker Compose manifest which requires our custom private image Path tempFile = getLocalTempFile(".docker-compose.yml"); - @Language("yaml") String composeFileContent = + @Language("yaml") + String composeFileContent = "version: '2.0'\n" + - "services:\n" + - " privateservice:\n" + - " command: /bin/sh -c 'sleep 60'\n" + - " image: " + testImageName.asCanonicalNameString(); + "services:\n" + + " privateservice:\n" + + " command: /bin/sh -c 'sleep 60'\n" + + " image: " + + testImageName.asCanonicalNameString(); Files.write(tempFile, composeFileContent.getBytes()); // Start the docker compose project, which will require an authenticated pull try (final DockerComposeContainer compose = new DockerComposeContainer<>(tempFile.toFile())) { compose.start(); - assertTrue("container started following an authenticated pull", - compose - .getContainerByServiceName("privateservice_1") - .map(ContainerState::isRunning) - .orElse(false) + assertTrue( + "container started following an authenticated pull", + compose.getContainerByServiceName("privateservice_1").map(ContainerState::isRunning).orElse(false) ); } } diff --git a/core/src/test/java/org/testcontainers/utility/ClasspathScannerTest.java b/core/src/test/java/org/testcontainers/utility/ClasspathScannerTest.java index bdd71b0db9f..4ed86e3a8fa 100644 --- a/core/src/test/java/org/testcontainers/utility/ClasspathScannerTest.java +++ b/core/src/test/java/org/testcontainers/utility/ClasspathScannerTest.java @@ -5,11 +5,11 @@ import java.io.IOException; import java.net.URL; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; -import static java.util.Arrays.asList; -import static java.util.stream.Collectors.toList; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -18,9 +18,13 @@ public class ClasspathScannerTest { private static URL FILE_A; + private static URL FILE_B; + private static URL JAR_A; + private static URL JAR_B; + private static URL FILE_C; @BeforeClass @@ -35,7 +39,7 @@ public static void setUp() throws Exception { @Test public void realClassLoaderLookupOccurs() { // look for a resource that we know exists only once - final List foundURLs = ClasspathScanner.scanFor("expectedClasspathFile.txt").collect(toList()); + final List foundURLs = ClasspathScanner.scanFor("expectedClasspathFile.txt").collect(Collectors.toList()); assertEquals("Exactly one resource was found", 1, foundURLs.size()); } @@ -43,41 +47,27 @@ public void realClassLoaderLookupOccurs() { @Test public void multipleResultsOnOneClassLoaderAreFound() throws IOException { final ClassLoader firstMockClassLoader = mock(ClassLoader.class); - when(firstMockClassLoader.getResources(eq("someName"))).thenReturn( - Collections.enumeration( - asList( - FILE_A, - FILE_B - ) - ) - ); + when(firstMockClassLoader.getResources(eq("someName"))) + .thenReturn(Collections.enumeration(Arrays.asList(FILE_A, FILE_B))); - final List foundURLs = ClasspathScanner.scanFor("someName", firstMockClassLoader).collect(toList()); - assertEquals( - "The expected URLs are found", - asList(FILE_A, FILE_B), - foundURLs - ); + final List foundURLs = ClasspathScanner + .scanFor("someName", firstMockClassLoader) + .collect(Collectors.toList()); + assertEquals("The expected URLs are found", Arrays.asList(FILE_A, FILE_B), foundURLs); } @Test public void orderIsAlphabeticalForDeterminism() throws IOException { final ClassLoader firstMockClassLoader = mock(ClassLoader.class); - when(firstMockClassLoader.getResources(eq("someName"))).thenReturn( - Collections.enumeration( - asList( - FILE_B, - JAR_A, - JAR_B, - FILE_A - ) - ) - ); + when(firstMockClassLoader.getResources(eq("someName"))) + .thenReturn(Collections.enumeration(Arrays.asList(FILE_B, JAR_A, JAR_B, FILE_A))); - final List foundURLs = ClasspathScanner.scanFor("someName", firstMockClassLoader).collect(toList()); + final List foundURLs = ClasspathScanner + .scanFor("someName", firstMockClassLoader) + .collect(Collectors.toList()); assertEquals( "The expected URLs are found in the expected order", - asList(FILE_A, FILE_B, JAR_A, JAR_B), + Arrays.asList(FILE_A, FILE_B, JAR_A, JAR_B), foundURLs ); } @@ -85,30 +75,23 @@ public void orderIsAlphabeticalForDeterminism() throws IOException { @Test public void multipleClassLoadersAreQueried() throws IOException { final ClassLoader firstMockClassLoader = mock(ClassLoader.class); - when(firstMockClassLoader.getResources(eq("someName"))).thenReturn( - Collections.enumeration( - asList( - FILE_A, - FILE_B - ) - ) - ); + when(firstMockClassLoader.getResources(eq("someName"))) + .thenReturn(Collections.enumeration(Arrays.asList(FILE_A, FILE_B))); final ClassLoader secondMockClassLoader = mock(ClassLoader.class); - when(secondMockClassLoader.getResources(eq("someName"))).thenReturn( - Collections.enumeration( - asList( - FILE_B, // duplicate - FILE_C + when(secondMockClassLoader.getResources(eq("someName"))) + .thenReturn( + Collections.enumeration( + Arrays.asList( + FILE_B, // duplicate + FILE_C + ) ) - ) - ); + ); - final List foundURLs = ClasspathScanner.scanFor("someName", firstMockClassLoader, secondMockClassLoader).collect(toList()); + final List foundURLs = ClasspathScanner + .scanFor("someName", firstMockClassLoader, secondMockClassLoader) + .collect(Collectors.toList()); - assertEquals( - "The expected URLs are found", - asList(FILE_A, FILE_B, FILE_C), - foundURLs - ); + assertEquals("The expected URLs are found", Arrays.asList(FILE_A, FILE_B, FILE_C), foundURLs); } } diff --git a/core/src/test/java/org/testcontainers/utility/ComparableVersionTest.java b/core/src/test/java/org/testcontainers/utility/ComparableVersionTest.java index d5a2c63a5b8..fb3c7e05c0b 100644 --- a/core/src/test/java/org/testcontainers/utility/ComparableVersionTest.java +++ b/core/src/test/java/org/testcontainers/utility/ComparableVersionTest.java @@ -1,18 +1,19 @@ package org.testcontainers.utility; -import java.util.Arrays; - import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import java.util.Arrays; + import static org.junit.Assert.assertArrayEquals; @RunWith(Parameterized.class) public class ComparableVersionTest { private final int[] expected; + private final String given; public ComparableVersionTest(final String given, final int[] expected) { @@ -27,14 +28,15 @@ public void shouldParseVersions() { @Parameters(name = "Parsed version: {0}={1}") public static Iterable data() { - return Arrays.asList(new Object[][] { - {"1.2.3", new int[] {1, 2, 3}}, - {"", new int[0]}, - {"1", new int[] {1}}, - {"1.2.3.4.5.6.7", new int[] {1, 2, 3, 4, 5, 6, 7}}, - {"1.2-dev", new int[] {1, 2}}, - {"18.06.0-dev", new int[] {18, 6}}, - }); + return Arrays.asList( + new Object[][] { + { "1.2.3", new int[] { 1, 2, 3 } }, + { "", new int[0] }, + { "1", new int[] { 1 } }, + { "1.2.3.4.5.6.7", new int[] { 1, 2, 3, 4, 5, 6, 7 } }, + { "1.2-dev", new int[] { 1, 2 } }, + { "18.06.0-dev", new int[] { 18, 6 } }, + } + ); } - } diff --git a/core/src/test/java/org/testcontainers/utility/DefaultImageNameSubstitutorTest.java b/core/src/test/java/org/testcontainers/utility/DefaultImageNameSubstitutorTest.java index a6f7813c3d3..0978003f815 100644 --- a/core/src/test/java/org/testcontainers/utility/DefaultImageNameSubstitutorTest.java +++ b/core/src/test/java/org/testcontainers/utility/DefaultImageNameSubstitutorTest.java @@ -12,7 +12,9 @@ public class DefaultImageNameSubstitutorTest { public static final DockerImageName ORIGINAL_IMAGE = DockerImageName.parse("foo"); + public static final DockerImageName SUBSTITUTE_IMAGE = DockerImageName.parse("bar"); + private ConfigurationFileImageNameSubstitutor underTest; @Rule diff --git a/core/src/test/java/org/testcontainers/utility/DirectoryTarResourceTest.java b/core/src/test/java/org/testcontainers/utility/DirectoryTarResourceTest.java index f439c55c3ea..cbd35a62b52 100644 --- a/core/src/test/java/org/testcontainers/utility/DirectoryTarResourceTest.java +++ b/core/src/test/java/org/testcontainers/utility/DirectoryTarResourceTest.java @@ -11,8 +11,8 @@ import java.io.File; import java.util.Arrays; -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; @@ -24,41 +24,51 @@ public void simpleRecursiveFileTest() { File directory = new File("src"); GenericContainer container = new GenericContainer( - new ImageFromDockerfile() - .withDockerfileFromBuilder(builder -> - builder.from("alpine:3.14") - .copy("/tmp/foo", "/foo") - .cmd("cat /foo/test/resources/test-recursive-file.txt") - .build() - ).withFileFromFile("/tmp/foo", directory)) - .withStartupCheckStrategy(new OneShotStartupCheckStrategy()); + new ImageFromDockerfile() + .withDockerfileFromBuilder(builder -> { + builder + .from("alpine:3.14") + .copy("/tmp/foo", "/foo") + .cmd("cat /foo/test/resources/test-recursive-file.txt") + .build(); + }) + .withFileFromFile("/tmp/foo", directory) + ) + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()); container.start(); final String results = container.getLogs(); - assertTrue("The container has a file that was copied in via a recursive copy", results.contains("Used for DirectoryTarResourceTest")); + assertTrue( + "The container has a file that was copied in via a recursive copy", + results.contains("Used for DirectoryTarResourceTest") + ); } @Test public void simpleRecursiveFileWithPermissionTest() { GenericContainer container = new GenericContainer( - new ImageFromDockerfile() - .withDockerfileFromBuilder(builder -> - builder.from("alpine:3.14") - .copy("/tmp/foo", "/foo") - .cmd("ls", "-al", "/") - .build() - ).withFileFromFile("/tmp/foo", new File("/mappable-resource/test-resource.txt"), - 0754)) - .withStartupCheckStrategy(new OneShotStartupCheckStrategy()); + new ImageFromDockerfile() + .withDockerfileFromBuilder(builder -> { + builder + .from("alpine:3.14") // + .copy("/tmp/foo", "/foo") + .cmd("ls", "-al", "/") + .build(); + }) + .withFileFromFile("/tmp/foo", new File("/mappable-resource/test-resource.txt"), 0754) + ) + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()); container.start(); String listing = container.getLogs(); - assertThat("Listing shows that file is copied with mode requested.", - Arrays.asList(listing.split("\\n")), - exactlyNItems(1, allOf(containsString("-rwxr-xr--"), containsString("foo")))); + assertThat( + "Listing shows that file is copied with mode requested.", + Arrays.asList(listing.split("\\n")), + exactlyNItems(1, allOf(containsString("-rwxr-xr--"), containsString("foo"))) + ); } @Test @@ -66,21 +76,27 @@ public void simpleRecursiveClasspathResourceTest() { // This test combines the copying of classpath resources from JAR files with the recursive TAR approach, to allow JARed classpath resources to be copied in to an image GenericContainer container = new GenericContainer( - new ImageFromDockerfile() - .withDockerfileFromBuilder(builder -> - builder.from("alpine:3.14") - .copy("/tmp/foo", "/foo") - .cmd("ls -lRt /foo") - .build() - ).withFileFromClasspath("/tmp/foo", "/recursive/dir")) // here we use /org/junit as a directory that really should exist on the classpath - .withStartupCheckStrategy(new OneShotStartupCheckStrategy()); + new ImageFromDockerfile() + .withDockerfileFromBuilder(builder -> { + builder + .from("alpine:3.14") // + .copy("/tmp/foo", "/foo") + .cmd("ls -lRt /foo") + .build(); + }) + .withFileFromClasspath("/tmp/foo", "/recursive/dir") + ) // here we use /org/junit as a directory that really should exist on the classpath + .withStartupCheckStrategy(new OneShotStartupCheckStrategy()); container.start(); final String results = container.getLogs(); // ExternalResource.class is known to exist in a subdirectory of /org/junit so should be successfully copied in - assertTrue("The container has a file that was copied in via a recursive copy from a JAR resource", results.contains("content.txt")); + assertTrue( + "The container has a file that was copied in via a recursive copy from a JAR resource", + results.contains("content.txt") + ); } public static Matcher> exactlyNItems(final int n, Matcher elementMatcher) { @@ -91,7 +107,6 @@ protected boolean matchesSafely(Iterable collection, Description mism boolean isPastFirst = false; for (Object item : collection) { - if (elementMatcher.matches(item)) { count++; } diff --git a/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java b/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java index 22d67de5785..f2ca26b8947 100644 --- a/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java +++ b/core/src/test/java/org/testcontainers/utility/DockerImageNameCompatibilityTest.java @@ -1,13 +1,12 @@ package org.testcontainers.utility; -import static org.hamcrest.core.StringContains.containsString; -import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; -import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; - import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import static org.hamcrest.Matchers.containsString; +import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; +import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; public class DockerImageNameCompatibilityTest { @@ -20,6 +19,7 @@ public void testPlainImage() { assertFalse("image name foo != bar", subject.isCompatibleWith(DockerImageName.parse("bar"))); } + @Test public void testNoTagTreatedAsWildcard() { final DockerImageName subject = DockerImageName.parse("foo:4.5.6"); @@ -59,7 +59,10 @@ public void testImageWithClaimedCompatibilityAndVersion() { public void testImageWithClaimedCompatibilityForFullPath() { DockerImageName subject = DockerImageName.parse("foo").asCompatibleSubstituteFor("registry/repo/bar"); - assertTrue("foo(registry/repo/bar) ~= registry/repo/bar", subject.isCompatibleWith(DockerImageName.parse("registry/repo/bar"))); + assertTrue( + "foo(registry/repo/bar) ~= registry/repo/bar", + subject.isCompatibleWith(DockerImageName.parse("registry/repo/bar")) + ); assertFalse("foo(registry/repo/bar) != repo/bar", subject.isCompatibleWith(DockerImageName.parse("repo/bar"))); assertFalse("foo(registry/repo/bar) != bar", subject.isCompatibleWith(DockerImageName.parse("bar"))); } diff --git a/core/src/test/java/org/testcontainers/utility/DockerImageNameTest.java b/core/src/test/java/org/testcontainers/utility/DockerImageNameTest.java index e06407fbf56..98fd21064ed 100644 --- a/core/src/test/java/org/testcontainers/utility/DockerImageNameTest.java +++ b/core/src/test/java/org/testcontainers/utility/DockerImageNameTest.java @@ -16,7 +16,7 @@ public static class ValidNames { @Parameterized.Parameters(name = "{0}") public static String[] getNames() { - return new String[]{ + return new String[] { "myname:latest", "repo/my-name:1.0", "registry.foo.com:1234/my-name:1.0", @@ -27,7 +27,8 @@ public static String[] getNames() { "1.2.3.4/my-name:1.0", "1.2.3.4:1234/my-name:1.0", "1.2.3.4/repo-here/my-name:1.0", - "1.2.3.4:1234/repo-here/my-name:1.0"}; + "1.2.3.4:1234/repo-here/my-name:1.0", + }; } @Parameterized.Parameter @@ -44,11 +45,13 @@ public static class InvalidNames { @Parameterized.Parameters(name = "{0}") public static String[] getNames() { - return new String[]{":latest", + return new String[] { + ":latest", "/myname:latest", "/myname@sha256:latest", "/myname@sha256:gggggggggggggggggggggggggggggggg", - "repo:notaport/myname:latest"}; + "repo:notaport/myname:latest", + }; } @Parameterized.Parameter @@ -65,39 +68,43 @@ public static class Parsing { @Parameterized.Parameters(name = "{0}{1}{2}{3}{4}") public static String[][] getNames() { - return new String[][]{ - {"", "", "myname", ":", null}, - {"", "", "myname", ":", "latest"}, - {"", "", "repo/myname", ":", null}, - {"", "", "repo/myname", ":", "latest"}, - {"registry.foo.com:1234", "/", "my-name", ":", null}, - {"registry.foo.com:1234", "/", "my-name", ":", "1.0"}, - {"registry.foo.com", "/", "my-name", ":", "1.0"}, - {"registry.foo.com:1234", "/", "repo_here/my-name", ":", null}, - {"registry.foo.com:1234", "/", "repo_here/my-name", ":", "1.0"}, - {"1.2.3.4:1234", "/", "repo_here/my-name", ":", null}, - {"1.2.3.4:1234", "/", "repo_here/my-name", ":", "1.0"}, - {"1.2.3.4:1234", "/", "my-name", ":", null}, - {"1.2.3.4:1234", "/", "my-name", ":", "1.0"}, - {"", "", "myname", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"}, - {"", "", "repo/myname", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"}, - {"registry.foo.com:1234", "/", "repo-here/my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"}, - {"registry.foo.com:1234", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"}, - {"1.2.3.4", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"}, - {"1.2.3.4:1234", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"}, - {"1.2.3.4", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"}, - {"1.2.3.4:1234", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd"} + return new String[][] { + { "", "", "myname", ":", null }, + { "", "", "myname", ":", "latest" }, + { "", "", "repo/myname", ":", null }, + { "", "", "repo/myname", ":", "latest" }, + { "registry.foo.com:1234", "/", "my-name", ":", null }, + { "registry.foo.com:1234", "/", "my-name", ":", "1.0" }, + { "registry.foo.com", "/", "my-name", ":", "1.0" }, + { "registry.foo.com:1234", "/", "repo_here/my-name", ":", null }, + { "registry.foo.com:1234", "/", "repo_here/my-name", ":", "1.0" }, + { "1.2.3.4:1234", "/", "repo_here/my-name", ":", null }, + { "1.2.3.4:1234", "/", "repo_here/my-name", ":", "1.0" }, + { "1.2.3.4:1234", "/", "my-name", ":", null }, + { "1.2.3.4:1234", "/", "my-name", ":", "1.0" }, + { "", "", "myname", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, + { "", "", "repo/myname", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, + { "registry.foo.com:1234", "/", "repo-here/my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, + { "registry.foo.com:1234", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, + { "1.2.3.4", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, + { "1.2.3.4:1234", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, + { "1.2.3.4", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, + { "1.2.3.4:1234", "/", "my-name", "@", "sha256:1234abcd1234abcd1234abcd1234abcd" }, }; } @Parameterized.Parameter(0) public String registry; + @Parameterized.Parameter(1) public String registrySeparator; + @Parameterized.Parameter(2) public String repo; + @Parameterized.Parameter(3) public String versionSeparator; + @Parameterized.Parameter(4) public String version; @@ -120,21 +127,45 @@ public void testParsing() { final DockerImageName imageName = DockerImageName.parse(combined); assertEquals(combined + " has registry address: " + registry, registry, imageName.getRegistry()); - assertEquals(combined + " has unversioned part: " + unversionedPart, unversionedPart, imageName.getUnversionedPart()); + assertEquals( + combined + " has unversioned part: " + unversionedPart, + unversionedPart, + imageName.getUnversionedPart() + ); if (version != null) { assertEquals(combined + " has version part: " + version, version, imageName.getVersionPart()); } else { - assertEquals(combined + " has automatic 'latest' version specified", "latest", imageName.getVersionPart()); + assertEquals( + combined + " has automatic 'latest' version specified", + "latest", + imageName.getVersionPart() + ); } - assertEquals(combined + " has canonical name: " + canonicalName, canonicalName, imageName.asCanonicalNameString()); + assertEquals( + combined + " has canonical name: " + canonicalName, + canonicalName, + imageName.asCanonicalNameString() + ); if (version != null) { VisibleAssertions.context("Using two-arg constructor:", 2); final DockerImageName imageNameFromSecondaryConstructor = new DockerImageName(unversionedPart, version); - assertEquals(combined + " has registry address: " + registry, registry, imageNameFromSecondaryConstructor.getRegistry()); - assertEquals(combined + " has unversioned part: " + unversionedPart, unversionedPart, imageNameFromSecondaryConstructor.getUnversionedPart()); - assertEquals(combined + " has version part: " + version, version, imageNameFromSecondaryConstructor.getVersionPart()); + assertEquals( + combined + " has registry address: " + registry, + registry, + imageNameFromSecondaryConstructor.getRegistry() + ); + assertEquals( + combined + " has unversioned part: " + unversionedPart, + unversionedPart, + imageNameFromSecondaryConstructor.getUnversionedPart() + ); + assertEquals( + combined + " has version part: " + version, + version, + imageNameFromSecondaryConstructor.getVersionPart() + ); } } } diff --git a/core/src/test/java/org/testcontainers/utility/DockerStatusTest.java b/core/src/test/java/org/testcontainers/utility/DockerStatusTest.java index 1ef8e136a32..36196aaf4c1 100644 --- a/core/src/test/java/org/testcontainers/utility/DockerStatusTest.java +++ b/core/src/test/java/org/testcontainers/utility/DockerStatusTest.java @@ -8,7 +8,7 @@ import java.time.Duration; import java.time.Instant; -import java.time.ZoneId; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; import static org.junit.Assert.assertFalse; @@ -18,8 +18,9 @@ /** * */ - @RunWith(Parameterized.class) +@RunWith(Parameterized.class) public class DockerStatusTest { + private final DateTimeFormatter dateTimeFormatter; private static final Instant now = Instant.now(); @@ -55,8 +56,8 @@ public DockerStatusTest(DateTimeFormatter dateTimeFormatter) { @Parameterized.Parameters public static Object[][] parameters() { return new Object[][] { - { DateTimeFormatter.ISO_INSTANT}, - { DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.of("America/New_York")) } + { DateTimeFormatter.ISO_INSTANT }, + { DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.of("America/New_York")) }, }; } @@ -88,9 +89,12 @@ private String buildTimestamp(Instant instant) { // ContainerState is a non-static inner class, with private member variables, in a different package. // It's simpler to mock it that to try to create one. - private static InspectContainerResponse.ContainerState buildState(boolean running, boolean paused, - String startedAt, String finishedAt) { - + private static InspectContainerResponse.ContainerState buildState( + boolean running, + boolean paused, + String startedAt, + String finishedAt + ) { InspectContainerResponse.ContainerState state = Mockito.mock(InspectContainerResponse.ContainerState.class); when(state.getRunning()).thenReturn(running); when(state.getPaused()).thenReturn(paused); diff --git a/core/src/test/java/org/testcontainers/utility/FakeImageSubstitutor.java b/core/src/test/java/org/testcontainers/utility/FakeImageSubstitutor.java index f74a6c942b3..50681ddc729 100644 --- a/core/src/test/java/org/testcontainers/utility/FakeImageSubstitutor.java +++ b/core/src/test/java/org/testcontainers/utility/FakeImageSubstitutor.java @@ -1,6 +1,7 @@ package org.testcontainers.utility; public class FakeImageSubstitutor extends ImageNameSubstitutor { + @Override public DockerImageName apply(final DockerImageName original) { return DockerImageName.parse("transformed-" + original.asCanonicalNameString()); diff --git a/core/src/test/java/org/testcontainers/utility/FilterRegistryTest.java b/core/src/test/java/org/testcontainers/utility/FilterRegistryTest.java index 49bc870e8d0..30367975d1e 100644 --- a/core/src/test/java/org/testcontainers/utility/FilterRegistryTest.java +++ b/core/src/test/java/org/testcontainers/utility/FilterRegistryTest.java @@ -9,22 +9,27 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.AbstractMap.SimpleEntry; +import java.util.Arrays; import java.util.List; import java.util.Map.Entry; -import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class FilterRegistryTest { - private static final List> FILTERS = asList( - new SimpleEntry<>("key1!", "value2?"), new SimpleEntry<>("key2#", "value2%") + private static final List> FILTERS = Arrays.asList( + new SimpleEntry<>("key1!", "value2?"), + new SimpleEntry<>("key2#", "value2%") ); + private static final String URL_ENCODED_FILTERS = "key1%21=value2%3F&key2%23=value2%25"; + private static final byte[] ACKNOWLEDGEMENT = FilterRegistry.ACKNOWLEDGMENT.getBytes(); + private static final byte[] NO_ACKNOWLEDGEMENT = "".getBytes(); + private static final String NEW_LINE = "\n"; @Test @@ -66,5 +71,4 @@ private static InputStream anyInputStream() { private static OutputStream anyOutputStream() { return new ByteArrayOutputStream(); } - } diff --git a/core/src/test/java/org/testcontainers/utility/ImageNameSubstitutorTest.java b/core/src/test/java/org/testcontainers/utility/ImageNameSubstitutorTest.java index 97ee0213f21..f7e319a5948 100644 --- a/core/src/test/java/org/testcontainers/utility/ImageNameSubstitutorTest.java +++ b/core/src/test/java/org/testcontainers/utility/ImageNameSubstitutorTest.java @@ -13,7 +13,9 @@ public class ImageNameSubstitutorTest { @Rule public MockTestcontainersConfigurationRule config = new MockTestcontainersConfigurationRule(); + private ImageNameSubstitutor originalInstance; + private ImageNameSubstitutor originalDefaultImplementation; @Before @@ -27,10 +29,7 @@ public void setUp() throws Exception { .doReturn(DockerImageName.parse("substituted-image")) .when(ImageNameSubstitutor.defaultImplementation) .apply(eq(DockerImageName.parse("original"))); - Mockito - .doReturn("default implementation") - .when(ImageNameSubstitutor.defaultImplementation) - .getDescription(); + Mockito.doReturn("default implementation").when(ImageNameSubstitutor.defaultImplementation).getDescription(); } @After @@ -58,10 +57,7 @@ public void simpleConfigurationTest() { @Test public void testWorksWithoutConfiguredImplementation() { - Mockito - .doReturn(null) - .when(TestcontainersConfiguration.getInstance()) - .getImageSubstitutorClassName(); + Mockito.doReturn(null).when(TestcontainersConfiguration.getInstance()).getImageSubstitutorClassName(); final ImageNameSubstitutor imageNameSubstitutor = ImageNameSubstitutor.instance(); diff --git a/core/src/test/java/org/testcontainers/utility/LazyFutureTest.java b/core/src/test/java/org/testcontainers/utility/LazyFutureTest.java index 81805106806..99443221805 100644 --- a/core/src/test/java/org/testcontainers/utility/LazyFutureTest.java +++ b/core/src/test/java/org/testcontainers/utility/LazyFutureTest.java @@ -8,9 +8,9 @@ import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import java.util.stream.IntStream; -import static java.util.stream.Collectors.toList; import static org.rnorth.visibleassertions.VisibleAssertions.*; public class LazyFutureTest { @@ -64,9 +64,14 @@ protected Integer resolve() { } }; - Future> task = new ForkJoinPool(numOfThreads).submit(() -> { - return IntStream.rangeClosed(1, numOfThreads).parallel().mapToObj(i -> Futures.getUnchecked(lazyFuture)).collect(toList()); - }); + Future> task = new ForkJoinPool(numOfThreads) + .submit(() -> { + return IntStream + .rangeClosed(1, numOfThreads) + .parallel() + .mapToObj(i -> Futures.getUnchecked(lazyFuture)) + .collect(Collectors.toList()); + }); while (latch.getCount() > 0) { latch.countDown(); @@ -74,5 +79,4 @@ protected Integer resolve() { assertEquals("All threads receives the same result", Collections.nCopies(numOfThreads, 1), task.get()); } - -} \ No newline at end of file +} diff --git a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java index c7dcaad2908..d3ff085c5de 100644 --- a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java +++ b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java @@ -20,7 +20,9 @@ public class MountableFileTest { private static final int TEST_FILE_MODE = 0532; + private static final int BASE_FILE_MODE = 0100000; + private static final int BASE_DIR_MODE = 0040000; @Test @@ -67,7 +69,10 @@ public void forHostPathWithSpaces() throws Exception { performChecks(mountableFile); assertTrue("The resolved path contains the original space", mountableFile.getResolvedPath().contains(" ")); - assertFalse("The resolved path does not contain an escaped space", mountableFile.getResolvedPath().contains("\\ ")); + assertFalse( + "The resolved path does not contain an escaped space", + mountableFile.getResolvedPath().contains("\\ ") + ); } @Test @@ -78,13 +83,18 @@ public void forHostPathWithPlus() throws Exception { performChecks(mountableFile); assertTrue("The resolved path contains the original space", mountableFile.getResolvedPath().contains("+")); - assertFalse("The resolved path does not contain an escaped space", mountableFile.getResolvedPath().contains(" ")); + assertFalse( + "The resolved path does not contain an escaped space", + mountableFile.getResolvedPath().contains(" ") + ); } @Test public void forClasspathResourceWithPermission() throws Exception { - final MountableFile mountableFile = MountableFile.forClasspathResource("mappable-resource/test-resource.txt", - TEST_FILE_MODE); + final MountableFile mountableFile = MountableFile.forClasspathResource( + "mappable-resource/test-resource.txt", + TEST_FILE_MODE + ); performChecks(mountableFile); assertEquals("Valid file mode.", BASE_FILE_MODE | TEST_FILE_MODE, mountableFile.getFileMode()); @@ -110,7 +120,8 @@ public void forHostDirPathWithPermission() throws Exception { public void noTrailingSlashesInTarEntryNames() throws Exception { final MountableFile mountableFile = MountableFile.forClasspathResource("mappable-resource/test-resource.txt"); - @Cleanup final TarArchiveInputStream tais = intoTarArchive((taos) -> { + @Cleanup + final TarArchiveInputStream tais = intoTarArchive(taos -> { mountableFile.transferTo(taos, "/some/path.txt"); mountableFile.transferTo(taos, "/path.txt"); mountableFile.transferTo(taos, "path.txt"); @@ -123,8 +134,10 @@ public void noTrailingSlashesInTarEntryNames() throws Exception { } private TarArchiveInputStream intoTarArchive(Consumer consumer) throws IOException { - @Cleanup final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - @Cleanup final TarArchiveOutputStream taos = new TarArchiveOutputStream(baos); + @Cleanup + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + @Cleanup + final TarArchiveOutputStream taos = new TarArchiveOutputStream(baos); consumer.accept(taos); taos.close(); @@ -151,7 +164,9 @@ private Path createTempDir() throws IOException { private void performChecks(final MountableFile mountableFile) { final String mountablePath = mountableFile.getResolvedPath(); assertTrue("The filesystem path '" + mountablePath + "' can be found", new File(mountablePath).exists()); - assertFalse("The filesystem path '" + mountablePath + "' does not contain any URL escaping", mountablePath.contains("%20")); + assertFalse( + "The filesystem path '" + mountablePath + "' does not contain any URL escaping", + mountablePath.contains("%20") + ); } - } diff --git a/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java b/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java index d2c33989deb..211f8e00536 100644 --- a/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java +++ b/core/src/test/java/org/testcontainers/utility/PrefixingImageNameSubstitutorTest.java @@ -8,11 +8,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.utility.PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY; public class PrefixingImageNameSubstitutorTest { private TestcontainersConfiguration mockConfiguration; + private PrefixingImageNameSubstitutor underTest; @Before @@ -23,7 +23,8 @@ public void setUp() { @Test public void testHappyPath() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com/our-mirror/"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/our-mirror/"); final DockerImageName result = underTest.apply(DockerImageName.parse("some/image:tag")); @@ -36,33 +37,28 @@ public void testHappyPath() { @Test public void hubIoRegistryIsNotChanged() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com/our-mirror/"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/our-mirror/"); final DockerImageName result = underTest.apply(DockerImageName.parse("docker.io/some/image:tag")); - assertEquals( - "The prefix is applied", - "docker.io/some/image:tag", - result.asCanonicalNameString() - ); + assertEquals("The prefix is applied", "docker.io/some/image:tag", result.asCanonicalNameString()); } @Test public void hubComRegistryIsNotChanged() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com/our-mirror/"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/our-mirror/"); final DockerImageName result = underTest.apply(DockerImageName.parse("registry.hub.docker.com/some/image:tag")); - assertEquals( - "The prefix is applied", - "registry.hub.docker.com/some/image:tag", - result.asCanonicalNameString() - ); + assertEquals("The prefix is applied", "registry.hub.docker.com/some/image:tag", result.asCanonicalNameString()); } @Test public void thirdPartyRegistriesNotAffected() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com/our-mirror/"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/our-mirror/"); final DockerImageName result = underTest.apply(DockerImageName.parse("gcr.io/something/image:tag")); @@ -75,7 +71,8 @@ public void thirdPartyRegistriesNotAffected() { @Test public void testNoDoublePrefixing() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com/our-mirror/"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/our-mirror/"); final DockerImageName result = underTest.apply(DockerImageName.parse("someregistry.com/some/image:tag")); @@ -88,7 +85,8 @@ public void testNoDoublePrefixing() { @Test public void testHandlesEmptyValue() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn(""); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn(""); final DockerImageName result = underTest.apply(DockerImageName.parse("some/image:tag")); @@ -101,39 +99,38 @@ public void testHandlesEmptyValue() { @Test public void testHandlesRegistryOnlyWithTrailingSlash() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com/"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/"); final DockerImageName result = underTest.apply(DockerImageName.parse("some/image:tag")); - assertEquals( - "The prefix is applied", - "someregistry.com/some/image:tag", - result.asCanonicalNameString() - ); + assertEquals("The prefix is applied", "someregistry.com/some/image:tag", result.asCanonicalNameString()); } @Test public void testCombinesLiterallyForRegistryOnlyWithoutTrailingSlash() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com"); final DockerImageName result = underTest.apply(DockerImageName.parse("some/image:tag")); assertEquals( "The prefix is applied", - "someregistry.comsome/image:tag", // treating the prefix literally, for predictability + "someregistry.comsome/image:tag", // treating the prefix literally, for predictability result.asCanonicalNameString() ); } @Test public void testCombinesLiterallyForBothPartsWithoutTrailingSlash() { - when(mockConfiguration.getEnvVarOrProperty(eq(PREFIX_PROPERTY_KEY), any())).thenReturn("someregistry.com/our-mirror"); + when(mockConfiguration.getEnvVarOrProperty(eq(PrefixingImageNameSubstitutor.PREFIX_PROPERTY_KEY), any())) + .thenReturn("someregistry.com/our-mirror"); final DockerImageName result = underTest.apply(DockerImageName.parse("some/image:tag")); assertEquals( "The prefix is applied", - "someregistry.com/our-mirrorsome/image:tag", // treating the prefix literally, for predictability + "someregistry.com/our-mirrorsome/image:tag", // treating the prefix literally, for predictability result.asCanonicalNameString() ); } diff --git a/core/src/test/java/org/testcontainers/utility/RegistryAuthLocatorTest.java b/core/src/test/java/org/testcontainers/utility/RegistryAuthLocatorTest.java index 5db2583958a..4ddfad8454f 100644 --- a/core/src/test/java/org/testcontainers/utility/RegistryAuthLocatorTest.java +++ b/core/src/test/java/org/testcontainers/utility/RegistryAuthLocatorTest.java @@ -14,13 +14,21 @@ import static org.rnorth.visibleassertions.VisibleAssertions.*; public class RegistryAuthLocatorTest { + @Test public void lookupAuthConfigWithoutCredentials() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-empty.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("unauthenticated.registry.org/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("unauthenticated.registry.org/org/repo"), + new AuthConfig() + ); - assertEquals("Default docker registry URL is set on auth config", "https://index.docker.io/v1/", authConfig.getRegistryAddress()); + assertEquals( + "Default docker registry URL is set on auth config", + "https://index.docker.io/v1/", + authConfig.getRegistryAddress() + ); assertNull("No username is set", authConfig.getUsername()); assertNull("No password is set", authConfig.getPassword()); } @@ -29,9 +37,16 @@ public void lookupAuthConfigWithoutCredentials() throws URISyntaxException { public void lookupAuthConfigWithBasicAuthCredentials() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-basic-auth.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("registry.example.com/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("registry.example.com/org/repo"), + new AuthConfig() + ); - assertEquals("Default docker registry URL is set on auth config", "https://registry.example.com", authConfig.getRegistryAddress()); + assertEquals( + "Default docker registry URL is set on auth config", + "https://registry.example.com", + authConfig.getRegistryAddress() + ); assertEquals("Username is set", "user", authConfig.getUsername()); assertEquals("Password is set", "pass", authConfig.getPassword()); } @@ -40,9 +55,16 @@ public void lookupAuthConfigWithBasicAuthCredentials() throws URISyntaxException public void lookupAuthConfigWithJsonKeyCredentials() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-with-json-key.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("registry.example.com/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("registry.example.com/org/repo"), + new AuthConfig() + ); - assertEquals("Default docker registry URL is set on auth config", "https://registry.example.com", authConfig.getRegistryAddress()); + assertEquals( + "Default docker registry URL is set on auth config", + "https://registry.example.com", + authConfig.getRegistryAddress() + ); assertEquals("Username is set", "_json_key", authConfig.getUsername()); assertNotNull("Password is set", authConfig.getPassword()); } @@ -51,7 +73,10 @@ public void lookupAuthConfigWithJsonKeyCredentials() throws URISyntaxException { public void lookupAuthConfigUsingStore() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-with-store.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("registry.example.com/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("registry.example.com/org/repo"), + new AuthConfig() + ); assertEquals("Correct server URL is obtained from a credential store", "url", authConfig.getRegistryAddress()); assertEquals("Correct username is obtained from a credential store", "username", authConfig.getUsername()); @@ -62,7 +87,10 @@ public void lookupAuthConfigUsingStore() throws URISyntaxException { public void lookupAuthConfigUsingHelper() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-with-helper.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("registry.example.com/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("registry.example.com/org/repo"), + new AuthConfig() + ); assertEquals("Correct server URL is obtained from a credential store", "url", authConfig.getRegistryAddress()); assertEquals("Correct username is obtained from a credential store", "username", authConfig.getUsername()); @@ -73,16 +101,26 @@ public void lookupAuthConfigUsingHelper() throws URISyntaxException { public void lookupAuthConfigUsingHelperWithToken() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-with-helper-using-token.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("registrytoken.example.com/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("registrytoken.example.com/org/repo"), + new AuthConfig() + ); - assertEquals("Correct identitytoken is obtained from a credential store", "secret", authConfig.getIdentitytoken()); + assertEquals( + "Correct identitytoken is obtained from a credential store", + "secret", + authConfig.getIdentitytoken() + ); } @Test public void lookupUsingHelperEmptyAuth() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-empty-auth-with-helper.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("registry.example.com/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("registry.example.com/org/repo"), + new AuthConfig() + ); assertEquals("Correct server URL is obtained from a credential store", "url", authConfig.getRegistryAddress()); assertEquals("Correct username is obtained from a credential store", "username", authConfig.getUsername()); @@ -93,7 +131,10 @@ public void lookupUsingHelperEmptyAuth() throws URISyntaxException { public void lookupNonEmptyAuthWithHelper() throws URISyntaxException { final RegistryAuthLocator authLocator = createTestAuthLocator("config-existing-auth-with-helper.json"); - final AuthConfig authConfig = authLocator.lookupAuthConfig(DockerImageName.parse("registry.example.com/org/repo"), new AuthConfig()); + final AuthConfig authConfig = authLocator.lookupAuthConfig( + DockerImageName.parse("registry.example.com/org/repo"), + new AuthConfig() + ); assertEquals("Correct server URL is obtained from a credential helper", "url", authConfig.getRegistryAddress()); assertEquals("Correct username is obtained from a credential helper", "username", authConfig.getUsername()); @@ -103,7 +144,10 @@ public void lookupNonEmptyAuthWithHelper() throws URISyntaxException { @Test public void lookupAuthConfigWithCredentialsNotFound() throws URISyntaxException { Map notFoundMessagesReference = new HashMap<>(); - final RegistryAuthLocator authLocator = createTestAuthLocator("config-with-store.json", notFoundMessagesReference); + final RegistryAuthLocator authLocator = createTestAuthLocator( + "config-with-store.json", + notFoundMessagesReference + ); DockerImageName dockerImageName = DockerImageName.parse("registry2.example.com/org/repo"); final AuthConfig authConfig = authLocator.lookupAuthConfig(dockerImageName, new AuthConfig()); @@ -117,7 +161,8 @@ public void lookupAuthConfigWithCredentialsNotFound() throws URISyntaxException assertEquals( "Not correct message discovered", "Fake credentials not found on credentials store 'https://not.a.real.registry/url'", - discoveredMessage); + discoveredMessage + ); } @Test @@ -136,7 +181,8 @@ private RegistryAuthLocator createTestAuthLocator(String configName) throws URIS } @NotNull - private RegistryAuthLocator createTestAuthLocator(String configName, Map notFoundMessagesReference) throws URISyntaxException { + private RegistryAuthLocator createTestAuthLocator(String configName, Map notFoundMessagesReference) + throws URISyntaxException { final File configFile = new File(Resources.getResource("auth-config/" + configName).toURI()); String commandPathPrefix = configFile.getParentFile().getAbsolutePath() + "/"; diff --git a/core/src/test/java/org/testcontainers/utility/ResourceReaperTest.java b/core/src/test/java/org/testcontainers/utility/ResourceReaperTest.java index 214b465c297..60f57a28b3e 100644 --- a/core/src/test/java/org/testcontainers/utility/ResourceReaperTest.java +++ b/core/src/test/java/org/testcontainers/utility/ResourceReaperTest.java @@ -42,25 +42,27 @@ public void shouldCleanupWithJVM() { private void assertCleanup(Map labels) { DockerClient client = DockerClientFactory.instance().client(); - ConditionFactory awaitFactory = Awaitility.await().atMost(Duration.ofMinutes(1)).pollInterval(Duration.ofSeconds(1)); - - List labelValues = labels.entrySet().stream() + ConditionFactory awaitFactory = Awaitility + .await() + .atMost(Duration.ofMinutes(1)) + .pollInterval(Duration.ofSeconds(1)); + + List labelValues = labels + .entrySet() + .stream() .map(it -> it.getKey() + "=" + it.getValue()) .collect(Collectors.toList()); awaitFactory.untilAsserted(() -> { - assertThat(client.listContainersCmd().withFilter("label", labelValues).withShowAll(true).exec()) - .isEmpty(); + assertThat(client.listContainersCmd().withFilter("label", labelValues).withShowAll(true).exec()).isEmpty(); }); awaitFactory.untilAsserted(() -> { - assertThat(client.listNetworksCmd().withFilter("label", labelValues).exec()) - .isEmpty(); + assertThat(client.listNetworksCmd().withFilter("label", labelValues).exec()).isEmpty(); }); awaitFactory.untilAsserted(() -> { - assertThat(client.listVolumesCmd().withFilter("label", labelValues).exec().getVolumes()) - .isEmpty(); + assertThat(client.listVolumesCmd().withFilter("label", labelValues).exec().getVolumes()).isEmpty(); }); } @@ -81,7 +83,8 @@ private Map runProcess(Consumer processExecutor ProcessResult result = processExecutor.execute(); assertEquals(0, result.getExitValue()); - String labelsJson = Stream.of(result.outputUTF8().split("\n")) + String labelsJson = Stream + .of(result.outputUTF8().split("\n")) .filter(it -> it.startsWith(SimpleUsage.LABELS_MARKER)) .map(it -> it.substring(SimpleUsage.LABELS_MARKER.length())) .findFirst() @@ -97,7 +100,9 @@ public static class SimpleUsage { @SneakyThrows @SuppressWarnings("deprecation") public static void main(String[] args) { - System.out.println(LABELS_MARKER + new ObjectMapper().writeValueAsString(ResourceReaper.instance().getLabels())); + System.out.println( + LABELS_MARKER + new ObjectMapper().writeValueAsString(ResourceReaper.instance().getLabels()) + ); GenericContainer container = new GenericContainer<>("testcontainers/helloworld:1.1.0") .withNetwork(org.testcontainers.containers.Network.newNetwork()) diff --git a/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java b/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java index 7ca656e1eaf..56cbdb98a56 100644 --- a/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java +++ b/core/src/test/java/org/testcontainers/utility/TestcontainersConfigurationTest.java @@ -15,7 +15,9 @@ public class TestcontainersConfigurationTest { private Properties userProperties; + private Properties classpathProperties; + private Map environment; @Before @@ -117,21 +119,33 @@ public void shouldReadChecksFromEnvironment() { public void shouldReadDockerSettingsFromEnvironmentWithoutTestcontainersPrefix() { userProperties.remove("docker.foo"); environment.put("DOCKER_FOO", "some value"); - assertEquals("reads unprefixed env vars for docker. settings", "some value", newConfig().getEnvVarOrUserProperty("docker.foo", "default")); + assertEquals( + "reads unprefixed env vars for docker. settings", + "some value", + newConfig().getEnvVarOrUserProperty("docker.foo", "default") + ); } @Test public void shouldNotReadDockerSettingsFromEnvironmentWithTestcontainersPrefix() { userProperties.remove("docker.foo"); environment.put("TESTCONTAINERS_DOCKER_FOO", "some value"); - assertEquals("reads unprefixed env vars for docker. settings", "default", newConfig().getEnvVarOrUserProperty("docker.foo", "default")); + assertEquals( + "reads unprefixed env vars for docker. settings", + "default", + newConfig().getEnvVarOrUserProperty("docker.foo", "default") + ); } @Test public void shouldReadDockerSettingsFromUserProperties() { environment.remove("DOCKER_FOO"); userProperties.put("docker.foo", "some value"); - assertEquals("reads unprefixed user properties for docker. settings", "some value", newConfig().getEnvVarOrUserProperty("docker.foo", "default")); + assertEquals( + "reads unprefixed user properties for docker. settings", + "some value", + newConfig().getEnvVarOrUserProperty("docker.foo", "default") + ); } @Test @@ -139,41 +153,69 @@ public void shouldNotReadDockerClientStrategyFromClasspathProperties() { String currentValue = newConfig().getDockerClientStrategyClassName(); classpathProperties.setProperty("docker.client.strategy", UUID.randomUUID().toString()); - assertEquals("Docker client strategy is not affected by classpath properties", currentValue, newConfig().getDockerClientStrategyClassName()); + assertEquals( + "Docker client strategy is not affected by classpath properties", + currentValue, + newConfig().getDockerClientStrategyClassName() + ); } @Test public void shouldReadDockerClientStrategyFromUserProperties() { userProperties.setProperty("docker.client.strategy", "foo"); - assertEquals("Docker client strategy is changed by user property", "foo", newConfig().getDockerClientStrategyClassName()); + assertEquals( + "Docker client strategy is changed by user property", + "foo", + newConfig().getDockerClientStrategyClassName() + ); } @Test public void shouldReadDockerClientStrategyFromEnvironment() { userProperties.remove("docker.client.strategy"); environment.put("TESTCONTAINERS_DOCKER_CLIENT_STRATEGY", "foo"); - assertEquals("Docker client strategy is changed by env var", "foo", newConfig().getDockerClientStrategyClassName()); + assertEquals( + "Docker client strategy is changed by env var", + "foo", + newConfig().getDockerClientStrategyClassName() + ); } @Test public void shouldNotUseImplicitDockerClientStrategyWhenDockerHostAndStrategyAreBothSet() { userProperties.put("docker.client.strategy", "foo"); userProperties.put("docker.host", "tcp://1.2.3.4:5678"); - assertEquals("Docker client strategy is can be explicitly set", "foo", newConfig().getDockerClientStrategyClassName()); + assertEquals( + "Docker client strategy is can be explicitly set", + "foo", + newConfig().getDockerClientStrategyClassName() + ); userProperties.remove("docker.client.strategy"); environment.put("TESTCONTAINERS_DOCKER_CLIENT_STRATEGY", "bar"); userProperties.put("docker.client.strategy", "foo"); - assertEquals("Docker client strategy is can be explicitly set", "bar", newConfig().getDockerClientStrategyClassName()); + assertEquals( + "Docker client strategy is can be explicitly set", + "bar", + newConfig().getDockerClientStrategyClassName() + ); environment.put("TESTCONTAINERS_DOCKER_CLIENT_STRATEGY", "bar"); userProperties.remove("docker.client.strategy"); - assertEquals("Docker client strategy is can be explicitly set", "bar", newConfig().getDockerClientStrategyClassName()); + assertEquals( + "Docker client strategy is can be explicitly set", + "bar", + newConfig().getDockerClientStrategyClassName() + ); environment.remove("TESTCONTAINERS_DOCKER_CLIENT_STRATEGY"); userProperties.put("docker.client.strategy", "foo"); - assertEquals("Docker client strategy is can be explicitly set", "foo", newConfig().getDockerClientStrategyClassName()); + assertEquals( + "Docker client strategy is can be explicitly set", + "foo", + newConfig().getDockerClientStrategyClassName() + ); } @Test @@ -191,6 +233,7 @@ public void shouldReadReuseFromUserProperties() { userProperties.setProperty("testcontainers.reuse.enable", "true"); assertTrue("reuse enabled via user property", newConfig().environmentSupportsReuse()); } + @Test public void shouldReadReuseFromEnvironment() { assertFalse("no reuse by default", newConfig().environmentSupportsReuse()); @@ -203,7 +246,11 @@ public void shouldReadReuseFromEnvironment() { @Test public void shouldTrimImageNames() { userProperties.setProperty("ryuk.container.image", " testcontainers/ryuk:0.3.2 "); - assertEquals("trailing whitespace was not removed from image name property", "testcontainers/ryuk:0.3.2",newConfig().getRyukImage()); + assertEquals( + "trailing whitespace was not removed from image name property", + "testcontainers/ryuk:0.3.2", + newConfig().getRyukImage() + ); } private TestcontainersConfiguration newConfig() { diff --git a/docs/examples/junit4/generic/src/test/java/generic/CmdModifierTest.java b/docs/examples/junit4/generic/src/test/java/generic/CmdModifierTest.java index 5306426070f..218ed90e5e0 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/CmdModifierTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/CmdModifierTest.java @@ -19,21 +19,26 @@ public class CmdModifierTest { // hostname { @Rule public GenericContainer theCache = new GenericContainer<>(DockerImageName.parse("redis:3.0.2")) - .withCreateContainerCmdModifier(cmd -> cmd.withHostName("the-cache")); + .withCreateContainerCmdModifier(cmd -> cmd.withHostName("the-cache")); + // } + // spotless:off // memory { private long memoryInBytes = 32 * 1024 * 1024; + private long memorySwapInBytes = 64 * 1024 * 1024; @Rule public GenericContainer memoryLimitedRedis = new GenericContainer<>(DockerImageName.parse("redis:3.0.2")) - .withCreateContainerCmdModifier(cmd -> cmd.getHostConfig() + .withCreateContainerCmdModifier(cmd -> { + cmd.getHostConfig() .withMemory(memoryInBytes) - .withMemorySwap(memorySwapInBytes) - ); - // } + .withMemorySwap(memorySwapInBytes); + }); + // } + // spotless:on @Test public void testHostnameModified() throws IOException, InterruptedException { diff --git a/docs/examples/junit4/generic/src/test/java/generic/CommandsTest.java b/docs/examples/junit4/generic/src/test/java/generic/CommandsTest.java index 23b265c26fa..80292465521 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/CommandsTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/CommandsTest.java @@ -8,11 +8,12 @@ import static org.junit.Assert.assertTrue; public class CommandsTest { + @Rule // startupCommand { public GenericContainer redisWithCustomPort = new GenericContainer(DockerImageName.parse("redis:5.0")) .withCommand("redis-server --port 7777") - // } + // } .withExposedPorts(7777); @Test diff --git a/docs/examples/junit4/generic/src/test/java/generic/ContainerCreationTest.java b/docs/examples/junit4/generic/src/test/java/generic/ContainerCreationTest.java index 83b45f0435d..bdd82968191 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/ContainerCreationTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/ContainerCreationTest.java @@ -9,31 +9,33 @@ public class ContainerCreationTest { + // spotless:off // simple { public static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis:3.0.2"); - // } - // simple { @ClassRule - public static GenericContainer redis = - new GenericContainer<>(REDIS_IMAGE) - .withExposedPorts(6379); + public static GenericContainer redis = new GenericContainer<>(REDIS_IMAGE) + .withExposedPorts(6379); + // } + // spotless:on public static final DockerImageName ALPINE_IMAGE = DockerImageName.parse("alpine:3.14"); + // spotless:off // withOptions { // Set up a plain OS container and customize environment, // command and exposed ports. This just listens on port 80 // and always returns '42' @ClassRule - public static GenericContainer alpine = - new GenericContainer<>(ALPINE_IMAGE) - .withExposedPorts(80) - .withEnv("MAGIC_NUMBER", "42") - .withCommand("/bin/sh", "-c", - "while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"); + public static GenericContainer alpine = new GenericContainer<>(ALPINE_IMAGE) + .withExposedPorts(80) + .withEnv("MAGIC_NUMBER", "42") + .withCommand("/bin/sh", "-c", + "while true; do echo \"$MAGIC_NUMBER\" | nc -l -p 80; done"); + // } + // spotless:on @Test public void testStartup() { diff --git a/docs/examples/junit4/generic/src/test/java/generic/ContainerLabelTest.java b/docs/examples/junit4/generic/src/test/java/generic/ContainerLabelTest.java index 08d57e31057..64618ad25a9 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/ContainerLabelTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/ContainerLabelTest.java @@ -7,12 +7,12 @@ import java.util.Map; public class ContainerLabelTest { + // single_label { public GenericContainer containerWithLabel = new GenericContainer(DockerImageName.parse("alpine:3.14")) .withLabel("key", "value"); // } - // multiple_labels { private Map mapOfLabels = new HashMap<>(); // populate map, e.g. mapOfLabels.put("key1", "value1"); diff --git a/docs/examples/junit4/generic/src/test/java/generic/HostPortExposedTest.java b/docs/examples/junit4/generic/src/test/java/generic/HostPortExposedTest.java index 1d15c2553b8..22bf0332a9d 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/HostPortExposedTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/HostPortExposedTest.java @@ -18,19 +18,23 @@ public class HostPortExposedTest { private static HttpServer server; + private static int localServerPort; @BeforeClass public static void setUp() throws Exception { server = HttpServer.create(new InetSocketAddress(0), 0); - server.createContext("/", exchange -> { - byte[] content = "Hello World!".getBytes(); - exchange.sendResponseHeaders(200, content.length); - try (OutputStream responseBody = exchange.getResponseBody()) { - responseBody.write(content); - responseBody.flush(); + server.createContext( + "/", + exchange -> { + byte[] content = "Hello World!".getBytes(); + exchange.sendResponseHeaders(200, content.length); + try (OutputStream responseBody = exchange.getResponseBody()) { + responseBody.write(content); + responseBody.flush(); + } } - }); + ); server.start(); localServerPort = server.getAddress().getPort(); @@ -46,14 +50,12 @@ public static void tearDown() throws Exception { } @Rule - public BrowserWebDriverContainer browser = new BrowserWebDriverContainer() - .withCapabilities(new ChromeOptions()); + public BrowserWebDriverContainer browser = new BrowserWebDriverContainer().withCapabilities(new ChromeOptions()); @Test public void testContainerRunningAgainstExposedHostPort() { // useHostExposedPort { - final String rootUrl = - String.format("http://host.testcontainers.internal:%d/", localServerPort); + final String rootUrl = String.format("http://host.testcontainers.internal:%d/", localServerPort); final RemoteWebDriver webDriver = browser.getWebDriver(); webDriver.get(rootUrl); diff --git a/docs/examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java b/docs/examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java index 65da67fd401..afbe38fe835 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/ImageNameSubstitutionTest.java @@ -1,6 +1,5 @@ package generic; - import generic.support.TestSpecificImageNameSubstitutor; import org.junit.Test; import org.testcontainers.containers.MySQLContainer; @@ -11,14 +10,15 @@ public class ImageNameSubstitutionTest { @Test public void simpleExample() { try ( + // spotless:off // directDockerHubReference { // Referring directly to an image on Docker Hub (mysql:8.0.24) final MySQLContainer mysql = new MySQLContainer<>( DockerImageName.parse("mysql:8.0.24") ) - // start the container and use it for testing // } + // spotless:on ) { mysql.start(); } @@ -32,15 +32,16 @@ public void simpleExample() { @Test public void substitutedExample() { try ( + // spotless:off // hardcodedMirror { // Referring directly to an image on a private registry - image name will vary final MySQLContainer mysql = new MySQLContainer<>( DockerImageName.parse("registry.mycompany.com/mirror/mysql:8.0.24") - .asCompatibleSubstituteFor("mysql") + .asCompatibleSubstituteFor("mysql") ) - // start the container and use it for testing // } + // spotless:on ) { mysql.start(); } diff --git a/docs/examples/junit4/generic/src/test/java/generic/MultiplePortsExposedTest.java b/docs/examples/junit4/generic/src/test/java/generic/MultiplePortsExposedTest.java index de2b56c6a63..49e62cff217 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/MultiplePortsExposedTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/MultiplePortsExposedTest.java @@ -1,23 +1,25 @@ package generic; -import static org.slf4j.LoggerFactory.getLogger; - import org.junit.Rule; import org.junit.Test; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.utility.DockerImageName; public class MultiplePortsExposedTest { - private static final Logger log = getLogger(MultiplePortsExposedTest.class); + private static final Logger log = LoggerFactory.getLogger(MultiplePortsExposedTest.class); @Rule // rule { - public GenericContainer container = new GenericContainer<>(DockerImageName.parse("testcontainers/helloworld:1.1.0")) + public GenericContainer container = new GenericContainer<>( + DockerImageName.parse("testcontainers/helloworld:1.1.0") + ) .withExposedPorts(8080, 8081) .withLogConsumer(new Slf4jLogConsumer(log)); + // } @Test @@ -38,7 +40,6 @@ public void getHostOnly() { @Test public void getHostAndMappedPort() { - String address = - container.getHost() + ":" + container.getMappedPort(8080); + String address = container.getHost() + ":" + container.getMappedPort(8080); } } diff --git a/docs/examples/junit4/generic/src/test/java/generic/WaitStrategiesTest.java b/docs/examples/junit4/generic/src/test/java/generic/WaitStrategiesTest.java index d45b1e28c47..bdc0d3ced8a 100644 --- a/docs/examples/junit4/generic/src/test/java/generic/WaitStrategiesTest.java +++ b/docs/examples/junit4/generic/src/test/java/generic/WaitStrategiesTest.java @@ -14,8 +14,9 @@ public class WaitStrategiesTest { @Rule // waitForNetworkListening { - public GenericContainer nginx = new GenericContainer(DockerImageName.parse("nginx:1.9.4")) + public GenericContainer nginx = new GenericContainer(DockerImageName.parse("nginx:1.9.4")) // .withExposedPorts(80); + // } @Rule @@ -23,44 +24,48 @@ public class WaitStrategiesTest { public GenericContainer nginxWithHttpWait = new GenericContainer(DockerImageName.parse("nginx:1.9.4")) .withExposedPorts(80) .waitingFor(Wait.forHttp("/")); + // } @Rule // logMessageWait { public GenericContainer containerWithLogWait = new GenericContainer(DockerImageName.parse("redis:5.0.3")) .withExposedPorts(6379) - .waitingFor( - Wait.forLogMessage(".*Ready to accept connections.*\\n", 1) - ); + .waitingFor(Wait.forLogMessage(".*Ready to accept connections.*\\n", 1)); + // } private static final HttpWaitStrategy MULTI_CODE_HTTP_WAIT = + // spotless:off // waitForHttpWithMultipleStatusCodes { Wait.forHttp("/") .forStatusCode(200) - .forStatusCode(301) + .forStatusCode(301); // } - ; + // spotless:on private static final HttpWaitStrategy PREDICATE_HTTP_WAIT = + // spotless:off // waitForHttpWithStatusCodePredicate { Wait.forHttp("/all") - .forStatusCodeMatching(it -> it >= 200 && it < 300 || it == 401) + .forStatusCodeMatching(it -> it >= 200 && it < 300 || it == 401); // } - ; + // spotless:on private static final HttpWaitStrategy TLS_HTTP_WAIT = + // spotless:off // waitForHttpWithTls { Wait.forHttp("/all") - .usingTls() + .usingTls(); // } - ; + // spotless:on private static final WaitStrategy HEALTHCHECK_WAIT = + // spotless:off // healthcheckWait { - Wait.forHealthcheck() + Wait.forHealthcheck(); // } - ; + // spotless:on @Test public void testContainersAllStarted() { diff --git a/docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java b/docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java index b60225010a1..82e3d83ab24 100644 --- a/docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java +++ b/docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java @@ -6,6 +6,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.OutputFrame; import org.testcontainers.containers.output.WaitingConsumer; import org.testcontainers.utility.DockerImageName; @@ -14,34 +15,39 @@ import java.util.concurrent.TimeoutException; import static org.assertj.core.api.Assertions.assertThat; -import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; -import static org.testcontainers.containers.startupcheck.StartupCheckStrategyTest.IndefiniteOneShotStrategyTest; -import static org.testcontainers.containers.startupcheck.StartupCheckStrategyTest.MinimumDurationStrategyTest; -import static org.testcontainers.containers.startupcheck.StartupCheckStrategyTest.OneShotStrategyTest; @RunWith(Suite.class) -@Suite.SuiteClasses({OneShotStrategyTest.class, IndefiniteOneShotStrategyTest.class, MinimumDurationStrategyTest.class}) +@Suite.SuiteClasses( + { + StartupCheckStrategyTest.OneShotStrategyTest.class, + StartupCheckStrategyTest.IndefiniteOneShotStrategyTest.class, + StartupCheckStrategyTest.MinimumDurationStrategyTest.class, + } +) public class StartupCheckStrategyTest { private static final String HELLO_TESTCONTAINERS = "Hello Testcontainers!"; private static void waitForHello(GenericContainer container) throws TimeoutException { WaitingConsumer consumer = new WaitingConsumer(); - container.followOutput(consumer, STDOUT); + container.followOutput(consumer, OutputFrame.OutputType.STDOUT); - consumer.waitUntil(frame -> - frame.getUtf8String().contains(HELLO_TESTCONTAINERS), 30, TimeUnit.SECONDS); + consumer.waitUntil(frame -> frame.getUtf8String().contains(HELLO_TESTCONTAINERS), 30, TimeUnit.SECONDS); } public static class OneShotStrategyTest { + @Rule + // spotless:off // withOneShotStrategy { public GenericContainer bboxWithOneShot = new GenericContainer<>(DockerImageName.parse("busybox:1.31.1")) .withCommand(String.format("echo %s", HELLO_TESTCONTAINERS)) .withStartupCheckStrategy( new OneShotStartupCheckStrategy().withTimeout(Duration.ofSeconds(3)) ); + // } + // spotless:on @SneakyThrows @Test @@ -53,14 +59,20 @@ public void testCommandIsExecuted() { } public static class IndefiniteOneShotStrategyTest { + @Rule + // spotless:off // withIndefiniteOneShotStrategy { - public GenericContainer bboxWithIndefiniteOneShot = new GenericContainer<>(DockerImageName.parse("busybox:1.31.1")) + public GenericContainer bboxWithIndefiniteOneShot = new GenericContainer<>( + DockerImageName.parse("busybox:1.31.1") + ) .withCommand("sh", "-c", String.format("sleep 5 && echo \"%s\"", HELLO_TESTCONTAINERS)) .withStartupCheckStrategy( new IndefiniteWaitOneShotStartupCheckStrategy() ); + // } + // spotless:on @SneakyThrows @Test @@ -72,14 +84,20 @@ public void testCommandIsExecuted() { } public static class MinimumDurationStrategyTest { + @Rule + // spotless:off // withMinimumDurationStrategy { - public GenericContainer bboxWithMinimumDuration = new GenericContainer<>(DockerImageName.parse("busybox:1.31.1")) + public GenericContainer bboxWithMinimumDuration = new GenericContainer<>( + DockerImageName.parse("busybox:1.31.1") + ) .withCommand("sh", "-c", String.format("sleep 5 && echo \"%s\"", HELLO_TESTCONTAINERS)) .withStartupCheckStrategy( new MinimumDurationRunningStartupCheckStrategy(Duration.ofSeconds(1)) ); + // } + // spotless:on @SneakyThrows @Test diff --git a/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java b/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java index cbb49b5fdb3..1d3d178975f 100644 --- a/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java +++ b/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java @@ -1,6 +1,5 @@ package quickstart; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -16,9 +15,9 @@ public class RedisBackedCacheIntTest { // rule { @Rule public GenericContainer redis = new GenericContainer(DockerImageName.parse("redis:5.0.3-alpine")) - .withExposedPorts(6379); - // } + .withExposedPorts(6379); + // } @Before public void setUp() { diff --git a/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java b/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java index 61a86ac3f8b..f837b3af0d5 100644 --- a/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java +++ b/docs/examples/junit4/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java @@ -1,6 +1,5 @@ package quickstart; - import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -9,6 +8,7 @@ @Ignore("This test class is deliberately invalid, as it relies on a non-existent local Redis") public class RedisBackedCacheIntTestStep0 { + private RedisBackedCache underTest; @Before diff --git a/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java b/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java index 9a3855ba23c..59d92210549 100644 --- a/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java +++ b/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTest.java @@ -1,6 +1,5 @@ package quickstart; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.testcontainers.containers.GenericContainer; @@ -19,9 +18,9 @@ public class RedisBackedCacheIntTest { // container { @Container public GenericContainer redis = new GenericContainer(DockerImageName.parse("redis:5.0.3-alpine")) - .withExposedPorts(6379); - // } + .withExposedPorts(6379); + // } @BeforeEach public void setUp() { diff --git a/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java b/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java index c81a185a188..d9f889a8943 100644 --- a/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java +++ b/docs/examples/junit5/redis/src/test/java/quickstart/RedisBackedCacheIntTestStep0.java @@ -1,6 +1,5 @@ package quickstart; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -9,6 +8,7 @@ @Disabled("This test class is deliberately invalid, as it relies on a non-existent local Redis") public class RedisBackedCacheIntTestStep0 { + private RedisBackedCache underTest; @BeforeEach diff --git a/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTest.groovy b/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTest.groovy index 068c8079a7d..5cc04dc6b9d 100644 --- a/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTest.groovy +++ b/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTest.groovy @@ -7,30 +7,30 @@ import spock.lang.Specification @org.testcontainers.spock.Testcontainers class RedisBackedCacheIntTest extends Specification { - private RedisBackedCache underTest + private RedisBackedCache underTest - // init { - GenericContainer redis = new GenericContainer<>("redis:5.0.3-alpine") - .withExposedPorts(6379) - // } + // init { + GenericContainer redis = new GenericContainer<>("redis:5.0.3-alpine") + .withExposedPorts(6379) + // } - void setup() { - String address = redis.host - Integer port = redis.firstMappedPort + void setup() { + String address = redis.host + Integer port = redis.firstMappedPort - // Now we have an address and port for Redis, no matter where it is running - underTest = new RedisBackedCache(address, port) - } + // Now we have an address and port for Redis, no matter where it is running + underTest = new RedisBackedCache(address, port) + } - void testSimplePutAndGet() { - setup: - underTest.put("test", "example") + void testSimplePutAndGet() { + setup: + underTest.put("test", "example") - when: - String retrieved = underTest.get("test") + when: + String retrieved = underTest.get("test") - then: - retrieved == "example" - } + then: + retrieved == "example" + } } // } diff --git a/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTestStep0.groovy b/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTestStep0.groovy index 52897c30097..d28942420da 100644 --- a/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTestStep0.groovy +++ b/docs/examples/spock/redis/src/test/groovy/quickstart/RedisBackedCacheIntTestStep0.groovy @@ -5,21 +5,21 @@ import spock.lang.Specification @Ignore("This test class is deliberately invalid, as it relies on a non-existent local Redis") class RedisBackedCacheIntTestStep0 extends Specification { - private RedisBackedCache underTest + private RedisBackedCache underTest - void setup() { - // Assume that we have Redis running locally? - underTest = new RedisBackedCache("localhost", 6379) - } + void setup() { + // Assume that we have Redis running locally? + underTest = new RedisBackedCache("localhost", 6379) + } - void testSimplePutAndGet() { - setup: - underTest.put("test", "example") + void testSimplePutAndGet() { + setup: + underTest.put("test", "example") - when: - String retrieved = underTest.get("test") + when: + String retrieved = underTest.get("test") - then: - retrieved == "example" - } + then: + retrieved == "example" + } } diff --git a/docs/modules/hivemq.md b/docs/modules/hivemq.md index 1e09bac4fc0..66f9670648c 100644 --- a/docs/modules/hivemq.md +++ b/docs/modules/hivemq.md @@ -31,7 +31,7 @@ Using the Community Edition: Using the Enterprise Edition: -[Enterprise Edition HiveMQ image](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:eeVersion +[Enterprise Edition HiveMQ image](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:hiveEEVersion Using a specifc version is possible by using the tag: @@ -138,7 +138,7 @@ The following example shows how to start a HiveMQ container with the extension c The following test then proceeds to enable and then disable the extension: -[Enable/Disable extension at runtime](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:runtimeEnable +[Enable/Disable extension at runtime](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:hiveRuntimeEnable ## Enable/Disable an extension loaded from a folder diff --git a/modules/azure/src/main/java/org/testcontainers/containers/CosmosDBEmulatorContainer.java b/modules/azure/src/main/java/org/testcontainers/containers/CosmosDBEmulatorContainer.java index 9328d881666..57af95ef106 100644 --- a/modules/azure/src/main/java/org/testcontainers/containers/CosmosDBEmulatorContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/containers/CosmosDBEmulatorContainer.java @@ -10,8 +10,9 @@ */ public class CosmosDBEmulatorContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = - DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator" + ); private static final int PORT = 8081; diff --git a/modules/azure/src/main/java/org/testcontainers/containers/KeyStoreBuilder.java b/modules/azure/src/main/java/org/testcontainers/containers/KeyStoreBuilder.java index 0179e8d832a..f7b6af370ac 100644 --- a/modules/azure/src/main/java/org/testcontainers/containers/KeyStoreBuilder.java +++ b/modules/azure/src/main/java/org/testcontainers/containers/KeyStoreBuilder.java @@ -5,10 +5,6 @@ import okhttp3.Request; import okhttp3.Response; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; import java.io.InputStream; import java.security.KeyStore; import java.security.SecureRandom; @@ -17,6 +13,11 @@ import java.security.cert.X509Certificate; import java.util.Objects; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + final class KeyStoreBuilder { static KeyStore buildByDownloadingCertificate(String endpoint, String keyStorePassword) { @@ -38,20 +39,18 @@ static KeyStore buildByDownloadingCertificate(String endpoint, String keyStorePa private static TrustManager[] buildTrustAllManagers() { return new TrustManager[] { - new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - } + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) {} - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - } + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) {} - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[]{}; - } + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[] {}; } + }, }; } @@ -60,16 +59,13 @@ private static OkHttpClient buildTrustAllClient(TrustManager[] trustManagers) th sslContext.init(null, trustManagers, new SecureRandom()); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); return new OkHttpClient.Builder() - .sslSocketFactory(socketFactory, (X509TrustManager) trustManagers[0]) - .hostnameVerifier((s, sslSession) -> true) - .build(); + .sslSocketFactory(socketFactory, (X509TrustManager) trustManagers[0]) + .hostnameVerifier((s, sslSession) -> true) + .build(); } private static Request buildRequest(String endpoint) { - return new Request.Builder() - .get() - .url(endpoint + "/_explorer/emulator.pem") - .build(); + return new Request.Builder().get().url(endpoint + "/_explorer/emulator.pem").build(); } private static KeyStore buildKeyStore(InputStream certificateStream, String keyStorePassword) throws Exception { @@ -85,8 +81,7 @@ private static void closeResponseSilently(Response response) { if (Objects.nonNull(response)) { response.close(); } - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } private static void closeClientSilently(OkHttpClient client) { @@ -99,7 +94,6 @@ private static void closeClientSilently(OkHttpClient client) { cache.close(); } } - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } } diff --git a/modules/azure/src/test/java/org/testcontainers/containers/CosmosDBEmulatorContainerTest.java b/modules/azure/src/test/java/org/testcontainers/containers/CosmosDBEmulatorContainerTest.java index dd9dc6b718f..37422b30af7 100644 --- a/modules/azure/src/test/java/org/testcontainers/containers/CosmosDBEmulatorContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/containers/CosmosDBEmulatorContainerTest.java @@ -37,8 +37,9 @@ public static void restoreOriginalSystemProperties() { @Rule // emulatorContainer { public CosmosDBEmulatorContainer emulator = new CosmosDBEmulatorContainer( - DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest") + DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest") ); + // } @Test @@ -55,18 +56,19 @@ public void testWithCosmosClient() throws Exception { // } // buildClient { CosmosAsyncClient client = new CosmosClientBuilder() - .gatewayMode() - .endpointDiscoveryEnabled(false) - .endpoint(emulator.getEmulatorEndpoint()) - .key(emulator.getEmulatorKey()) - .buildAsyncClient(); + .gatewayMode() + .endpointDiscoveryEnabled(false) + .endpoint(emulator.getEmulatorEndpoint()) + .key(emulator.getEmulatorKey()) + .buildAsyncClient(); // } // testWithClientAgainstEmulatorContainer { - CosmosDatabaseResponse databaseResponse = - client.createDatabaseIfNotExists("Azure").block(); + CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists("Azure").block(); Assertions.assertThat(databaseResponse.getStatusCode()).isEqualTo(201); - CosmosContainerResponse containerResponse = - client.getDatabase("Azure").createContainerIfNotExists("ServiceContainer", "/name").block(); + CosmosContainerResponse containerResponse = client + .getDatabase("Azure") + .createContainerIfNotExists("ServiceContainer", "/name") + .block(); Assertions.assertThat(containerResponse.getStatusCode()).isEqualTo(201); // } } diff --git a/modules/cassandra/src/main/java/org/testcontainers/containers/CassandraContainer.java b/modules/cassandra/src/main/java/org/testcontainers/containers/CassandraContainer.java index e3ae084cb8a..3c78743fb62 100644 --- a/modules/cassandra/src/main/java/org/testcontainers/containers/CassandraContainer.java +++ b/modules/cassandra/src/main/java/org/testcontainers/containers/CassandraContainer.java @@ -10,12 +10,13 @@ import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.MountableFile; -import javax.script.ScriptException; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.Optional; +import javax.script.ScriptException; + /** * Cassandra container * @@ -26,18 +27,24 @@ public class CassandraContainer> extends GenericContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("cassandra"); + private static final String DEFAULT_TAG = "3.11.2"; @Deprecated public static final String IMAGE = DEFAULT_IMAGE_NAME.getUnversionedPart(); public static final Integer CQL_PORT = 9042; + private static final String CONTAINER_CONFIG_LOCATION = "/etc/cassandra"; + private static final String USERNAME = "cassandra"; + private static final String PASSWORD = "cassandra"; private String configLocation; + private String initScriptPath; + private boolean enableJmxReporting; /** @@ -54,17 +61,13 @@ public CassandraContainer(String dockerImageName) { public CassandraContainer(DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); addExposedPort(CQL_PORT); this.enableJmxReporting = false; withEnv("CASSANDRA_SNITCH", "GossipingPropertyFileSnitch"); - withEnv( - "JVM_OPTS", - "-Dcassandra.skip_wait_for_gossip_to_settle=0 -Dcassandra.initial_token=0" - ); + withEnv("JVM_OPTS", "-Dcassandra.skip_wait_for_gossip_to_settle=0 -Dcassandra.initial_token=0"); withEnv("HEAP_NEWSIZE", "128M"); withEnv("MAX_HEAP_SIZE", "1024M"); } @@ -88,7 +91,9 @@ private void runInitScriptIfRequired() { URL resource = Thread.currentThread().getContextClassLoader().getResource(initScriptPath); if (resource == null) { logger().warn("Could not load classpath init script: {}", initScriptPath); - throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath + ". Resource not found."); + throw new ScriptLoadException( + "Could not load classpath init script: " + initScriptPath + ". Resource not found." + ); } String cql = IOUtils.toString(resource, StandardCharsets.UTF_8); DatabaseDelegate databaseDelegate = getDatabaseDelegate(); @@ -98,7 +103,10 @@ private void runInitScriptIfRequired() { throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath, e); } catch (ScriptException e) { logger().error("Error while executing init script: {}", initScriptPath, e); - throw new ScriptUtils.UncategorizedScriptException("Error while executing init script: " + initScriptPath, e); + throw new ScriptUtils.UncategorizedScriptException( + "Error while executing init script: " + initScriptPath, + e + ); } } } @@ -112,9 +120,10 @@ private void runInitScriptIfRequired() { * @param resourceLocation relative classpath to resource */ protected void optionallyMapResourceParameterAsVolume(String pathNameInContainer, String resourceLocation) { - Optional.ofNullable(resourceLocation) - .map(MountableFile::forClasspathResource) - .ifPresent(mountableFile -> withCopyFileToContainer(mountableFile, pathNameInContainer)); + Optional + .ofNullable(resourceLocation) + .map(MountableFile::forClasspathResource) + .ifPresent(mountableFile -> withCopyFileToContainer(mountableFile, pathNameInContainer)); } /** @@ -184,7 +193,8 @@ public Cluster getCluster() { } public static Cluster getCluster(ContainerState containerState, boolean enableJmxReporting) { - final Cluster.Builder builder = Cluster.builder() + final Cluster.Builder builder = Cluster + .builder() .addContactPoint(containerState.getHost()) .withPort(containerState.getMappedPort(CQL_PORT)); if (!enableJmxReporting) { diff --git a/modules/cassandra/src/main/java/org/testcontainers/containers/delegate/CassandraDatabaseDelegate.java b/modules/cassandra/src/main/java/org/testcontainers/containers/delegate/CassandraDatabaseDelegate.java index e55dd31b0ff..8bc72e7f154 100644 --- a/modules/cassandra/src/main/java/org/testcontainers/containers/delegate/CassandraDatabaseDelegate.java +++ b/modules/cassandra/src/main/java/org/testcontainers/containers/delegate/CassandraDatabaseDelegate.java @@ -25,8 +25,7 @@ public class CassandraDatabaseDelegate extends AbstractDatabaseDelegate @Override protected Session createNewConnection() { try { - return CassandraContainer.getCluster(container) - .newSession(); + return CassandraContainer.getCluster(container).newSession(); } catch (DriverException e) { log.error("Could not obtain cassandra connection"); throw new ConnectionCreationException("Could not obtain cassandra connection", e); @@ -34,7 +33,13 @@ protected Session createNewConnection() { } @Override - public void execute(String statement, String scriptPath, int lineNumber, boolean continueOnError, boolean ignoreFailedDrops) { + public void execute( + String statement, + String scriptPath, + int lineNumber, + boolean continueOnError, + boolean ignoreFailedDrops + ) { try { ResultSet result = getConnection().execute(statement); if (result.wasApplied()) { diff --git a/modules/cassandra/src/main/java/org/testcontainers/containers/wait/CassandraQueryWaitStrategy.java b/modules/cassandra/src/main/java/org/testcontainers/containers/wait/CassandraQueryWaitStrategy.java index cf7f3769985..aa2466cf7c4 100644 --- a/modules/cassandra/src/main/java/org/testcontainers/containers/wait/CassandraQueryWaitStrategy.java +++ b/modules/cassandra/src/main/java/org/testcontainers/containers/wait/CassandraQueryWaitStrategy.java @@ -18,20 +18,26 @@ public class CassandraQueryWaitStrategy extends AbstractWaitStrategy { private static final String SELECT_VERSION_QUERY = "SELECT release_version FROM system.local"; + private static final String TIMEOUT_ERROR = "Timed out waiting for Cassandra to be accessible for query execution"; @Override protected void waitUntilReady() { // execute select version query until success or timeout try { - retryUntilSuccess((int) startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> { - getRateLimiter().doWhenReady(() -> { - try (DatabaseDelegate databaseDelegate = getDatabaseDelegate()) { - databaseDelegate.execute(SELECT_VERSION_QUERY, "", 1, false, false); - } - }); - return true; - }); + retryUntilSuccess( + (int) startupTimeout.getSeconds(), + TimeUnit.SECONDS, + () -> { + getRateLimiter() + .doWhenReady(() -> { + try (DatabaseDelegate databaseDelegate = getDatabaseDelegate()) { + databaseDelegate.execute(SELECT_VERSION_QUERY, "", 1, false, false); + } + }); + return true; + } + ); } catch (TimeoutException e) { throw new ContainerLaunchException(TIMEOUT_ERROR); } diff --git a/modules/cassandra/src/test/java/org/testcontainers/containers/CassandraContainerTest.java b/modules/cassandra/src/test/java/org/testcontainers/containers/CassandraContainerTest.java index 76c8c8438d7..45cbba0abc7 100644 --- a/modules/cassandra/src/test/java/org/testcontainers/containers/CassandraContainerTest.java +++ b/modules/cassandra/src/test/java/org/testcontainers/containers/CassandraContainerTest.java @@ -36,7 +36,11 @@ public void testSimple() { @Test public void testSpecificVersion() { String cassandraVersion = "3.0.15"; - try (CassandraContainer cassandraContainer = new CassandraContainer<>(CASSANDRA_IMAGE.withTag(cassandraVersion))) { + try ( + CassandraContainer cassandraContainer = new CassandraContainer<>( + CASSANDRA_IMAGE.withTag(cassandraVersion) + ) + ) { cassandraContainer.start(); ResultSet resultSet = performQuery(cassandraContainer, "SELECT release_version FROM system.local"); assertTrue("Query was not applied", resultSet.wasApplied()); @@ -53,7 +57,11 @@ public void testConfigurationOverride() { cassandraContainer.start(); ResultSet resultSet = performQuery(cassandraContainer, "SELECT cluster_name FROM system.local"); assertTrue("Query was not applied", resultSet.wasApplied()); - assertEquals("Cassandra configuration is not overridden", TEST_CLUSTER_NAME_IN_CONF, resultSet.one().getString(0)); + assertEquals( + "Cassandra configuration is not overridden", + TEST_CLUSTER_NAME_IN_CONF, + resultSet.one().getString(0) + ); } } @@ -81,7 +89,9 @@ public void testInitScript() { @Test public void testInitScriptWithLegacyCassandra() { try ( - CassandraContainer cassandraContainer = new CassandraContainer<>(DockerImageName.parse("cassandra:2.2.11")) + CassandraContainer cassandraContainer = new CassandraContainer<>( + DockerImageName.parse("cassandra:2.2.11") + ) .withInitScript("initial.cql") ) { cassandraContainer.start(); @@ -107,7 +117,10 @@ public void testCassandraQueryWaitStrategy() { public void testCassandraGetCluster() { try (CassandraContainer cassandraContainer = new CassandraContainer<>()) { cassandraContainer.start(); - ResultSet resultSet = performQuery(cassandraContainer.getCluster(), "SELECT release_version FROM system.local"); + ResultSet resultSet = performQuery( + cassandraContainer.getCluster(), + "SELECT release_version FROM system.local" + ); assertTrue("Query was not applied", resultSet.wasApplied()); assertNotNull("Result set has no release_version", resultSet.one().getString(0)); } @@ -122,7 +135,8 @@ private void testInitScript(CassandraContainer cassandraContainer) { } private ResultSet performQuery(CassandraContainer cassandraContainer, String cql) { - Cluster explicitCluster = Cluster.builder() + Cluster explicitCluster = Cluster + .builder() .addContactPoint(cassandraContainer.getHost()) .withPort(cassandraContainer.getMappedPort(CassandraContainer.CQL_PORT)) .build(); diff --git a/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseContainer.java b/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseContainer.java index 9b5f130a323..4528c48e935 100644 --- a/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseContainer.java +++ b/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseContainer.java @@ -8,6 +8,7 @@ import java.util.Set; public class ClickHouseContainer extends JdbcDatabaseContainer { + public static final String NAME = "clickhouse"; private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("yandex/clickhouse-server"); @@ -19,14 +20,19 @@ public class ClickHouseContainer extends JdbcDatabaseContainer { public static final String DEFAULT_TAG = "18.10.3"; public static final Integer HTTP_PORT = 8123; + public static final Integer NATIVE_PORT = 9000; private static final String DRIVER_CLASS_NAME = "ru.yandex.clickhouse.ClickHouseDriver"; + private static final String JDBC_URL_PREFIX = "jdbc:" + NAME + "://"; + private static final String TEST_QUERY = "SELECT 1"; private String databaseName = "default"; + private String username = "default"; + private String password = ""; /** @@ -43,7 +49,6 @@ public ClickHouseContainer(String dockerImageName) { public ClickHouseContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(HTTP_PORT, NATIVE_PORT); diff --git a/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseProvider.java b/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseProvider.java index cd2453b8349..80fb71bd5da 100644 --- a/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseProvider.java +++ b/modules/clickhouse/src/main/java/org/testcontainers/containers/ClickHouseProvider.java @@ -3,6 +3,7 @@ import org.testcontainers.utility.DockerImageName; public class ClickHouseProvider extends JdbcDatabaseContainerProvider { + @Override public boolean supports(String databaseType) { return databaseType.equals(ClickHouseContainer.NAME); diff --git a/modules/clickhouse/src/test/java/org/testcontainers/jdbc/clickhouse/ClickhouseJDBCDriverTest.java b/modules/clickhouse/src/test/java/org/testcontainers/jdbc/clickhouse/ClickhouseJDBCDriverTest.java index f3946c8a317..056aace7772 100644 --- a/modules/clickhouse/src/test/java/org/testcontainers/jdbc/clickhouse/ClickhouseJDBCDriverTest.java +++ b/modules/clickhouse/src/test/java/org/testcontainers/jdbc/clickhouse/ClickhouseJDBCDriverTest.java @@ -4,18 +4,18 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class ClickhouseJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:clickhouse://hostname/databasename", EnumSet.of(Options.PmdKnownBroken)}, - }); + return Arrays.asList( + new Object[][] { // + { "jdbc:tc:clickhouse://hostname/databasename", EnumSet.of(Options.PmdKnownBroken) }, + } + ); } } diff --git a/modules/clickhouse/src/test/java/org/testcontainers/junit/clickhouse/SimpleClickhouseTest.java b/modules/clickhouse/src/test/java/org/testcontainers/junit/clickhouse/SimpleClickhouseTest.java index 8f3879673a0..d2375891f8c 100644 --- a/modules/clickhouse/src/test/java/org/testcontainers/junit/clickhouse/SimpleClickhouseTest.java +++ b/modules/clickhouse/src/test/java/org/testcontainers/junit/clickhouse/SimpleClickhouseTest.java @@ -1,6 +1,7 @@ package org.testcontainers.junit.clickhouse; import org.junit.Test; +import org.testcontainers.ClickhouseTestImages; import org.testcontainers.containers.ClickHouseContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; @@ -8,13 +9,12 @@ import java.sql.SQLException; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.ClickhouseTestImages.CLICKHOUSE_IMAGE; public class SimpleClickhouseTest extends AbstractContainerDatabaseTest { @Test public void testSimple() throws SQLException { - try (ClickHouseContainer clickhouse = new ClickHouseContainer(CLICKHOUSE_IMAGE)) { + try (ClickHouseContainer clickhouse = new ClickHouseContainer(ClickhouseTestImages.CLICKHOUSE_IMAGE)) { clickhouse.start(); ResultSet resultSet = performQuery(clickhouse, "SELECT 1"); diff --git a/modules/cockroachdb/src/main/java/org/testcontainers/containers/CockroachContainer.java b/modules/cockroachdb/src/main/java/org/testcontainers/containers/CockroachContainer.java index f32e6bce385..dfec3988f15 100644 --- a/modules/cockroachdb/src/main/java/org/testcontainers/containers/CockroachContainer.java +++ b/modules/cockroachdb/src/main/java/org/testcontainers/containers/CockroachContainer.java @@ -8,6 +8,7 @@ public class CockroachContainer extends JdbcDatabaseContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("cockroachdb/cockroach"); + private static final String DEFAULT_TAG = "v19.2.11"; public static final String NAME = "cockroach"; @@ -19,13 +20,19 @@ public class CockroachContainer extends JdbcDatabaseContainer data() { - return asList( - new Object[][]{ - {"jdbc:tc:cockroach://hostname/databasename", EnumSet.noneOf(Options.class)}, - }); + return Arrays.asList( + new Object[][] { // + { "jdbc:tc:cockroach://hostname/databasename", EnumSet.noneOf(Options.class) }, + } + ); } } diff --git a/modules/cockroachdb/src/test/java/org/testcontainers/junit/cockroachdb/SimpleCockroachDBTest.java b/modules/cockroachdb/src/test/java/org/testcontainers/junit/cockroachdb/SimpleCockroachDBTest.java index 3121ad82100..87e82fb30e3 100644 --- a/modules/cockroachdb/src/test/java/org/testcontainers/junit/cockroachdb/SimpleCockroachDBTest.java +++ b/modules/cockroachdb/src/test/java/org/testcontainers/junit/cockroachdb/SimpleCockroachDBTest.java @@ -1,6 +1,7 @@ package org.testcontainers.junit.cockroachdb; import org.junit.Test; +import org.testcontainers.CockroachDBTestImages; import org.testcontainers.containers.CockroachContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; @@ -9,13 +10,11 @@ import java.util.logging.Level; import java.util.logging.LogManager; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.CockroachDBTestImages.COCKROACHDB_IMAGE; public class SimpleCockroachDBTest extends AbstractContainerDatabaseTest { - static { // Postgres JDBC driver uses JUL; disable it to avoid annoying, irrelevant, stderr logs during connection testing LogManager.getLogManager().getLogger("").setLevel(Level.OFF); @@ -23,7 +22,7 @@ public class SimpleCockroachDBTest extends AbstractContainerDatabaseTest { @Test public void testSimple() throws SQLException { - try (CockroachContainer cockroach = new CockroachContainer(COCKROACHDB_IMAGE)) { + try (CockroachContainer cockroach = new CockroachContainer(CockroachDBTestImages.COCKROACHDB_IMAGE)) { cockroach.start(); ResultSet resultSet = performQuery(cockroach, "SELECT 1"); @@ -35,8 +34,10 @@ public void testSimple() throws SQLException { @Test public void testExplicitInitScript() throws SQLException { - try (CockroachContainer cockroach = new CockroachContainer(COCKROACHDB_IMAGE) - .withInitScript("somepath/init_postgresql.sql")) { // CockroachDB is expected to be compatible with Postgres + try ( + CockroachContainer cockroach = new CockroachContainer(CockroachDBTestImages.COCKROACHDB_IMAGE) + .withInitScript("somepath/init_postgresql.sql") + ) { // CockroachDB is expected to be compatible with Postgres cockroach.start(); ResultSet resultSet = performQuery(cockroach, "SELECT foo FROM bar"); @@ -48,7 +49,7 @@ public void testExplicitInitScript() throws SQLException { @Test public void testWithAdditionalUrlParamInJdbcUrl() { - CockroachContainer cockroach = new CockroachContainer(COCKROACHDB_IMAGE) + CockroachContainer cockroach = new CockroachContainer(CockroachDBTestImages.COCKROACHDB_IMAGE) .withUrlParam("sslmode", "disable") .withUrlParam("application_name", "cockroach"); diff --git a/modules/couchbase/src/main/java/org/testcontainers/couchbase/BucketDefinition.java b/modules/couchbase/src/main/java/org/testcontainers/couchbase/BucketDefinition.java index 3778833182e..ad666b4ffef 100644 --- a/modules/couchbase/src/main/java/org/testcontainers/couchbase/BucketDefinition.java +++ b/modules/couchbase/src/main/java/org/testcontainers/couchbase/BucketDefinition.java @@ -22,8 +22,11 @@ public class BucketDefinition { private final String name; + private boolean flushEnabled = false; + private boolean queryPrimaryIndex = true; + private int quota = 100; public BucketDefinition(final String name) { @@ -49,7 +52,7 @@ public BucketDefinition withFlushEnabled(final boolean flushEnabled) { */ public BucketDefinition withQuota(final int quota) { if (quota < 100) { - throw new IllegalArgumentException("Bucket quota cannot be less than 100MB!"); + throw new IllegalArgumentException("Bucket quota cannot be less than 100MB!"); } this.quota = quota; return this; @@ -81,5 +84,4 @@ public boolean hasPrimaryIndex() { public int getQuota() { return quota; } - } diff --git a/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseContainer.java b/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseContainer.java index c2becc68fc3..4f190a5413c 100644 --- a/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseContainer.java +++ b/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseContainer.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.testcontainers.couchbase; import com.fasterxml.jackson.databind.JsonNode; @@ -139,7 +140,6 @@ public CouchbaseContainer(final String dockerImageName) { */ public CouchbaseContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); } @@ -182,8 +182,14 @@ public CouchbaseContainer withServiceQuota(final CouchbaseService service, final throw new IllegalArgumentException("The provided service (" + service + ") has no quota to configure"); } if (quotaMb < service.getMinimumQuotaMb()) { - throw new IllegalArgumentException("The custom quota (" + quotaMb + ") must not be smaller than the " + - "minimum quota for the service (" + service.getMinimumQuotaMb() + ")"); + throw new IllegalArgumentException( + "The custom quota (" + + quotaMb + + ") must not be smaller than the " + + "minimum quota for the service (" + + service.getMinimumQuotaMb() + + ")" + ); } this.customServiceQuotas.put(service, quotaMb); return this; @@ -255,54 +261,59 @@ protected void configure() { WaitAllStrategy waitStrategy = new WaitAllStrategy(); // Makes sure that all nodes in the cluster are healthy. - waitStrategy = waitStrategy.withStrategy( - new HttpWaitStrategy() - .forPath("/pools/default") - .forPort(MGMT_PORT) - .withBasicCredentials(username, password) - .forStatusCode(200) - .forResponsePredicate(response -> { - try { - return Optional.of(MAPPER.readTree(response)) - .map(n -> n.at("/nodes/0/status")) - .map(JsonNode::asText) - .map("healthy"::equals) - .orElse(false); - } catch (IOException e) { - logger().error("Unable to parse response: {}", response, e); - return false; - } - }) - ); - - if (enabledServices.contains(CouchbaseService.QUERY)) { - waitStrategy = waitStrategy.withStrategy( + waitStrategy = + waitStrategy.withStrategy( new HttpWaitStrategy() - .forPath("/admin/ping") - .forPort(QUERY_PORT) + .forPath("/pools/default") + .forPort(MGMT_PORT) .withBasicCredentials(username, password) .forStatusCode(200) + .forResponsePredicate(response -> { + try { + return Optional + .of(MAPPER.readTree(response)) + .map(n -> n.at("/nodes/0/status")) + .map(JsonNode::asText) + .map("healthy"::equals) + .orElse(false); + } catch (IOException e) { + logger().error("Unable to parse response: {}", response, e); + return false; + } + }) ); + + if (enabledServices.contains(CouchbaseService.QUERY)) { + waitStrategy = + waitStrategy.withStrategy( + new HttpWaitStrategy() + .forPath("/admin/ping") + .forPort(QUERY_PORT) + .withBasicCredentials(username, password) + .forStatusCode(200) + ); } if (enabledServices.contains(CouchbaseService.ANALYTICS)) { - waitStrategy = waitStrategy.withStrategy( - new HttpWaitStrategy() - .forPath("/admin/ping") - .forPort(ANALYTICS_PORT) - .withBasicCredentials(username, password) - .forStatusCode(200) - ); + waitStrategy = + waitStrategy.withStrategy( + new HttpWaitStrategy() + .forPath("/admin/ping") + .forPort(ANALYTICS_PORT) + .withBasicCredentials(username, password) + .forStatusCode(200) + ); } if (enabledServices.contains(CouchbaseService.EVENTING)) { - waitStrategy = waitStrategy.withStrategy( - new HttpWaitStrategy() - .forPath("/api/v1/config") - .forPort(EVENTING_PORT) - .withBasicCredentials(username, password) - .forStatusCode(200) - ); + waitStrategy = + waitStrategy.withStrategy( + new HttpWaitStrategy() + .forPath("/api/v1/config") + .forPort(EVENTING_PORT) + .withBasicCredentials(username, password) + .forStatusCode(200) + ); } waitingFor(waitStrategy); @@ -329,25 +340,23 @@ protected void containerIsStarting(final InspectContainerResponse containerInfo) protected void containerIsStarted(InspectContainerResponse containerInfo) { timePhase("createBuckets", this::createBuckets); - logger().info("Couchbase container is ready! UI available at http://{}:{}", getHost(), getMappedPort(MGMT_PORT)); + logger() + .info("Couchbase container is ready! UI available at http://{}:{}", getHost(), getMappedPort(MGMT_PORT)); } /** * Before we can start configuring the host, we need to wait until the cluster manager is listening. */ private void waitUntilNodeIsOnline() { - new HttpWaitStrategy() - .forPort(MGMT_PORT) - .forPath("/pools") - .forStatusCode(200) - .waitUntilReady(this); + new HttpWaitStrategy().forPort(MGMT_PORT).forPath("/pools").forStatusCode(200).waitUntilReady(this); } /** * Fetches edition (enterprise or community) of started container. */ private void initializeIsEnterprise() { - @Cleanup Response response = doHttpRequest(MGMT_PORT, "/pools", "GET", null, true); + @Cleanup + Response response = doHttpRequest(MGMT_PORT, "/pools", "GET", null, true); try { isEnterprise = MAPPER.readTree(response.body().string()).get("isEnterprise").asBoolean(); @@ -374,9 +383,13 @@ private void initializeIsEnterprise() { private void renameNode() { logger().debug("Renaming Couchbase Node from localhost to {}", getHost()); - @Cleanup Response response = doHttpRequest(MGMT_PORT, "/node/controller/rename", "POST", new FormBody.Builder() - .add("hostname", getInternalIpAddress()) - .build(), false + @Cleanup + Response response = doHttpRequest( + MGMT_PORT, + "/node/controller/rename", + "POST", + new FormBody.Builder().add("hostname", getInternalIpAddress()).build(), + false ); checkSuccessfulResponse(response, "Could not rename couchbase node"); @@ -393,9 +406,13 @@ private void initializeServices() { .map(CouchbaseService::getIdentifier) .collect(Collectors.joining(",")); - @Cleanup Response response = doHttpRequest(MGMT_PORT, "/node/controller/setupServices", "POST", new FormBody.Builder() - .add("services", services) - .build(), false + @Cleanup + Response response = doHttpRequest( + MGMT_PORT, + "/node/controller/setupServices", + "POST", + new FormBody.Builder().add("services", services).build(), + false ); checkSuccessfulResponse(response, "Could not enable couchbase services"); @@ -423,9 +440,8 @@ private void setMemoryQuotas() { } } - @Cleanup Response response = doHttpRequest( - MGMT_PORT, "/pools/default", "POST", quotaBuilder.build(), false - ); + @Cleanup + Response response = doHttpRequest(MGMT_PORT, "/pools/default", "POST", quotaBuilder.build(), false); checkSuccessfulResponse(response, "Could not configure service memory quotas"); } @@ -438,11 +454,18 @@ private void setMemoryQuotas() { private void configureAdminUser() { logger().debug("Configuring couchbase admin user with username: \"{}\"", username); - @Cleanup Response response = doHttpRequest(MGMT_PORT, "/settings/web", "POST", new FormBody.Builder() - .add("username", username) - .add("password", password) - .add("port", Integer.toString(MGMT_PORT)) - .build(), false); + @Cleanup + Response response = doHttpRequest( + MGMT_PORT, + "/settings/web", + "POST", + new FormBody.Builder() + .add("username", username) + .add("password", password) + .add("port", Integer.toString(MGMT_PORT)) + .build(), + false + ); checkSuccessfulResponse(response, "Could not configure couchbase admin user"); } @@ -489,7 +512,8 @@ private void configureExternalPorts() { builder.add("eventingSSL", Integer.toString(getMappedPort(EVENTING_SSL_PORT))); } - @Cleanup Response response = doHttpRequest( + @Cleanup + Response response = doHttpRequest( MGMT_PORT, "/node/controller/setupAlternateAddresses/external", "PUT", @@ -506,9 +530,13 @@ private void configureExternalPorts() { private void configureIndexer() { logger().debug("Configuring the indexer service"); - @Cleanup Response response = doHttpRequest(MGMT_PORT, "/settings/indexes", "POST", new FormBody.Builder() - .add("storageMode", isEnterprise ? "memory_optimized" : "forestdb") - .build(), true + @Cleanup + Response response = doHttpRequest( + MGMT_PORT, + "/settings/indexes", + "POST", + new FormBody.Builder().add("storageMode", isEnterprise ? "memory_optimized" : "forestdb").build(), + true ); checkSuccessfulResponse(response, "Could not configure the indexing service"); @@ -523,22 +551,32 @@ private void createBuckets() { for (BucketDefinition bucket : buckets) { logger().debug("Creating bucket \"{}\"", bucket.getName()); - @Cleanup Response response = doHttpRequest(MGMT_PORT, "/pools/default/buckets", "POST", new FormBody.Builder() - .add("name", bucket.getName()) - .add("ramQuotaMB", Integer.toString(bucket.getQuota())) - .add("flushEnabled", bucket.hasFlushEnabled() ? "1" : "0") - .build(), true); + @Cleanup + Response response = doHttpRequest( + MGMT_PORT, + "/pools/default/buckets", + "POST", + new FormBody.Builder() + .add("name", bucket.getName()) + .add("ramQuotaMB", Integer.toString(bucket.getQuota())) + .add("flushEnabled", bucket.hasFlushEnabled() ? "1" : "0") + .build(), + true + ); checkSuccessfulResponse(response, "Could not create bucket " + bucket.getName()); - timePhase("createBucket:" + bucket.getName() + ":waitForAllServicesEnabled", () -> - new HttpWaitStrategy() - .forPath("/pools/default/b/" + bucket.getName()) - .forPort(MGMT_PORT) - .withBasicCredentials(username, password) - .forStatusCode(200) - .forResponsePredicate(new AllServicesEnabledPredicate()) - .waitUntilReady(this) + timePhase( + "createBucket:" + bucket.getName() + ":waitForAllServicesEnabled", + () -> { + new HttpWaitStrategy() + .forPath("/pools/default/b/" + bucket.getName()) + .forPort(MGMT_PORT) + .withBasicCredentials(username, password) + .forStatusCode(200) + .forResponsePredicate(new AllServicesEnabledPredicate()) + .waitUntilReady(this); + } ); if (enabledServices.contains(CouchbaseService.QUERY)) { @@ -546,29 +584,62 @@ private void createBuckets() { // knows about the bucket in its metadata configuration. timePhase( "createBucket:" + bucket.getName() + ":queryKeyspacePresent", - () -> Unreliables.retryUntilTrue(1, TimeUnit.MINUTES, () -> { - @Cleanup Response queryResponse = doHttpRequest(QUERY_PORT, "/query/service", "POST", new FormBody.Builder() - .add("statement", "SELECT COUNT(*) > 0 as present FROM system:keyspaces WHERE name = \"" + bucket.getName() + "\"") - .build(), true); - - String body = queryResponse.body() != null ? queryResponse.body().string() : null; - checkSuccessfulResponse(queryResponse, "Could not poll query service state for bucket: " + bucket.getName()); - - return Optional.of(MAPPER.readTree(body)) - .map(n -> n.at("/results/0/present")) - .map(JsonNode::asBoolean) - .orElse(false); - })); + () -> { + Unreliables.retryUntilTrue( + 1, + TimeUnit.MINUTES, + () -> { + @Cleanup + Response queryResponse = doHttpRequest( + QUERY_PORT, + "/query/service", + "POST", + new FormBody.Builder() + .add( + "statement", + "SELECT COUNT(*) > 0 as present FROM system:keyspaces WHERE name = \"" + + bucket.getName() + + "\"" + ) + .build(), + true + ); + + String body = queryResponse.body() != null ? queryResponse.body().string() : null; + checkSuccessfulResponse( + queryResponse, + "Could not poll query service state for bucket: " + bucket.getName() + ); + + return Optional + .of(MAPPER.readTree(body)) + .map(n -> n.at("/results/0/present")) + .map(JsonNode::asBoolean) + .orElse(false); + } + ); + } + ); } if (bucket.hasPrimaryIndex()) { if (enabledServices.contains(CouchbaseService.QUERY)) { - @Cleanup Response queryResponse = doHttpRequest(QUERY_PORT, "/query/service", "POST", new FormBody.Builder() - .add("statement", "CREATE PRIMARY INDEX on `" + bucket.getName() + "`") - .build(), true); + @Cleanup + Response queryResponse = doHttpRequest( + QUERY_PORT, + "/query/service", + "POST", + new FormBody.Builder() + .add("statement", "CREATE PRIMARY INDEX on `" + bucket.getName() + "`") + .build(), + true + ); try { - checkSuccessfulResponse(queryResponse, "Could not create primary index for bucket " + bucket.getName()); + checkSuccessfulResponse( + queryResponse, + "Could not create primary index for bucket " + bucket.getName() + ); } catch (IllegalStateException ex) { // potentially ignore the error, the index will be eventually built. if (!ex.getMessage().contains("Index creation will be retried in background")) { @@ -578,21 +649,48 @@ private void createBuckets() { timePhase( "createBucket:" + bucket.getName() + ":primaryIndexOnline", - () -> Unreliables.retryUntilTrue(1, TimeUnit.MINUTES, () -> { - @Cleanup Response stateResponse = doHttpRequest(QUERY_PORT, "/query/service", "POST", new FormBody.Builder() - .add("statement", "SELECT count(*) > 0 AS online FROM system:indexes where keyspace_id = \"" + bucket.getName() + "\" and is_primary = true and state = \"online\"") - .build(), true); - - String body = stateResponse.body() != null ? stateResponse.body().string() : null; - checkSuccessfulResponse(stateResponse, "Could not poll primary index state for bucket: " + bucket.getName()); - - return Optional.of(MAPPER.readTree(body)) - .map(n -> n.at("/results/0/online")) - .map(JsonNode::asBoolean) - .orElse(false); - })); + () -> { + Unreliables.retryUntilTrue( + 1, + TimeUnit.MINUTES, + () -> { + @Cleanup + Response stateResponse = doHttpRequest( + QUERY_PORT, + "/query/service", + "POST", + new FormBody.Builder() + .add( + "statement", + "SELECT count(*) > 0 AS online FROM system:indexes where keyspace_id = \"" + + bucket.getName() + + "\" and is_primary = true and state = \"online\"" + ) + .build(), + true + ); + + String body = stateResponse.body() != null ? stateResponse.body().string() : null; + checkSuccessfulResponse( + stateResponse, + "Could not poll primary index state for bucket: " + bucket.getName() + ); + + return Optional + .of(MAPPER.readTree(body)) + .map(n -> n.at("/results/0/online")) + .map(JsonNode::asBoolean) + .orElse(false); + } + ); + } + ); } else { - logger().info("Primary index creation for bucket {} ignored, since QUERY service is not present.", bucket.getName()); + logger() + .info( + "Primary index creation for bucket {} ignored, since QUERY service is not present.", + bucket.getName() + ); } } } @@ -602,7 +700,11 @@ private void createBuckets() { * Helper method to extract the internal IP address based on the network configuration. */ private String getInternalIpAddress() { - return getContainerInfo().getNetworkSettings().getNetworks().values().stream() + return getContainerInfo() + .getNetworkSettings() + .getNetworks() + .values() + .stream() .findFirst() .map(ContainerNetwork::getIpAddress) .orElseThrow(() -> new IllegalStateException("No network available to extract the internal IP from!")); @@ -648,8 +750,13 @@ private void checkNotRunning() { * @param auth if authentication with the admin user and password should be used. * @return the response of the request. */ - private Response doHttpRequest(final int port, final String path, final String method, final RequestBody body, - final boolean auth) { + private Response doHttpRequest( + final int port, + final String path, + final String method, + final RequestBody body, + final boolean auth + ) { try { Request.Builder requestBuilder = new Request.Builder() .url("http://" + getHost() + ":" + getMappedPort(port) + path); diff --git a/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseService.java b/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseService.java index ffb0c9f7f1f..d9a9d2ffe3a 100644 --- a/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseService.java +++ b/modules/couchbase/src/main/java/org/testcontainers/couchbase/CouchbaseService.java @@ -20,7 +20,6 @@ * Describes the different services that should be exposed on the container. */ public enum CouchbaseService { - /** * Key-Value service. */ @@ -88,5 +87,4 @@ int getMinimumQuotaMb() { boolean hasQuota() { return minimumQuotaMb > 0; } - } diff --git a/modules/couchbase/src/test/java/org/testcontainers/couchbase/CouchbaseContainerTest.java b/modules/couchbase/src/test/java/org/testcontainers/couchbase/CouchbaseContainerTest.java index c91f3f12d7c..1bdbe2ab1db 100644 --- a/modules/couchbase/src/test/java/org/testcontainers/couchbase/CouchbaseContainerTest.java +++ b/modules/couchbase/src/test/java/org/testcontainers/couchbase/CouchbaseContainerTest.java @@ -34,10 +34,13 @@ public class CouchbaseContainerTest { - private static final DockerImageName COUCHBASE_IMAGE_ENTERPRISE = - DockerImageName.parse("couchbase/server:enterprise-7.0.3"); - private static final DockerImageName COUCHBASE_IMAGE_COMMUNITY = - DockerImageName.parse("couchbase/server:community-7.0.2"); + private static final DockerImageName COUCHBASE_IMAGE_ENTERPRISE = DockerImageName.parse( + "couchbase/server:enterprise-7.0.3" + ); + + private static final DockerImageName COUCHBASE_IMAGE_COMMUNITY = DockerImageName.parse( + "couchbase/server:community-7.0.2" + ); @Test public void testBasicContainerUsageForEnterpriseContainer() { @@ -51,18 +54,21 @@ public void testBasicContainerUsageForEnterpriseContainer() { .withBucket(bucketDefinition) // } ) { - setUpClient(container, cluster -> { - Bucket bucket = cluster.bucket(bucketDefinition.getName()); - bucket.waitUntilReady(Duration.ofSeconds(10L)); + setUpClient( + container, + cluster -> { + Bucket bucket = cluster.bucket(bucketDefinition.getName()); + bucket.waitUntilReady(Duration.ofSeconds(10L)); - Collection collection = bucket.defaultCollection(); + Collection collection = bucket.defaultCollection(); - collection.upsert("foo", JsonObject.create().put("key", "value")); + collection.upsert("foo", JsonObject.create().put("key", "value")); - JsonObject fooObject = collection.get("foo").contentAsObject(); + JsonObject fooObject = collection.get("foo").contentAsObject(); - assertEquals("value", fooObject.getString("key")); - }); + assertEquals("value", fooObject.getString("key")); + } + ); } } @@ -74,42 +80,47 @@ public void testBasicContainerUsageForCommunityContainer() { CouchbaseContainer container = new CouchbaseContainer(COUCHBASE_IMAGE_COMMUNITY) .withBucket(bucketDefinition) ) { - setUpClient(container, cluster -> { - Bucket bucket = cluster.bucket(bucketDefinition.getName()); - bucket.waitUntilReady(Duration.ofSeconds(10L)); + setUpClient( + container, + cluster -> { + Bucket bucket = cluster.bucket(bucketDefinition.getName()); + bucket.waitUntilReady(Duration.ofSeconds(10L)); - Collection collection = bucket.defaultCollection(); + Collection collection = bucket.defaultCollection(); - collection.upsert("foo", JsonObject.create().put("key", "value")); + collection.upsert("foo", JsonObject.create().put("key", "value")); - JsonObject fooObject = collection.get("foo").contentAsObject(); + JsonObject fooObject = collection.get("foo").contentAsObject(); - assertEquals("value", fooObject.getString("key")); - }); + assertEquals("value", fooObject.getString("key")); + } + ); } } @Test public void testBucketIsFlushableIfEnabled() { - BucketDefinition bucketDefinition = new BucketDefinition("mybucket") - .withFlushEnabled(true); + BucketDefinition bucketDefinition = new BucketDefinition("mybucket").withFlushEnabled(true); try ( CouchbaseContainer container = new CouchbaseContainer(COUCHBASE_IMAGE_ENTERPRISE) .withBucket(bucketDefinition) ) { - setUpClient(container, cluster -> { - Bucket bucket = cluster.bucket(bucketDefinition.getName()); - bucket.waitUntilReady(Duration.ofSeconds(10L)); + setUpClient( + container, + cluster -> { + Bucket bucket = cluster.bucket(bucketDefinition.getName()); + bucket.waitUntilReady(Duration.ofSeconds(10L)); - Collection collection = bucket.defaultCollection(); + Collection collection = bucket.defaultCollection(); - collection.upsert("foo", JsonObject.create().put("key", "value")); + collection.upsert("foo", JsonObject.create().put("key", "value")); - cluster.buckets().flushBucket(bucketDefinition.getName()); + cluster.buckets().flushBucket(bucketDefinition.getName()); - await().untilAsserted(() -> assertFalse(collection.exists("foo").exists())); - }); + await().untilAsserted(() -> assertFalse(collection.exists("foo").exists())); + } + ); } } @@ -123,7 +134,12 @@ public void testFailureIfCommunityUsedWithAnalytics() { CouchbaseContainer container = new CouchbaseContainer(COUCHBASE_IMAGE_COMMUNITY) .withEnabledServices(CouchbaseService.KV, CouchbaseService.ANALYTICS) ) { - assertThrows(ContainerLaunchException.class, () -> setUpClient(container, cluster -> {})); + assertThrows( + ContainerLaunchException.class, + () -> { + setUpClient(container, cluster -> {}); + } + ); } } @@ -137,7 +153,12 @@ public void testFailureIfCommunityUsedWithEventing() { CouchbaseContainer container = new CouchbaseContainer(COUCHBASE_IMAGE_COMMUNITY) .withEnabledServices(CouchbaseService.KV, CouchbaseService.EVENTING) ) { - assertThrows(ContainerLaunchException.class, () -> setUpClient(container, cluster -> {})); + assertThrows( + ContainerLaunchException.class, + () -> { + setUpClient(container, cluster -> {}); + } + ); } } diff --git a/modules/database-commons/src/main/java/org/testcontainers/delegate/AbstractDatabaseDelegate.java b/modules/database-commons/src/main/java/org/testcontainers/delegate/AbstractDatabaseDelegate.java index 14572dec421..196eb485b5f 100644 --- a/modules/database-commons/src/main/java/org/testcontainers/delegate/AbstractDatabaseDelegate.java +++ b/modules/database-commons/src/main/java/org/testcontainers/delegate/AbstractDatabaseDelegate.java @@ -27,7 +27,12 @@ protected CONNECTION getConnection() { } @Override - public void execute(Collection statements, String scriptPath, boolean continueOnError, boolean ignoreFailedDrops) { + public void execute( + Collection statements, + String scriptPath, + boolean continueOnError, + boolean ignoreFailedDrops + ) { int lineNumber = 0; for (String statement : statements) { lineNumber++; diff --git a/modules/database-commons/src/main/java/org/testcontainers/delegate/DatabaseDelegate.java b/modules/database-commons/src/main/java/org/testcontainers/delegate/DatabaseDelegate.java index 55886d88143..eda8f197008 100644 --- a/modules/database-commons/src/main/java/org/testcontainers/delegate/DatabaseDelegate.java +++ b/modules/database-commons/src/main/java/org/testcontainers/delegate/DatabaseDelegate.java @@ -10,11 +10,16 @@ * @author Eugeny Karpov */ public interface DatabaseDelegate extends AutoCloseable { - /** * Execute statement by the implementation of the delegate */ - void execute(String statement, String scriptPath, int lineNumber, boolean continueOnError, boolean ignoreFailedDrops); + void execute( + String statement, + String scriptPath, + int lineNumber, + boolean continueOnError, + boolean ignoreFailedDrops + ); /** * Execute collection of statements diff --git a/modules/database-commons/src/main/java/org/testcontainers/ext/ScriptUtils.java b/modules/database-commons/src/main/java/org/testcontainers/ext/ScriptUtils.java index 1b94b84f368..eca4989c70e 100644 --- a/modules/database-commons/src/main/java/org/testcontainers/ext/ScriptUtils.java +++ b/modules/database-commons/src/main/java/org/testcontainers/ext/ScriptUtils.java @@ -22,13 +22,14 @@ import org.slf4j.LoggerFactory; import org.testcontainers.delegate.DatabaseDelegate; -import javax.script.ScriptException; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.LinkedList; import java.util.List; +import javax.script.ScriptException; + /** * This is a modified version of the Spring-JDBC ScriptUtils class, adapted to reduce * dependencies and slightly alter the API. @@ -48,278 +49,346 @@ */ public abstract class ScriptUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(ScriptUtils.class); - - /** - * Default statement separator within SQL scripts. - */ - public static final String DEFAULT_STATEMENT_SEPARATOR = ";"; + private static final Logger LOGGER = LoggerFactory.getLogger(ScriptUtils.class); - /** - * Fallback statement separator within SQL scripts. - *

Used if neither a custom defined separator nor the - * {@link #DEFAULT_STATEMENT_SEPARATOR} is present in a given script. - */ - public static final String FALLBACK_STATEMENT_SEPARATOR = "\n"; + /** + * Default statement separator within SQL scripts. + */ + public static final String DEFAULT_STATEMENT_SEPARATOR = ";"; - /** - * Default prefix for line comments within SQL scripts. - */ - public static final String DEFAULT_COMMENT_PREFIX = "--"; + /** + * Fallback statement separator within SQL scripts. + *

Used if neither a custom defined separator nor the + * {@link #DEFAULT_STATEMENT_SEPARATOR} is present in a given script. + */ + public static final String FALLBACK_STATEMENT_SEPARATOR = "\n"; - /** - * Default start delimiter for block comments within SQL scripts. - */ - public static final String DEFAULT_BLOCK_COMMENT_START_DELIMITER = "/*"; + /** + * Default prefix for line comments within SQL scripts. + */ + public static final String DEFAULT_COMMENT_PREFIX = "--"; - /** - * Default end delimiter for block comments within SQL scripts. - */ - public static final String DEFAULT_BLOCK_COMMENT_END_DELIMITER = "*/"; + /** + * Default start delimiter for block comments within SQL scripts. + */ + public static final String DEFAULT_BLOCK_COMMENT_START_DELIMITER = "/*"; + /** + * Default end delimiter for block comments within SQL scripts. + */ + public static final String DEFAULT_BLOCK_COMMENT_END_DELIMITER = "*/"; - /** - * Prevent instantiation of this utility class. - */ - private ScriptUtils() { - /* no-op */ - } + /** + * Prevent instantiation of this utility class. + */ + private ScriptUtils() { + /* no-op */ + } /** - * Split an SQL script into separate statements delimited by the provided - * separator string. Each individual statement will be added to the provided - * {@code List}. - *

Within the script, the provided {@code commentPrefix} will be honored: - * any text beginning with the comment prefix and extending to the end of the - * line will be omitted from the output. Similarly, the provided - * {@code blockCommentStartDelimiter} and {@code blockCommentEndDelimiter} - * delimiters will be honored: any text enclosed in a block comment will be - * omitted from the output. In addition, multiple adjacent whitespace characters - * will be collapsed into a single space. - * @param resource the resource from which the script was read - * @param script the SQL script; never {@code null} or empty - * @param separator text separating each statement — typically a ';' or - * newline character; never {@code null} - * @param commentPrefix the prefix that identifies SQL line comments — - * typically "--"; never {@code null} or empty - * @param blockCommentStartDelimiter the start block comment delimiter; - * never {@code null} or empty - * @param blockCommentEndDelimiter the end block comment delimiter; - * never {@code null} or empty - * @param statements the list that will contain the individual statements - */ - public static void splitSqlScript(String resource, String script, String separator, String commentPrefix, - String blockCommentStartDelimiter, String blockCommentEndDelimiter, List statements) { - - checkArgument(StringUtils.isNotEmpty(script), "script must not be null or empty"); - checkArgument(separator != null, "separator must not be null"); - checkArgument(StringUtils.isNotEmpty(commentPrefix), "commentPrefix must not be null or empty"); - checkArgument(StringUtils.isNotEmpty(blockCommentStartDelimiter), "blockCommentStartDelimiter must not be null or empty"); - checkArgument(StringUtils.isNotEmpty(blockCommentEndDelimiter), "blockCommentEndDelimiter must not be null or empty"); - - StringBuilder sb = new StringBuilder(); - boolean inEscape = false; - boolean inLineComment = false; - boolean inBlockComment = false; - Character currentLiteralDelimiter = null; - - int compoundStatementDepth = 0; - final String lowerCaseScriptContent = script.toLowerCase(); - char[] content = script.toCharArray(); - for (int i = 0; i < script.length(); i++) { - char c = content[i]; - if (inEscape) { - inEscape = false; - sb.append(c); - continue; - } - // MySQL style escapes - if (c == '\\') { - inEscape = true; - sb.append(c); - continue; - } - // Determine whether we're entering/leaving a string literal - if (!inBlockComment && !inLineComment && (c == '\'' || c == '"' || c == '`')) { - if (currentLiteralDelimiter == null) { // ignore delimiters within an existing string literal - currentLiteralDelimiter = c; - } else if (currentLiteralDelimiter == c) { // find end of string literal - currentLiteralDelimiter = null; - } - } - final boolean inLiteral = currentLiteralDelimiter != null; - - if (!inLiteral && containsSubstringAtOffset(lowerCaseScriptContent, commentPrefix, i)) { - inLineComment = true; - } - if (inLineComment && c == '\n') { - inLineComment = false; - } - if (!inLiteral && containsSubstringAtOffset(lowerCaseScriptContent, blockCommentStartDelimiter, i)) { - inBlockComment = true; - } - if (!inLiteral && inBlockComment && containsSubstringAtOffset(lowerCaseScriptContent, blockCommentEndDelimiter, i)) { - inBlockComment = false; - } - final boolean inComment = inLineComment || inBlockComment; - - if (!inLiteral && !inComment && containsKeywordsAtOffset(lowerCaseScriptContent, "BEGIN", i, separator, commentPrefix, blockCommentStartDelimiter)) { - compoundStatementDepth++; - } - if (!inLiteral && !inComment && containsKeywordsAtOffset(lowerCaseScriptContent, "END", i, separator, commentPrefix, blockCommentStartDelimiter)) { - compoundStatementDepth--; - } - final boolean inCompoundStatement = compoundStatementDepth != 0; - - if (!inLiteral && !inCompoundStatement) { - if (script.startsWith(separator, i)) { - // we've reached the end of the current statement - sb = flushStringBuilder(sb, statements); - i += separator.length() - 1; - continue; - } - else if (script.startsWith(commentPrefix, i)) { - // skip over any content from the start of the comment to the EOL - int indexOfNextNewline = script.indexOf("\n", i); - if (indexOfNextNewline > i) { - i = indexOfNextNewline; - continue; - } - else { - // if there's no EOL, we must be at the end - // of the script, so stop here. - break; - } - } - else if (script.startsWith(blockCommentStartDelimiter, i)) { - // skip over any block comments - int indexOfCommentEnd = script.indexOf(blockCommentEndDelimiter, i); - if (indexOfCommentEnd > i) { - i = indexOfCommentEnd + blockCommentEndDelimiter.length() - 1; + * Split an SQL script into separate statements delimited by the provided + * separator string. Each individual statement will be added to the provided + * {@code List}. + *

Within the script, the provided {@code commentPrefix} will be honored: + * any text beginning with the comment prefix and extending to the end of the + * line will be omitted from the output. Similarly, the provided + * {@code blockCommentStartDelimiter} and {@code blockCommentEndDelimiter} + * delimiters will be honored: any text enclosed in a block comment will be + * omitted from the output. In addition, multiple adjacent whitespace characters + * will be collapsed into a single space. + * @param resource the resource from which the script was read + * @param script the SQL script; never {@code null} or empty + * @param separator text separating each statement — typically a ';' or + * newline character; never {@code null} + * @param commentPrefix the prefix that identifies SQL line comments — + * typically "--"; never {@code null} or empty + * @param blockCommentStartDelimiter the start block comment delimiter; + * never {@code null} or empty + * @param blockCommentEndDelimiter the end block comment delimiter; + * never {@code null} or empty + * @param statements the list that will contain the individual statements + */ + public static void splitSqlScript( + String resource, + String script, + String separator, + String commentPrefix, + String blockCommentStartDelimiter, + String blockCommentEndDelimiter, + List statements + ) { + checkArgument(StringUtils.isNotEmpty(script), "script must not be null or empty"); + checkArgument(separator != null, "separator must not be null"); + checkArgument(StringUtils.isNotEmpty(commentPrefix), "commentPrefix must not be null or empty"); + checkArgument( + StringUtils.isNotEmpty(blockCommentStartDelimiter), + "blockCommentStartDelimiter must not be null or empty" + ); + checkArgument( + StringUtils.isNotEmpty(blockCommentEndDelimiter), + "blockCommentEndDelimiter must not be null or empty" + ); + + StringBuilder sb = new StringBuilder(); + boolean inEscape = false; + boolean inLineComment = false; + boolean inBlockComment = false; + Character currentLiteralDelimiter = null; + + int compoundStatementDepth = 0; + final String lowerCaseScriptContent = script.toLowerCase(); + char[] content = script.toCharArray(); + for (int i = 0; i < script.length(); i++) { + char c = content[i]; + if (inEscape) { + inEscape = false; + sb.append(c); + continue; + } + // MySQL style escapes + if (c == '\\') { + inEscape = true; + sb.append(c); + continue; + } + // Determine whether we're entering/leaving a string literal + if (!inBlockComment && !inLineComment && (c == '\'' || c == '"' || c == '`')) { + if (currentLiteralDelimiter == null) { // ignore delimiters within an existing string literal + currentLiteralDelimiter = c; + } else if (currentLiteralDelimiter == c) { // find end of string literal + currentLiteralDelimiter = null; + } + } + final boolean inLiteral = currentLiteralDelimiter != null; + + if (!inLiteral && containsSubstringAtOffset(lowerCaseScriptContent, commentPrefix, i)) { + inLineComment = true; + } + if (inLineComment && c == '\n') { + inLineComment = false; + } + if (!inLiteral && containsSubstringAtOffset(lowerCaseScriptContent, blockCommentStartDelimiter, i)) { + inBlockComment = true; + } + if ( + !inLiteral && + inBlockComment && + containsSubstringAtOffset(lowerCaseScriptContent, blockCommentEndDelimiter, i) + ) { + inBlockComment = false; + } + final boolean inComment = inLineComment || inBlockComment; + + if ( + !inLiteral && + !inComment && + containsKeywordsAtOffset( + lowerCaseScriptContent, + "BEGIN", + i, + separator, + commentPrefix, + blockCommentStartDelimiter + ) + ) { + compoundStatementDepth++; + } + if ( + !inLiteral && + !inComment && + containsKeywordsAtOffset( + lowerCaseScriptContent, + "END", + i, + separator, + commentPrefix, + blockCommentStartDelimiter + ) + ) { + compoundStatementDepth--; + } + final boolean inCompoundStatement = compoundStatementDepth != 0; + + if (!inLiteral && !inCompoundStatement) { + if (script.startsWith(separator, i)) { + // we've reached the end of the current statement + sb = flushStringBuilder(sb, statements); + i += separator.length() - 1; + continue; + } else if (script.startsWith(commentPrefix, i)) { + // skip over any content from the start of the comment to the EOL + int indexOfNextNewline = script.indexOf("\n", i); + if (indexOfNextNewline > i) { + i = indexOfNextNewline; + continue; + } else { + // if there's no EOL, we must be at the end + // of the script, so stop here. + break; + } + } else if (script.startsWith(blockCommentStartDelimiter, i)) { + // skip over any block comments + int indexOfCommentEnd = script.indexOf(blockCommentEndDelimiter, i); + if (indexOfCommentEnd > i) { + i = indexOfCommentEnd + blockCommentEndDelimiter.length() - 1; inBlockComment = false; - continue; - } - else { - throw new ScriptParseException(String.format("Missing block comment end delimiter [%s].", - blockCommentEndDelimiter), resource); - } - } - else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') { - // avoid multiple adjacent whitespace characters - if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') { - c = ' '; - } - else { - continue; - } - } - } - sb.append(c); - } - flushStringBuilder(sb, statements); - } - - private static StringBuilder flushStringBuilder(StringBuilder sb, List statements) { - if (sb.length() == 0) { - return sb; - } - - final String s = sb.toString().trim(); - if (StringUtils.isNotEmpty(s)) { - statements.add(s); - } - - return new StringBuilder(); - } - - private static boolean isSeperator(char c, String separator, String commentPrefix, - String blockCommentStartDelimiter) { - return c == ' ' || c == '\r' || c == '\n' || c == '\t' || - c == separator.charAt(0) || c == separator.charAt(separator.length() - 1) || - c == commentPrefix.charAt(0) || c == blockCommentStartDelimiter.charAt(0) || - c == blockCommentStartDelimiter.charAt(blockCommentStartDelimiter.length() - 1); + continue; + } else { + throw new ScriptParseException( + String.format("Missing block comment end delimiter [%s].", blockCommentEndDelimiter), + resource + ); + } + } else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') { + // avoid multiple adjacent whitespace characters + if (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ') { + c = ' '; + } else { + continue; + } + } + } + sb.append(c); + } + flushStringBuilder(sb, statements); + } + + private static StringBuilder flushStringBuilder(StringBuilder sb, List statements) { + if (sb.length() == 0) { + return sb; + } + + final String s = sb.toString().trim(); + if (StringUtils.isNotEmpty(s)) { + statements.add(s); + } + + return new StringBuilder(); } - private static boolean containsSubstringAtOffset(String lowercaseString, String substring, int offset) { - String lowercaseSubstring = substring.toLowerCase(); + private static boolean isSeperator( + char c, + String separator, + String commentPrefix, + String blockCommentStartDelimiter + ) { + return ( + c == ' ' || + c == '\r' || + c == '\n' || + c == '\t' || + c == separator.charAt(0) || + c == separator.charAt(separator.length() - 1) || + c == commentPrefix.charAt(0) || + c == blockCommentStartDelimiter.charAt(0) || + c == blockCommentStartDelimiter.charAt(blockCommentStartDelimiter.length() - 1) + ); + } - return lowercaseString.startsWith(lowercaseSubstring, offset); - } + private static boolean containsSubstringAtOffset(String lowercaseString, String substring, int offset) { + String lowercaseSubstring = substring.toLowerCase(); - private static boolean containsKeywordsAtOffset(String lowercaseString, String keywords, int offset, - String separator, String commentPrefix, - String blockCommentStartDelimiter) { + return lowercaseString.startsWith(lowercaseSubstring, offset); + } + + private static boolean containsKeywordsAtOffset( + String lowercaseString, + String keywords, + int offset, + String separator, + String commentPrefix, + String blockCommentStartDelimiter + ) { String lowercaseKeywords = keywords.toLowerCase(); - boolean backSeperated = (offset == 0) || isSeperator(lowercaseString.charAt(offset - 1), - separator, commentPrefix, blockCommentStartDelimiter); - boolean frontSeperated = (offset >= (lowercaseString.length() - keywords.length())) || - isSeperator(lowercaseString.charAt(offset + keywords.length()), - separator, commentPrefix, blockCommentStartDelimiter); + boolean backSeperated = + (offset == 0) || + isSeperator(lowercaseString.charAt(offset - 1), separator, commentPrefix, blockCommentStartDelimiter); + boolean frontSeperated = + (offset >= (lowercaseString.length() - keywords.length())) || + isSeperator( + lowercaseString.charAt(offset + keywords.length()), + separator, + commentPrefix, + blockCommentStartDelimiter + ); return backSeperated && frontSeperated && lowercaseString.startsWith(lowercaseKeywords, offset); } - private static void checkArgument(boolean expression, String errorMessage) { - if (!expression) { - throw new IllegalArgumentException(errorMessage); - } - } - - /** - * Does the provided SQL script contain the specified delimiter? - * @param script the SQL script - * @param delim String delimiting each statement - typically a ';' character - */ - public static boolean containsSqlScriptDelimiters(String script, String delim) { - boolean inLiteral = false; - char[] content = script.toCharArray(); - for (int i = 0; i < script.length(); i++) { - if (content[i] == '\'') { - inLiteral = !inLiteral; - } - if (!inLiteral && script.startsWith(delim, i)) { - return true; - } - } - return false; - } - - /** - * Load script from classpath and apply it to the given database - * - * @param databaseDelegate database delegate for script execution - * @param initScriptPath the resource to load the init script from - */ - public static void runInitScript(DatabaseDelegate databaseDelegate, String initScriptPath) { - try { - URL resource = Thread.currentThread().getContextClassLoader().getResource(initScriptPath); - if (resource == null) { - resource = ScriptUtils.class.getClassLoader().getResource(initScriptPath); - if (resource == null) { - LOGGER.warn("Could not load classpath init script: {}", initScriptPath); - throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath + ". Resource not found."); - } - } - String scripts = IOUtils.toString(resource, StandardCharsets.UTF_8); - executeDatabaseScript(databaseDelegate, initScriptPath, scripts); - } catch (IOException e) { - LOGGER.warn("Could not load classpath init script: {}", initScriptPath); - throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath, e); - } catch (ScriptException e) { - LOGGER.error("Error while executing init script: {}", initScriptPath, e); - throw new UncategorizedScriptException("Error while executing init script: " + initScriptPath, e); - } - } - - public static void executeDatabaseScript(DatabaseDelegate databaseDelegate, String scriptPath, String script) throws ScriptException { - executeDatabaseScript(databaseDelegate, scriptPath, script, false, false, DEFAULT_COMMENT_PREFIX, DEFAULT_STATEMENT_SEPARATOR, DEFAULT_BLOCK_COMMENT_START_DELIMITER, DEFAULT_BLOCK_COMMENT_END_DELIMITER); + private static void checkArgument(boolean expression, String errorMessage) { + if (!expression) { + throw new IllegalArgumentException(errorMessage); + } + } + + /** + * Does the provided SQL script contain the specified delimiter? + * @param script the SQL script + * @param delim String delimiting each statement - typically a ';' character + */ + public static boolean containsSqlScriptDelimiters(String script, String delim) { + boolean inLiteral = false; + char[] content = script.toCharArray(); + for (int i = 0; i < script.length(); i++) { + if (content[i] == '\'') { + inLiteral = !inLiteral; + } + if (!inLiteral && script.startsWith(delim, i)) { + return true; + } + } + return false; + } + + /** + * Load script from classpath and apply it to the given database + * + * @param databaseDelegate database delegate for script execution + * @param initScriptPath the resource to load the init script from + */ + public static void runInitScript(DatabaseDelegate databaseDelegate, String initScriptPath) { + try { + URL resource = Thread.currentThread().getContextClassLoader().getResource(initScriptPath); + if (resource == null) { + resource = ScriptUtils.class.getClassLoader().getResource(initScriptPath); + if (resource == null) { + LOGGER.warn("Could not load classpath init script: {}", initScriptPath); + throw new ScriptLoadException( + "Could not load classpath init script: " + initScriptPath + ". Resource not found." + ); + } + } + String scripts = IOUtils.toString(resource, StandardCharsets.UTF_8); + executeDatabaseScript(databaseDelegate, initScriptPath, scripts); + } catch (IOException e) { + LOGGER.warn("Could not load classpath init script: {}", initScriptPath); + throw new ScriptLoadException("Could not load classpath init script: " + initScriptPath, e); + } catch (ScriptException e) { + LOGGER.error("Error while executing init script: {}", initScriptPath, e); + throw new UncategorizedScriptException("Error while executing init script: " + initScriptPath, e); + } + } + + public static void executeDatabaseScript(DatabaseDelegate databaseDelegate, String scriptPath, String script) + throws ScriptException { + executeDatabaseScript( + databaseDelegate, + scriptPath, + script, + false, + false, + DEFAULT_COMMENT_PREFIX, + DEFAULT_STATEMENT_SEPARATOR, + DEFAULT_BLOCK_COMMENT_START_DELIMITER, + DEFAULT_BLOCK_COMMENT_END_DELIMITER + ); } /** - * Execute the given database script. - *

Statement separators and comments will be removed before executing - * individual statements within the supplied script. + * Execute the given database script. + *

Statement separators and comments will be removed before executing + * individual statements within the supplied script. *

Do not use this method to execute DDL if you expect rollback. * @param databaseDelegate database delegate for script execution * @param scriptPath the resource (potentially associated with a specific encoding) @@ -328,85 +397,104 @@ public static void executeDatabaseScript(DatabaseDelegate databaseDelegate, Stri *@param continueOnError whether or not to continue without throwing an exception * in the event of an error * @param ignoreFailedDrops whether or not to continue in the event of specifically -* an error on a {@code DROP} statement + * an error on a {@code DROP} statement * @param commentPrefix the prefix that identifies comments in the SQL script — -* typically "--" + * typically "--" * @param separator the script statement separator; defaults to -* {@value #DEFAULT_STATEMENT_SEPARATOR} if not specified and falls back to -* {@value #FALLBACK_STATEMENT_SEPARATOR} as a last resort + * {@value #DEFAULT_STATEMENT_SEPARATOR} if not specified and falls back to + * {@value #FALLBACK_STATEMENT_SEPARATOR} as a last resort * @param blockCommentStartDelimiter the start block comment delimiter; never -* {@code null} or empty + * {@code null} or empty * @param blockCommentEndDelimiter the end block comment delimiter; never -* {@code null} or empty @throws ScriptException if an error occurred while executing the SQL script - */ - public static void executeDatabaseScript(DatabaseDelegate databaseDelegate, String scriptPath, String script, boolean continueOnError, - boolean ignoreFailedDrops, String commentPrefix, String separator, String blockCommentStartDelimiter, - String blockCommentEndDelimiter) throws ScriptException { - - try { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Executing database script from " + scriptPath); - } - - long startTime = System.currentTimeMillis(); - List statements = new LinkedList<>(); - - if (separator == null) { - separator = DEFAULT_STATEMENT_SEPARATOR; - } - if (!containsSqlScriptDelimiters(script, separator)) { - separator = FALLBACK_STATEMENT_SEPARATOR; - } - - splitSqlScript(scriptPath, script, separator, commentPrefix, blockCommentStartDelimiter, - blockCommentEndDelimiter, statements); - - try (DatabaseDelegate closeableDelegate = databaseDelegate) { - closeableDelegate.execute(statements, scriptPath, continueOnError, ignoreFailedDrops); - } - - long elapsedTime = System.currentTimeMillis() - startTime; - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Executed database script from " + scriptPath + " in " + elapsedTime + " ms."); - } - } - catch (Exception ex) { - if (ex instanceof ScriptException) { - throw (ScriptException) ex; - } - - throw new UncategorizedScriptException( - "Failed to execute database script from resource [" + script + "]", ex); - } - } - - public static class ScriptLoadException extends RuntimeException { - public ScriptLoadException(String message) { - super(message); - } - - public ScriptLoadException(String message, Throwable cause) { - super(message, cause); - } - } - - public static class ScriptParseException extends RuntimeException { - public ScriptParseException(String format, String scriptPath) { - super(String.format(format, scriptPath)); - } - } - - public static class ScriptStatementFailedException extends RuntimeException { - public ScriptStatementFailedException(String statement, int lineNumber, String scriptPath) { - this(statement, lineNumber, scriptPath, null); - } - - public ScriptStatementFailedException(String statement, int lineNumber, String scriptPath, Exception ex) { - super(String.format("Script execution failed (%s:%d): %s", scriptPath, lineNumber, statement), ex); - } - } + * {@code null} or empty @throws ScriptException if an error occurred while executing the SQL script + */ + public static void executeDatabaseScript( + DatabaseDelegate databaseDelegate, + String scriptPath, + String script, + boolean continueOnError, + boolean ignoreFailedDrops, + String commentPrefix, + String separator, + String blockCommentStartDelimiter, + String blockCommentEndDelimiter + ) throws ScriptException { + try { + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Executing database script from " + scriptPath); + } + + long startTime = System.currentTimeMillis(); + List statements = new LinkedList<>(); + + if (separator == null) { + separator = DEFAULT_STATEMENT_SEPARATOR; + } + if (!containsSqlScriptDelimiters(script, separator)) { + separator = FALLBACK_STATEMENT_SEPARATOR; + } + + splitSqlScript( + scriptPath, + script, + separator, + commentPrefix, + blockCommentStartDelimiter, + blockCommentEndDelimiter, + statements + ); + + try (DatabaseDelegate closeableDelegate = databaseDelegate) { + closeableDelegate.execute(statements, scriptPath, continueOnError, ignoreFailedDrops); + } + + long elapsedTime = System.currentTimeMillis() - startTime; + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Executed database script from " + scriptPath + " in " + elapsedTime + " ms."); + } + } catch (Exception ex) { + if (ex instanceof ScriptException) { + throw (ScriptException) ex; + } + + throw new UncategorizedScriptException( + "Failed to execute database script from resource [" + script + "]", + ex + ); + } + } + + public static class ScriptLoadException extends RuntimeException { + + public ScriptLoadException(String message) { + super(message); + } + + public ScriptLoadException(String message, Throwable cause) { + super(message, cause); + } + } + + public static class ScriptParseException extends RuntimeException { + + public ScriptParseException(String format, String scriptPath) { + super(String.format(format, scriptPath)); + } + } + + public static class ScriptStatementFailedException extends RuntimeException { + + public ScriptStatementFailedException(String statement, int lineNumber, String scriptPath) { + this(statement, lineNumber, scriptPath, null); + } + + public ScriptStatementFailedException(String statement, int lineNumber, String scriptPath, Exception ex) { + super(String.format("Script execution failed (%s:%d): %s", scriptPath, lineNumber, statement), ex); + } + } public static class UncategorizedScriptException extends RuntimeException { + public UncategorizedScriptException(String s, Exception ex) { super(s, ex); } diff --git a/modules/database-commons/src/test/java/org/testcontainers/ext/ScriptSplittingTest.java b/modules/database-commons/src/test/java/org/testcontainers/ext/ScriptSplittingTest.java index 202a3b995db..bc9476cc83d 100644 --- a/modules/database-commons/src/test/java/org/testcontainers/ext/ScriptSplittingTest.java +++ b/modules/database-commons/src/test/java/org/testcontainers/ext/ScriptSplittingTest.java @@ -4,11 +4,10 @@ import org.junit.Test; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import static java.util.Arrays.asList; import static org.junit.Assert.fail; -import static org.testcontainers.ext.ScriptUtils.*; public class ScriptSplittingTest { @@ -16,18 +15,15 @@ public class ScriptSplittingTest { public void testStringDemarcation() { String script = "SELECT 'foo `bar`'; SELECT 'foo -- `bar`'; SELECT 'foo /* `bar`';"; - List expected = asList( - "SELECT 'foo `bar`'", - "SELECT 'foo -- `bar`'", - "SELECT 'foo /* `bar`'" - ); + List expected = Arrays.asList("SELECT 'foo `bar`'", "SELECT 'foo -- `bar`'", "SELECT 'foo /* `bar`'"); splitAndCompare(script, expected); } @Test public void testIssue1547Case1() { - String script = "create database if not exists ttt;\n" + + String script = + "create database if not exists ttt;\n" + "\n" + "use ttt;\n" + "\n" + @@ -43,7 +39,7 @@ public void testIssue1547Case1() { " id bigint auto_increment primary key\n" + ") comment 'bbb';"; - List expected = asList( + List expected = Arrays.asList( "create database if not exists ttt", "use ttt", "create table aaa ( id bigint auto_increment primary key, end_time datetime null COMMENT 'end_time', data_status varchar(16) not null ) comment 'aaa'", @@ -55,14 +51,15 @@ public void testIssue1547Case1() { @Test public void testIssue1547Case2() { - String script = "CREATE TABLE bar (\n" + + String script = + "CREATE TABLE bar (\n" + " end_time VARCHAR(255)\n" + ");\n" + "CREATE TABLE bar (\n" + " end_time VARCHAR(255)\n" + ");"; - List expected = asList( + List expected = Arrays.asList( "CREATE TABLE bar ( end_time VARCHAR(255) )", "CREATE TABLE bar ( end_time VARCHAR(255) )" ); @@ -74,25 +71,17 @@ public void testIssue1547Case2() { public void testUnusualSemicolonPlacement() { String script = "SELECT 1;;;;;SELECT 2;\n;SELECT 3\n; SELECT 4;\n SELECT 5"; - List expected = asList( - "SELECT 1", - "SELECT 2", - "SELECT 3", - "SELECT 4", - "SELECT 5" - ); + List expected = Arrays.asList("SELECT 1", "SELECT 2", "SELECT 3", "SELECT 4", "SELECT 5"); splitAndCompare(script, expected); } @Test public void testCommentedSemicolon() { - String script = "CREATE TABLE bar (\n" + - " foo VARCHAR(255)\n" + - "); \nDROP PROCEDURE IF EXISTS -- ;\n" + - " count_foo"; + String script = + "CREATE TABLE bar (\n" + " foo VARCHAR(255)\n" + "); \nDROP PROCEDURE IF EXISTS -- ;\n" + " count_foo"; - List expected = asList( + List expected = Arrays.asList( "CREATE TABLE bar ( foo VARCHAR(255) )", "DROP PROCEDURE IF EXISTS count_foo" ); @@ -102,11 +91,12 @@ public void testCommentedSemicolon() { @Test public void testStringEscaping() { - String script = "SELECT \"a /* string literal containing comment characters like -- here\";\n" + + String script = + "SELECT \"a /* string literal containing comment characters like -- here\";\n" + "SELECT \"a 'quoting' \\\"scenario ` involving BEGIN keyword\\\" here\";\n" + "SELECT * from `bar`;"; - List expected = asList( + List expected = Arrays.asList( "SELECT \"a /* string literal containing comment characters like -- here\"", "SELECT \"a 'quoting' \\\"scenario ` involving BEGIN keyword\\\" here\"", "SELECT * from `bar`" @@ -119,18 +109,17 @@ public void testStringEscaping() { public void testBlockCommentExclusion() { String script = "INSERT INTO bar (foo) /* ; */ VALUES ('hello world');"; - List expected = asList( - "INSERT INTO bar (foo) VALUES ('hello world')" - ); + List expected = Arrays.asList("INSERT INTO bar (foo) VALUES ('hello world')"); splitAndCompare(script, expected); } @Test public void testBeginEndKeywordCorrectDetection() { - String script = "INSERT INTO something_end (begin_with_the_token, another_field) /*end*/ VALUES /* end */ (' begin ', `end`)-- begin\n;"; + String script = + "INSERT INTO something_end (begin_with_the_token, another_field) /*end*/ VALUES /* end */ (' begin ', `end`)-- begin\n;"; - List expected = asList( + List expected = Arrays.asList( "INSERT INTO something_end (begin_with_the_token, another_field) VALUES (' begin ', `end`)" ); @@ -139,16 +128,17 @@ public void testBeginEndKeywordCorrectDetection() { @Test public void testCommentInStrings() { - String script = "CREATE TABLE bar (foo VARCHAR(255));\n" + + String script = + "CREATE TABLE bar (foo VARCHAR(255));\n" + "\n" + "/* Insert Values */\n" + "INSERT INTO bar (foo) values ('--1');\n" + "INSERT INTO bar (foo) values ('--2');\n" + "INSERT INTO bar (foo) values ('/* something */');\n" + - "/* INSERT INTO bar (foo) values (' */'); -- '*/;\n" + // purposefully broken, to see if it breaks our splitting + "/* INSERT INTO bar (foo) values (' */'); -- '*/;\n" + // purposefully broken, to see if it breaks our splitting "INSERT INTO bar (foo) values ('foo');"; - List expected = asList( + List expected = Arrays.asList( "CREATE TABLE bar (foo VARCHAR(255))", "INSERT INTO bar (foo) values ('--1')", "INSERT INTO bar (foo) values ('--2')", @@ -162,7 +152,8 @@ public void testCommentInStrings() { @Test public void testMultipleBeginEndDetection() { - String script = "CREATE TABLE bar (foo VARCHAR(255));\n" + + String script = + "CREATE TABLE bar (foo VARCHAR(255));\n" + "\n" + "CREATE TABLE gender (gender VARCHAR(255));\n" + "CREATE TABLE ending (ending VARCHAR(255));\n" + @@ -187,24 +178,16 @@ public void testMultipleBeginEndDetection() { "\n" + "CREATE TABLE foo (bar VARCHAR(255));"; - List expected = asList( + List expected = Arrays.asList( "CREATE TABLE bar (foo VARCHAR(255))", "CREATE TABLE gender (gender VARCHAR(255))", "CREATE TABLE ending (ending VARCHAR(255))", "CREATE TABLE end2 (end2 VARCHAR(255))", "CREATE TABLE end_2 (end2 VARCHAR(255))", - "BEGIN\n" + - " INSERT INTO ending values ('ending');\n" + - "END", - "BEGIN\n" + - " INSERT INTO ending values ('ending');\n" + - "END", - "BEGIN--Hello\n" + - " INSERT INTO ending values ('ending');\n" + - "END", - "BEGIN\n" + - " INSERT INTO ending values ('ending');\n" + - "END", + "BEGIN\n" + " INSERT INTO ending values ('ending');\n" + "END", + "BEGIN\n" + " INSERT INTO ending values ('ending');\n" + "END", + "BEGIN--Hello\n" + " INSERT INTO ending values ('ending');\n" + "END", + "BEGIN\n" + " INSERT INTO ending values ('ending');\n" + "END", "CREATE TABLE foo (bar VARCHAR(255))" ); @@ -213,7 +196,8 @@ public void testMultipleBeginEndDetection() { @Test public void testProcedureBlock() { - String script = "CREATE PROCEDURE count_foo()\n" + + String script = + "CREATE PROCEDURE count_foo()\n" + " BEGIN\n" + "\n" + " BEGIN\n" + @@ -239,31 +223,31 @@ public void testProcedureBlock() { "\n" + " END /*; */;"; - List expected = asList( + List expected = Arrays.asList( "CREATE PROCEDURE count_foo() BEGIN\n" + - "\n" + - " BEGIN\n" + - " SELECT *\n" + - " FROM bar;\n" + - " SELECT 1\n" + - " FROM dual;\n" + - " END;\n" + - "\n" + - " BEGIN\n" + - " select * from bar;\n" + - " END;\n" + - "\n" + - " -- we can do comments\n" + - "\n" + - " /* including block\n" + - " comments\n" + - " */\n" + - "\n" + - " /* what if BEGIN appears inside a comment? */\n" + - "\n" + - " select \"or what if BEGIN appears inside a literal?\";\n" + - "\n" + - " END" + "\n" + + " BEGIN\n" + + " SELECT *\n" + + " FROM bar;\n" + + " SELECT 1\n" + + " FROM dual;\n" + + " END;\n" + + "\n" + + " BEGIN\n" + + " select * from bar;\n" + + " END;\n" + + "\n" + + " -- we can do comments\n" + + "\n" + + " /* including block\n" + + " comments\n" + + " */\n" + + "\n" + + " /* what if BEGIN appears inside a comment? */\n" + + "\n" + + " select \"or what if BEGIN appears inside a literal?\";\n" + + "\n" + + " END" ); splitAndCompare(script, expected); @@ -283,12 +267,13 @@ public void testUnclosedBlockComment() { @Test public void testIssue1452Case() { - String script = "create table test (text VARCHAR(255));\n" + + String script = + "create table test (text VARCHAR(255));\n" + "\n" + "/* some comment */\n" + "insert into `test` (`text`) values ('a b');"; - List expected = asList( + List expected = Arrays.asList( "create table test (text VARCHAR(255))", "insert into `test` (`text`) values ('a b')" ); @@ -303,7 +288,15 @@ private void splitAndCompare(String script, List expected) { private List doSplit(String script) { final List statements = new ArrayList<>(); - ScriptUtils.splitSqlScript("ignored", script, DEFAULT_STATEMENT_SEPARATOR, DEFAULT_COMMENT_PREFIX, DEFAULT_BLOCK_COMMENT_START_DELIMITER, DEFAULT_BLOCK_COMMENT_END_DELIMITER, statements); + ScriptUtils.splitSqlScript( + "ignored", + script, + ScriptUtils.DEFAULT_STATEMENT_SEPARATOR, + ScriptUtils.DEFAULT_COMMENT_PREFIX, + ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER, + ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER, + statements + ); return statements; } } diff --git a/modules/db2/src/main/java/org/testcontainers/containers/Db2Container.java b/modules/db2/src/main/java/org/testcontainers/containers/Db2Container.java index c1a252936ea..29e2ce8aa07 100644 --- a/modules/db2/src/main/java/org/testcontainers/containers/Db2Container.java +++ b/modules/db2/src/main/java/org/testcontainers/containers/Db2Container.java @@ -20,10 +20,13 @@ public class Db2Container extends JdbcDatabaseContainer { @Deprecated public static final String DEFAULT_TAG = "11.5.0.0a"; + public static final int DB2_PORT = 50000; private String databaseName = "test"; + private String username = "db2inst1"; + private String password = "foobar1234"; /** @@ -40,11 +43,11 @@ public Db2Container(String dockerImageName) { public Db2Container(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withPrivilegedMode(true); - this.waitStrategy = new LogMessageWaitStrategy() + this.waitStrategy = + new LogMessageWaitStrategy() .withRegEx(".*Setup has completed\\..*") .withStartupTimeout(Duration.of(10, ChronoUnit.MINUTES)); @@ -69,10 +72,12 @@ protected void configure() { addEnv("DB2INST1_PASSWORD", password); // These settings help the DB2 container start faster - if (!getEnvMap().containsKey("AUTOCONFIG")) + if (!getEnvMap().containsKey("AUTOCONFIG")) { addEnv("AUTOCONFIG", "false"); - if (!getEnvMap().containsKey("ARCHIVE_LOGS")) + } + if (!getEnvMap().containsKey("ARCHIVE_LOGS")) { addEnv("ARCHIVE_LOGS", "false"); + } } /** @@ -92,8 +97,7 @@ public String getDriverClassName() { @Override public String getJdbcUrl() { String additionalUrlParams = constructUrlParameters(":", ";", ";"); - return "jdbc:db2://" + getHost() + ":" + getMappedPort(DB2_PORT) + - "/" + databaseName + additionalUrlParams; + return "jdbc:db2://" + getHost() + ":" + getMappedPort(DB2_PORT) + "/" + databaseName + additionalUrlParams; } @Override diff --git a/modules/db2/src/main/java/org/testcontainers/containers/Db2ContainerProvider.java b/modules/db2/src/main/java/org/testcontainers/containers/Db2ContainerProvider.java index 618b97c3ca6..42ac21f271b 100644 --- a/modules/db2/src/main/java/org/testcontainers/containers/Db2ContainerProvider.java +++ b/modules/db2/src/main/java/org/testcontainers/containers/Db2ContainerProvider.java @@ -3,6 +3,7 @@ import org.testcontainers.utility.DockerImageName; public class Db2ContainerProvider extends JdbcDatabaseContainerProvider { + @Override public boolean supports(String databaseType) { return databaseType.equals(Db2Container.NAME); diff --git a/modules/db2/src/test/java/org/testcontainers/jdbc/db2/DB2JDBCDriverTest.java b/modules/db2/src/test/java/org/testcontainers/jdbc/db2/DB2JDBCDriverTest.java index 2c87a4a1a65..4a03f824a28 100644 --- a/modules/db2/src/test/java/org/testcontainers/jdbc/db2/DB2JDBCDriverTest.java +++ b/modules/db2/src/test/java/org/testcontainers/jdbc/db2/DB2JDBCDriverTest.java @@ -4,18 +4,18 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class DB2JDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:db2://hostname/databasename", EnumSet.noneOf(Options.class)} - }); + return Arrays.asList( + new Object[][] { // + { "jdbc:tc:db2://hostname/databasename", EnumSet.noneOf(Options.class) }, + } + ); } } diff --git a/modules/db2/src/test/java/org/testcontainers/junit/db2/SimpleDb2Test.java b/modules/db2/src/test/java/org/testcontainers/junit/db2/SimpleDb2Test.java index b7a1d5478e8..8f3489eae95 100644 --- a/modules/db2/src/test/java/org/testcontainers/junit/db2/SimpleDb2Test.java +++ b/modules/db2/src/test/java/org/testcontainers/junit/db2/SimpleDb2Test.java @@ -1,24 +1,22 @@ package org.testcontainers.junit.db2; import org.junit.Test; +import org.testcontainers.Db2TestImages; import org.testcontainers.containers.Db2Container; import org.testcontainers.db.AbstractContainerDatabaseTest; import java.sql.ResultSet; import java.sql.SQLException; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.Db2TestImages.DB2_IMAGE; public class SimpleDb2Test extends AbstractContainerDatabaseTest { @Test public void testSimple() throws SQLException { - try (Db2Container db2 = new Db2Container(DB2_IMAGE) - .acceptLicense()) { - + try (Db2Container db2 = new Db2Container(Db2TestImages.DB2_IMAGE).acceptLicense()) { db2.start(); ResultSet resultSet = performQuery(db2, "SELECT 1 FROM SYSIBM.SYSDUMMY1"); @@ -30,10 +28,11 @@ public void testSimple() throws SQLException { @Test public void testWithAdditionalUrlParamInJdbcUrl() { - try (Db2Container db2 = new Db2Container(DB2_IMAGE) - .withUrlParam("sslConnection", "false") - .acceptLicense()) { - + try ( + Db2Container db2 = new Db2Container(Db2TestImages.DB2_IMAGE) + .withUrlParam("sslConnection", "false") + .acceptLicense() + ) { db2.start(); String jdbcUrl = db2.getJdbcUrl(); diff --git a/modules/dynalite/src/main/java/org/testcontainers/dynamodb/DynaliteContainer.java b/modules/dynalite/src/main/java/org/testcontainers/dynamodb/DynaliteContainer.java index 8900964a8bb..401fa8782b1 100644 --- a/modules/dynalite/src/main/java/org/testcontainers/dynamodb/DynaliteContainer.java +++ b/modules/dynalite/src/main/java/org/testcontainers/dynamodb/DynaliteContainer.java @@ -15,7 +15,9 @@ public class DynaliteContainer extends GenericContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("quay.io/testcontainers/dynalite"); + private static final String DEFAULT_TAG = "v1.2.1-1"; + private static final int MAPPED_PORT = 4567; /** @@ -32,13 +34,11 @@ public DynaliteContainer(String dockerImageName) { public DynaliteContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(MAPPED_PORT); } - /** * Gets a preconfigured {@link AmazonDynamoDB} client object for connecting to this * container. @@ -46,10 +46,11 @@ public DynaliteContainer(final DockerImageName dockerImageName) { * @return preconfigured client */ public AmazonDynamoDB getClient() { - return AmazonDynamoDBClientBuilder.standard() - .withEndpointConfiguration(getEndpointConfiguration()) - .withCredentials(getCredentials()) - .build(); + return AmazonDynamoDBClientBuilder + .standard() + .withEndpointConfiguration(getEndpointConfiguration()) + .withCredentials(getCredentials()) + .build(); } /** @@ -59,9 +60,10 @@ public AmazonDynamoDB getClient() { * @return endpoint configuration */ public AwsClientBuilder.EndpointConfiguration getEndpointConfiguration() { - return new AwsClientBuilder.EndpointConfiguration("http://" + - this.getHost() + ":" + - this.getMappedPort(MAPPED_PORT), null); + return new AwsClientBuilder.EndpointConfiguration( + "http://" + this.getHost() + ":" + this.getMappedPort(MAPPED_PORT), + null + ); } /** @@ -72,6 +74,4 @@ public AwsClientBuilder.EndpointConfiguration getEndpointConfiguration() { public AWSCredentialsProvider getCredentials() { return new AWSStaticCredentialsProvider(new BasicAWSCredentials("dummy", "dummy")); } - - } diff --git a/modules/dynalite/src/test/java/org/testcontainers/dynamodb/DynaliteContainerTest.java b/modules/dynalite/src/test/java/org/testcontainers/dynamodb/DynaliteContainerTest.java index 0b440939139..ced5931de31 100644 --- a/modules/dynalite/src/test/java/org/testcontainers/dynamodb/DynaliteContainerTest.java +++ b/modules/dynalite/src/test/java/org/testcontainers/dynamodb/DynaliteContainerTest.java @@ -18,17 +18,20 @@ public class DynaliteContainerTest { - private static final DockerImageName DYNALITE_IMAGE = DockerImageName.parse("quay.io/testcontainers/dynalite:v1.2.1-1"); + private static final DockerImageName DYNALITE_IMAGE = DockerImageName.parse( + "quay.io/testcontainers/dynalite:v1.2.1-1" + ); @Rule public DynaliteContainer dynamoDB = new DynaliteContainer(DYNALITE_IMAGE); @Test public void simpleTestWithManualClientCreation() { - final AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() - .withEndpointConfiguration(dynamoDB.getEndpointConfiguration()) - .withCredentials(dynamoDB.getCredentials()) - .build(); + final AmazonDynamoDB client = AmazonDynamoDBClientBuilder + .standard() + .withEndpointConfiguration(dynamoDB.getEndpointConfiguration()) + .withCredentials(dynamoDB.getCredentials()) + .build(); runTest(client); } @@ -42,13 +45,10 @@ public void simpleTestWithProvidedClient() { private void runTest(AmazonDynamoDB client) { CreateTableRequest request = new CreateTableRequest() - .withAttributeDefinitions(new AttributeDefinition( - "Name", ScalarAttributeType.S)) - .withKeySchema(new KeySchemaElement("Name", KeyType.HASH)) - .withProvisionedThroughput(new ProvisionedThroughput( - 10L, 10L)) - .withTableName("foo"); - + .withAttributeDefinitions(new AttributeDefinition("Name", ScalarAttributeType.S)) + .withKeySchema(new KeySchemaElement("Name", KeyType.HASH)) + .withProvisionedThroughput(new ProvisionedThroughput(10L, 10L)) + .withTableName("foo"); client.createTable(request); @@ -56,6 +56,10 @@ private void runTest(AmazonDynamoDB client) { assertNotNull("the description is not null", tableDescription); assertEquals("the table has the right name", "foo", tableDescription.getTableName()); - assertEquals("the name has the right primary key", "Name", tableDescription.getKeySchema().get(0).getAttributeName()); + assertEquals( + "the name has the right primary key", + "Name", + tableDescription.getKeySchema().get(0).getAttributeName() + ); } } diff --git a/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java b/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java index ac0b367f403..5a64a5e67a2 100644 --- a/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java +++ b/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java @@ -11,8 +11,6 @@ import org.testcontainers.utility.ComparableVersion; import org.testcontainers.utility.DockerImageName; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; import java.io.ByteArrayInputStream; import java.net.InetSocketAddress; import java.security.KeyStore; @@ -20,6 +18,9 @@ import java.security.cert.CertificateFactory; import java.util.Optional; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + /** * Represents an elasticsearch docker instance which exposes by default port 9200 and 9300 (transport.tcp.port) * The docker image is by default fetched from docker.elastic.co/elasticsearch/elasticsearch @@ -47,8 +48,13 @@ public class ElasticsearchContainer extends GenericContainer caCertAsBytes = Optional.empty(); + private String certPath = "/usr/share/elasticsearch/config/certs/http_ca.crt"; /** @@ -83,7 +92,6 @@ public ElasticsearchContainer(String dockerImageName) { */ public ElasticsearchContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME, DEFAULT_OSS_IMAGE_NAME); this.isOss = dockerImageName.isCompatibleWith(DEFAULT_OSS_IMAGE_NAME); @@ -91,7 +99,8 @@ public ElasticsearchContainer(final DockerImageName dockerImageName) { withNetworkAliases("elasticsearch-" + Base58.randomString(6)); withEnv("discovery.type", "single-node"); addExposedPorts(ELASTICSEARCH_DEFAULT_PORT, ELASTICSEARCH_DEFAULT_TCP_PORT); - this.isAtLeastMajorVersion8 = new ComparableVersion(dockerImageName.getVersionPart()).isGreaterThanOrEqualTo("8.0.0"); + this.isAtLeastMajorVersion8 = + new ComparableVersion(dockerImageName.getVersionPart()).isGreaterThanOrEqualTo("8.0.0"); // regex that // matches 8.0 JSON logging with no whitespace between message field and content // matches 7.x JSON logging with whitespace between message field and content @@ -159,8 +168,9 @@ public SSLContext createSslContextFromCa() { */ public ElasticsearchContainer withPassword(String password) { if (isOss) { - throw new IllegalArgumentException("You can not activate security on Elastic OSS Image. " + - "Please switch to the default distribution"); + throw new IllegalArgumentException( + "You can not activate security on Elastic OSS Image. " + "Please switch to the default distribution" + ); } withEnv("ELASTIC_PASSWORD", password); if (!isAtLeastMajorVersion8) { diff --git a/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java b/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java index 5b6b5ce3194..4427163ca56 100644 --- a/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java +++ b/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java @@ -25,12 +25,13 @@ import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.MountableFile; -import javax.net.ssl.SSLHandshakeException; import java.io.IOException; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.is; +import javax.net.ssl.SSLHandshakeException; + import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; import static org.rnorth.visibleassertions.VisibleAssertions.assertThrows; public class ElasticsearchContainerTest { @@ -39,10 +40,10 @@ public class ElasticsearchContainerTest { * Elasticsearch version which should be used for the Tests */ private static final String ELASTICSEARCH_VERSION = "7.9.2"; - private static final DockerImageName ELASTICSEARCH_IMAGE = - DockerImageName - .parse("docker.elastic.co/elasticsearch/elasticsearch") - .withTag(ELASTICSEARCH_VERSION); + + private static final DockerImageName ELASTICSEARCH_IMAGE = DockerImageName + .parse("docker.elastic.co/elasticsearch/elasticsearch") + .withTag(ELASTICSEARCH_VERSION); /** * Elasticsearch default username, when secured @@ -55,6 +56,7 @@ public class ElasticsearchContainerTest { private static final String ELASTICSEARCH_PASSWORD = "changeme"; private RestClient client = null; + private RestClient anonymousClient = null; @After @@ -74,8 +76,8 @@ public void stopRestClient() throws IOException { @Deprecated // We will remove this test in the future public void elasticsearchDeprecatedCtorTest() throws IOException { // Create the elasticsearch container. - try (ElasticsearchContainer container = new ElasticsearchContainer() - .withEnv("foo", "bar") // dummy env for compiler checking correct generics usage + try ( + ElasticsearchContainer container = new ElasticsearchContainer().withEnv("foo", "bar") // dummy env for compiler checking correct generics usage ) { // Start the container. This step might take some time... container.start(); @@ -96,8 +98,8 @@ public void elasticsearchDeprecatedCtorTest() throws IOException { @Test public void elasticsearchDefaultTest() throws IOException { // Create the elasticsearch container. - try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE) - .withEnv("foo", "bar") // dummy env for compiler checking correct generics usage + try ( + ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE).withEnv("foo", "bar") // dummy env for compiler checking correct generics usage ) { // Start the container. This step might take some time... container.start(); @@ -117,14 +119,18 @@ public void elasticsearchDefaultTest() throws IOException { @Test public void elasticsearchSecuredTest() throws IOException { - try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE) - .withPassword(ELASTICSEARCH_PASSWORD)) { + try ( + ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE) + .withPassword(ELASTICSEARCH_PASSWORD) + ) { container.start(); // The cluster should be secured so it must fail when we try to access / without credentials - assertThrows("We should not be able to access / URI with an anonymous client.", + assertThrows( + "We should not be able to access / URI with an anonymous client.", ResponseException.class, - () -> getAnonymousClient(container).performRequest(new Request("GET", "/"))); + () -> getAnonymousClient(container).performRequest(new Request("GET", "/")) + ); // But it should work when we try to access / with the proper login and password Response response = getClient(container).performRequest(new Request("GET", "/")); @@ -146,22 +152,24 @@ public void elasticsearchVersion() throws IOException { @Test public void elasticsearchOssImage() throws IOException { - try (ElasticsearchContainer container = - // ossContainer { - new ElasticsearchContainer( - DockerImageName - .parse("docker.elastic.co/elasticsearch/elasticsearch-oss") - .withTag(ELASTICSEARCH_VERSION) - ) - // } + try ( + // ossContainer { + ElasticsearchContainer container = new ElasticsearchContainer( + DockerImageName + .parse("docker.elastic.co/elasticsearch/elasticsearch-oss") + .withTag(ELASTICSEARCH_VERSION) + ) + // } ) { container.start(); Response response = getClient(container).performRequest(new Request("GET", "/")); assertThat(response.getStatusLine().getStatusCode(), is(200)); // The OSS image does not have any feature under Elastic License - assertThrows("We should not have /_xpack endpoint with an OSS License", + assertThrows( + "We should not have /_xpack endpoint with an OSS License", ResponseException.class, - () -> getClient(container).performRequest(new Request("GET", "/_xpack/"))); + () -> getClient(container).performRequest(new Request("GET", "/_xpack/")) + ); } } @@ -175,12 +183,18 @@ public void restClientClusterHealth() throws IOException { // Do whatever you want with the rest client ... final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, - new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD)); - - client = RestClient.builder(HttpHost.create(container.getHttpHostAddress())) - .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)) - .build(); + credentialsProvider.setCredentials( + AuthScope.ANY, + new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD) + ); + + client = + RestClient + .builder(HttpHost.create(container.getHttpHostAddress())) + .setHttpClientConfigCallback(httpClientBuilder -> { + return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + }) + .build(); Response response = client.performRequest(new Request("GET", "/_cluster/health")); // }} @@ -195,20 +209,28 @@ public void restClientClusterHealth() throws IOException { public void restClientSecuredClusterHealth() throws IOException { // httpClientSecuredContainer { // Create the elasticsearch container. - try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE) - // With a password - .withPassword(ELASTICSEARCH_PASSWORD)) { + try ( + ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE) + // With a password + .withPassword(ELASTICSEARCH_PASSWORD) + ) { // Start the container. This step might take some time... container.start(); // Create the secured client. final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, - new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD)); - - client = RestClient.builder(HttpHost.create(container.getHttpHostAddress())) - .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)) - .build(); + credentialsProvider.setCredentials( + AuthScope.ANY, + new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD) + ); + + client = + RestClient + .builder(HttpHost.create(container.getHttpHostAddress())) + .setHttpClientConfigCallback(httpClientBuilder -> { + return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + }) + .build(); Response response = client.performRequest(new Request("GET", "/_cluster/health")); // }} @@ -224,7 +246,7 @@ public void restClientSecuredClusterHealth() throws IOException { public void transportClientClusterHealth() { // transportClientContainer { // Create the elasticsearch container. - try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)){ + try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)) { // Start the container. This step might take some time... container.start(); @@ -232,8 +254,10 @@ public void transportClientClusterHealth() { TransportAddress transportAddress = new TransportAddress(container.getTcpHost()); String expectedClusterName = "docker-cluster"; Settings settings = Settings.builder().put("cluster.name", expectedClusterName).build(); - try (TransportClient transportClient = new PreBuiltTransportClient(settings) - .addTransportAddress(transportAddress)) { + try ( + TransportClient transportClient = new PreBuiltTransportClient(settings) + .addTransportAddress(transportAddress) + ) { ClusterHealthResponse healths = transportClient.admin().cluster().prepareHealth().get(); String clusterName = healths.getClusterName(); // }}} @@ -247,19 +271,27 @@ public void transportClientClusterHealth() { @Test public void incompatibleSettingsTest() { // The OSS image can not use security feature - assertThrows("We should not be able to activate security with an OSS License", + assertThrows( + "We should not be able to activate security with an OSS License", IllegalArgumentException.class, - () -> new ElasticsearchContainer( - DockerImageName - .parse("docker.elastic.co/elasticsearch/elasticsearch-oss") - .withTag(ELASTICSEARCH_VERSION)) - .withPassword("foo") + () -> { + new ElasticsearchContainer( + DockerImageName + .parse("docker.elastic.co/elasticsearch/elasticsearch-oss") + .withTag(ELASTICSEARCH_VERSION) + ) + .withPassword("foo"); + } ); } @Test public void testElasticsearch8SecureByDefault() throws Exception { - try (ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.1.2")) { + try ( + ElasticsearchContainer container = new ElasticsearchContainer( + "docker.elastic.co/elasticsearch/elasticsearch:8.1.2" + ) + ) { // Start the container. This step might take some time... container.start(); @@ -273,29 +305,40 @@ public void testElasticsearch8SecureByDefault() throws Exception { public void testElasticsearch8SecureByDefaultCustomCaCertFails() throws Exception { final MountableFile mountableFile = MountableFile.forClasspathResource("http_ca.crt"); String caPath = "/tmp/http_ca.crt"; - try (ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.1.2") - .withCopyToContainer(mountableFile, caPath) - .withCertPath(caPath)) { - + try ( + ElasticsearchContainer container = new ElasticsearchContainer( + "docker.elastic.co/elasticsearch/elasticsearch:8.1.2" + ) + .withCopyToContainer(mountableFile, caPath) + .withCertPath(caPath) + ) { container.start(); // this is expected, as a different cert is used for creating the SSL context - assertThrows("PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors", SSLHandshakeException.class, () -> getClusterHealth(container)); + assertThrows( + "PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors", + SSLHandshakeException.class, + () -> getClusterHealth(container) + ); } } @Test public void testElasticsearch8SecureByDefaultHttpWaitStrategy() throws Exception { - final HttpWaitStrategy httpsWaitStrategy = Wait.forHttps("/") + final HttpWaitStrategy httpsWaitStrategy = Wait + .forHttps("/") .forPort(9200) .forStatusCode(200) .withBasicCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD) // trusting self-signed certificate .allowInsecure(); - try (ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.1.2") - .waitingFor(httpsWaitStrategy)) { - + try ( + ElasticsearchContainer container = new ElasticsearchContainer( + "docker.elastic.co/elasticsearch/elasticsearch:8.1.2" + ) + .waitingFor(httpsWaitStrategy) + ) { // Start the container. This step might take some time... container.start(); @@ -311,7 +354,9 @@ public void testElasticsearch8SecureByDefaultFailsSilentlyOnLatestImages() throw // even though the version might be older than version 8 // this tags an old 7.x version as :latest tagImage("docker.elastic.co/elasticsearch/elasticsearch:7.9.2", "elasticsearch-tc-older-release", "latest"); - DockerImageName image = DockerImageName.parse("elasticsearch-tc-older-release:latest").asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"); + DockerImageName image = DockerImageName + .parse("elasticsearch-tc-older-release:latest") + .asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"); try (ElasticsearchContainer container = new ElasticsearchContainer(image)) { container.start(); @@ -324,27 +369,31 @@ public void testElasticsearch8SecureByDefaultFailsSilentlyOnLatestImages() throw private void tagImage(String sourceImage, String targetImage, String targetTag) throws InterruptedException { DockerClient dockerClient = DockerClientFactory.instance().client(); - dockerClient.tagImageCmd( - new RemoteDockerImage(DockerImageName.parse(sourceImage)).get(), - targetImage, - targetTag - ) + dockerClient + .tagImageCmd(new RemoteDockerImage(DockerImageName.parse(sourceImage)).get(), targetImage, targetTag) .exec(); } private Response getClusterHealth(ElasticsearchContainer container) throws IOException { // Create the secured client. final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, - new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ElasticsearchContainer.ELASTICSEARCH_DEFAULT_PASSWORD)); + credentialsProvider.setCredentials( + AuthScope.ANY, + new UsernamePasswordCredentials( + ELASTICSEARCH_USERNAME, + ElasticsearchContainer.ELASTICSEARCH_DEFAULT_PASSWORD + ) + ); - client = RestClient.builder(HttpHost.create("https://" + container.getHttpHostAddress())) - .setHttpClientConfigCallback(httpClientBuilder -> { - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - httpClientBuilder.setSSLContext(container.createSslContextFromCa()); - return httpClientBuilder; - }) - .build(); + client = + RestClient + .builder(HttpHost.create("https://" + container.getHttpHostAddress())) + .setHttpClientConfigCallback(httpClientBuilder -> { + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + httpClientBuilder.setSSLContext(container.createSslContextFromCa()); + return httpClientBuilder; + }) + .build(); return client.performRequest(new Request("GET", "/_cluster/health")); } @@ -352,12 +401,18 @@ private Response getClusterHealth(ElasticsearchContainer container) throws IOExc private RestClient getClient(ElasticsearchContainer container) { if (client == null) { final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, - new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD)); - - client = RestClient.builder(HttpHost.create(container.getHttpHostAddress())) - .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)) - .build(); + credentialsProvider.setCredentials( + AuthScope.ANY, + new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD) + ); + + client = + RestClient + .builder(HttpHost.create(container.getHttpHostAddress())) + .setHttpClientConfigCallback(httpClientBuilder -> { + return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + }) + .build(); } return client; diff --git a/modules/gcloud/src/main/java/org/testcontainers/containers/BigtableEmulatorContainer.java b/modules/gcloud/src/main/java/org/testcontainers/containers/BigtableEmulatorContainer.java index 4b81e3964ce..84515fc7244 100644 --- a/modules/gcloud/src/main/java/org/testcontainers/containers/BigtableEmulatorContainer.java +++ b/modules/gcloud/src/main/java/org/testcontainers/containers/BigtableEmulatorContainer.java @@ -13,19 +13,20 @@ */ public class BigtableEmulatorContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "gcr.io/google.com/cloudsdktool/cloud-sdk" + ); private static final String CMD = "gcloud beta emulators bigtable start --host-port 0.0.0.0:9000"; + private static final int PORT = 9000; public BigtableEmulatorContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(PORT); - setWaitStrategy(new LogMessageWaitStrategy() - .withRegEx("(?s).*running.*$")); + setWaitStrategy(new LogMessageWaitStrategy().withRegEx("(?s).*running.*$")); withCommand("/bin/sh", "-c", CMD); } diff --git a/modules/gcloud/src/main/java/org/testcontainers/containers/DatastoreEmulatorContainer.java b/modules/gcloud/src/main/java/org/testcontainers/containers/DatastoreEmulatorContainer.java index 58e5c023a0e..b0716829875 100644 --- a/modules/gcloud/src/main/java/org/testcontainers/containers/DatastoreEmulatorContainer.java +++ b/modules/gcloud/src/main/java/org/testcontainers/containers/DatastoreEmulatorContainer.java @@ -12,14 +12,17 @@ */ public class DatastoreEmulatorContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "gcr.io/google.com/cloudsdktool/cloud-sdk" + ); + + private static final String CMD = + "gcloud beta emulators datastore start --project test-project --host-port 0.0.0.0:8081"; - private static final String CMD = "gcloud beta emulators datastore start --project test-project --host-port 0.0.0.0:8081"; private static final int HTTP_PORT = 8081; public DatastoreEmulatorContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(HTTP_PORT); diff --git a/modules/gcloud/src/main/java/org/testcontainers/containers/FirestoreEmulatorContainer.java b/modules/gcloud/src/main/java/org/testcontainers/containers/FirestoreEmulatorContainer.java index c36082dfeb6..a04c1e5831f 100644 --- a/modules/gcloud/src/main/java/org/testcontainers/containers/FirestoreEmulatorContainer.java +++ b/modules/gcloud/src/main/java/org/testcontainers/containers/FirestoreEmulatorContainer.java @@ -12,19 +12,20 @@ */ public class FirestoreEmulatorContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "gcr.io/google.com/cloudsdktool/cloud-sdk" + ); private static final String CMD = "gcloud beta emulators firestore start --host-port 0.0.0.0:8080"; + private static final int PORT = 8080; public FirestoreEmulatorContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(PORT); - setWaitStrategy(new LogMessageWaitStrategy() - .withRegEx("(?s).*running.*$")); + setWaitStrategy(new LogMessageWaitStrategy().withRegEx("(?s).*running.*$")); withCommand("/bin/sh", "-c", CMD); } diff --git a/modules/gcloud/src/main/java/org/testcontainers/containers/PubSubEmulatorContainer.java b/modules/gcloud/src/main/java/org/testcontainers/containers/PubSubEmulatorContainer.java index 231f7626044..8d9f76e44ae 100644 --- a/modules/gcloud/src/main/java/org/testcontainers/containers/PubSubEmulatorContainer.java +++ b/modules/gcloud/src/main/java/org/testcontainers/containers/PubSubEmulatorContainer.java @@ -12,19 +12,20 @@ */ public class PubSubEmulatorContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "gcr.io/google.com/cloudsdktool/cloud-sdk" + ); private static final String CMD = "gcloud beta emulators pubsub start --host-port 0.0.0.0:8085"; + private static final int PORT = 8085; public PubSubEmulatorContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(8085); - setWaitStrategy(new LogMessageWaitStrategy() - .withRegEx("(?s).*started.*$")); + setWaitStrategy(new LogMessageWaitStrategy().withRegEx("(?s).*started.*$")); withCommand("/bin/sh", "-c", CMD); } diff --git a/modules/gcloud/src/main/java/org/testcontainers/containers/SpannerEmulatorContainer.java b/modules/gcloud/src/main/java/org/testcontainers/containers/SpannerEmulatorContainer.java index 0ae8e89dc06..dc45b004c6c 100644 --- a/modules/gcloud/src/main/java/org/testcontainers/containers/SpannerEmulatorContainer.java +++ b/modules/gcloud/src/main/java/org/testcontainers/containers/SpannerEmulatorContainer.java @@ -10,19 +10,20 @@ */ public class SpannerEmulatorContainer extends GenericContainer { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "gcr.io/cloud-spanner-emulator/emulator" + ); private static final int GRPC_PORT = 9010; + private static final int HTTP_PORT = 9020; public SpannerEmulatorContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(GRPC_PORT, HTTP_PORT); - setWaitStrategy(new LogMessageWaitStrategy() - .withRegEx(".*Cloud Spanner emulator running\\..*")); + setWaitStrategy(new LogMessageWaitStrategy().withRegEx(".*Cloud Spanner emulator running\\..*")); } /** diff --git a/modules/gcloud/src/test/java/org/testcontainers/containers/BigtableEmulatorContainerTest.java b/modules/gcloud/src/test/java/org/testcontainers/containers/BigtableEmulatorContainerTest.java index 4ba59a75488..3e22231220b 100644 --- a/modules/gcloud/src/test/java/org/testcontainers/containers/BigtableEmulatorContainerTest.java +++ b/modules/gcloud/src/test/java/org/testcontainers/containers/BigtableEmulatorContainerTest.java @@ -1,22 +1,13 @@ package org.testcontainers.containers; -import static org.assertj.core.api.Assertions.assertThat; - -import com.google.api.core.ApiFuture; -import com.google.api.gax.batching.Batcher; import com.google.api.gax.core.CredentialsProvider; import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.rpc.FixedTransportChannelProvider; import com.google.api.gax.rpc.TransportChannelProvider; -import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminClient; import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; -import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest; import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; -import com.google.cloud.bigtable.admin.v2.models.Instance; import com.google.cloud.bigtable.admin.v2.models.Table; -import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStub; -import com.google.cloud.bigtable.admin.v2.stub.BigtableInstanceAdminStubSettings; import com.google.cloud.bigtable.admin.v2.stub.BigtableTableAdminStubSettings; import com.google.cloud.bigtable.admin.v2.stub.EnhancedBigtableTableAdminStub; import com.google.cloud.bigtable.data.v2.BigtableDataClient; @@ -24,20 +15,22 @@ import com.google.cloud.bigtable.data.v2.models.Row; import com.google.cloud.bigtable.data.v2.models.RowCell; import com.google.cloud.bigtable.data.v2.models.RowMutation; -import com.google.cloud.bigtable.data.v2.models.RowMutationEntry; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.io.IOException; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.ExecutionException; import org.junit.Rule; import org.junit.Test; import org.testcontainers.utility.DockerImageName; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + public class BigtableEmulatorContainerTest { public static final String PROJECT_ID = "test-project"; + public static final String INSTANCE_ID = "test-instance"; @Rule @@ -45,28 +38,31 @@ public class BigtableEmulatorContainerTest { public BigtableEmulatorContainer emulator = new BigtableEmulatorContainer( DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators") ); + // } @Test // testWithEmulatorContainer { public void testSimple() throws IOException, InterruptedException, ExecutionException { - ManagedChannel channel = ManagedChannelBuilder.forTarget(emulator.getEmulatorEndpoint()) - .usePlaintext().build(); + ManagedChannel channel = ManagedChannelBuilder.forTarget(emulator.getEmulatorEndpoint()).usePlaintext().build(); - TransportChannelProvider channelProvider = FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)); + TransportChannelProvider channelProvider = FixedTransportChannelProvider.create( + GrpcTransportChannel.create(channel) + ); NoCredentialsProvider credentialsProvider = NoCredentialsProvider.create(); try { - createTable(channelProvider, credentialsProvider, "test-table" ); + createTable(channelProvider, credentialsProvider, "test-table"); - BigtableDataClient client = BigtableDataClient.create(BigtableDataSettings - .newBuilderForEmulator(emulator.getHost(), emulator.getEmulatorPort()) - .setProjectId(PROJECT_ID) - .setInstanceId(INSTANCE_ID) - .build()); + BigtableDataClient client = BigtableDataClient.create( + BigtableDataSettings + .newBuilderForEmulator(emulator.getHost(), emulator.getEmulatorPort()) + .setProjectId(PROJECT_ID) + .setInstanceId(INSTANCE_ID) + .build() + ); - client.mutateRow(RowMutation.create("test-table", "1") - .setCell("name", "firstName", "Ray")); + client.mutateRow(RowMutation.create("test-table", "1").setCell("name", "firstName", "Ray")); Row row = client.readRow("test-table", "1"); List cells = row.getCells("name", "firstName"); @@ -77,15 +73,22 @@ public void testSimple() throws IOException, InterruptedException, ExecutionExce channel.shutdown(); } } + // } // createTable { - private void createTable(TransportChannelProvider channelProvider, CredentialsProvider credentialsProvider, String tableName) throws IOException { - EnhancedBigtableTableAdminStub stub = EnhancedBigtableTableAdminStub - .createEnhanced(BigtableTableAdminStubSettings.newBuilder() + private void createTable( + TransportChannelProvider channelProvider, + CredentialsProvider credentialsProvider, + String tableName + ) throws IOException { + EnhancedBigtableTableAdminStub stub = EnhancedBigtableTableAdminStub.createEnhanced( + BigtableTableAdminStubSettings + .newBuilder() .setTransportChannelProvider(channelProvider) .setCredentialsProvider(credentialsProvider) - .build()); + .build() + ); try (BigtableTableAdminClient client = BigtableTableAdminClient.create(PROJECT_ID, INSTANCE_ID, stub)) { Table table = client.createTable(CreateTableRequest.of(tableName).addFamily("name")); diff --git a/modules/gcloud/src/test/java/org/testcontainers/containers/DatastoreEmulatorContainerTest.java b/modules/gcloud/src/test/java/org/testcontainers/containers/DatastoreEmulatorContainerTest.java index ba998e402ce..a7fe340791d 100644 --- a/modules/gcloud/src/test/java/org/testcontainers/containers/DatastoreEmulatorContainerTest.java +++ b/modules/gcloud/src/test/java/org/testcontainers/containers/DatastoreEmulatorContainerTest.java @@ -1,7 +1,5 @@ package org.testcontainers.containers; -import static org.assertj.core.api.Assertions.assertThat; - import com.google.cloud.NoCredentials; import com.google.cloud.ServiceOptions; import com.google.cloud.datastore.Datastore; @@ -12,6 +10,8 @@ import org.junit.Test; import org.testcontainers.utility.DockerImageName; +import static org.assertj.core.api.Assertions.assertThat; + public class DatastoreEmulatorContainerTest { @Rule @@ -19,17 +19,19 @@ public class DatastoreEmulatorContainerTest { public DatastoreEmulatorContainer emulator = new DatastoreEmulatorContainer( DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators") ); + // } // startingDatastoreEmulatorContainer { @Test public void testSimple() { - DatastoreOptions options = DatastoreOptions.newBuilder() - .setHost(emulator.getEmulatorEndpoint()) - .setCredentials(NoCredentials.getInstance()) - .setRetrySettings(ServiceOptions.getNoRetrySettings()) - .setProjectId("test-project") - .build(); + DatastoreOptions options = DatastoreOptions + .newBuilder() + .setHost(emulator.getEmulatorEndpoint()) + .setCredentials(NoCredentials.getInstance()) + .setRetrySettings(ServiceOptions.getNoRetrySettings()) + .setProjectId("test-project") + .build(); Datastore datastore = options.getService(); Key key = datastore.newKeyFactory().setKind("Task").newKey("sample"); diff --git a/modules/gcloud/src/test/java/org/testcontainers/containers/FirestoreEmulatorContainerTest.java b/modules/gcloud/src/test/java/org/testcontainers/containers/FirestoreEmulatorContainerTest.java index 04939ecc30e..c87f8e5176a 100644 --- a/modules/gcloud/src/test/java/org/testcontainers/containers/FirestoreEmulatorContainerTest.java +++ b/modules/gcloud/src/test/java/org/testcontainers/containers/FirestoreEmulatorContainerTest.java @@ -1,7 +1,5 @@ package org.testcontainers.containers; -import static org.assertj.core.api.Assertions.assertThat; - import com.google.api.core.ApiFuture; import com.google.cloud.NoCredentials; import com.google.cloud.firestore.CollectionReference; @@ -10,13 +8,16 @@ import com.google.cloud.firestore.FirestoreOptions; import com.google.cloud.firestore.QuerySnapshot; import com.google.cloud.firestore.WriteResult; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutionException; import org.junit.Rule; import org.junit.Test; import org.testcontainers.utility.DockerImageName; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + public class FirestoreEmulatorContainerTest { @Rule @@ -24,16 +25,19 @@ public class FirestoreEmulatorContainerTest { public FirestoreEmulatorContainer emulator = new FirestoreEmulatorContainer( DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators") ); + // } // testWithEmulatorContainer { @Test public void testSimple() throws ExecutionException, InterruptedException { - FirestoreOptions options = FirestoreOptions.getDefaultInstance().toBuilder() - .setHost(emulator.getEmulatorEndpoint()) - .setCredentials(NoCredentials.getInstance()) - .setProjectId("test-project") - .build(); + FirestoreOptions options = FirestoreOptions + .getDefaultInstance() + .toBuilder() + .setHost(emulator.getEmulatorEndpoint()) + .setCredentials(NoCredentials.getInstance()) + .setProjectId("test-project") + .build(); Firestore firestore = options.getService(); CollectionReference users = firestore.collection("users"); diff --git a/modules/gcloud/src/test/java/org/testcontainers/containers/PubSubEmulatorContainerTest.java b/modules/gcloud/src/test/java/org/testcontainers/containers/PubSubEmulatorContainerTest.java index 61d56a279d7..aeb92bc4a69 100644 --- a/modules/gcloud/src/test/java/org/testcontainers/containers/PubSubEmulatorContainerTest.java +++ b/modules/gcloud/src/test/java/org/testcontainers/containers/PubSubEmulatorContainerTest.java @@ -1,7 +1,5 @@ package org.testcontainers.containers; -import static org.assertj.core.api.Assertions.assertThat; - import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.rpc.FixedTransportChannelProvider; @@ -24,11 +22,14 @@ import com.google.pubsub.v1.TopicName; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import java.io.IOException; import org.junit.Rule; import org.junit.Test; import org.testcontainers.utility.DockerImageName; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + public class PubSubEmulatorContainerTest { public static final String PROJECT_ID = "my-project-id"; @@ -38,8 +39,8 @@ public class PubSubEmulatorContainerTest { public PubSubEmulatorContainer emulator = new PubSubEmulatorContainer( DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators") ); - // } + // } @Test // testWithEmulatorContainer { @@ -47,8 +48,9 @@ public void testSimple() throws IOException { String hostport = emulator.getEmulatorEndpoint(); ManagedChannel channel = ManagedChannelBuilder.forTarget(hostport).usePlaintext().build(); try { - TransportChannelProvider channelProvider = - FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)); + TransportChannelProvider channelProvider = FixedTransportChannelProvider.create( + GrpcTransportChannel.create(channel) + ); NoCredentialsProvider credentialsProvider = NoCredentialsProvider.create(); String topicId = "my-topic-id"; @@ -57,56 +59,77 @@ public void testSimple() throws IOException { String subscriptionId = "my-subscription-id"; createSubscription(subscriptionId, topicId, channelProvider, credentialsProvider); - Publisher publisher = Publisher.newBuilder(TopicName.of(PROJECT_ID, topicId)) - .setChannelProvider(channelProvider) - .setCredentialsProvider(credentialsProvider) - .build(); + Publisher publisher = Publisher + .newBuilder(TopicName.of(PROJECT_ID, topicId)) + .setChannelProvider(channelProvider) + .setCredentialsProvider(credentialsProvider) + .build(); PubsubMessage message = PubsubMessage.newBuilder().setData(ByteString.copyFromUtf8("test message")).build(); publisher.publish(message); - SubscriberStubSettings subscriberStubSettings = - SubscriberStubSettings.newBuilder() - .setTransportChannelProvider(channelProvider) - .setCredentialsProvider(credentialsProvider) - .build(); + SubscriberStubSettings subscriberStubSettings = SubscriberStubSettings + .newBuilder() + .setTransportChannelProvider(channelProvider) + .setCredentialsProvider(credentialsProvider) + .build(); try (SubscriberStub subscriber = GrpcSubscriberStub.create(subscriberStubSettings)) { - PullRequest pullRequest = PullRequest.newBuilder() - .setMaxMessages(1) - .setSubscription(ProjectSubscriptionName.format(PROJECT_ID, subscriptionId)) - .build(); + PullRequest pullRequest = PullRequest + .newBuilder() + .setMaxMessages(1) + .setSubscription(ProjectSubscriptionName.format(PROJECT_ID, subscriptionId)) + .build(); PullResponse pullResponse = subscriber.pullCallable().call(pullRequest); assertThat(pullResponse.getReceivedMessagesList()).hasSize(1); - assertThat(pullResponse.getReceivedMessages(0).getMessage().getData().toStringUtf8()).isEqualTo("test message"); + assertThat(pullResponse.getReceivedMessages(0).getMessage().getData().toStringUtf8()) + .isEqualTo("test message"); } } finally { channel.shutdown(); } } + // } // createTopic { - private void createTopic(String topicId, TransportChannelProvider channelProvider, NoCredentialsProvider credentialsProvider) throws IOException { - TopicAdminSettings topicAdminSettings = TopicAdminSettings.newBuilder() - .setTransportChannelProvider(channelProvider) - .setCredentialsProvider(credentialsProvider) - .build(); + private void createTopic( + String topicId, + TransportChannelProvider channelProvider, + NoCredentialsProvider credentialsProvider + ) throws IOException { + TopicAdminSettings topicAdminSettings = TopicAdminSettings + .newBuilder() + .setTransportChannelProvider(channelProvider) + .setCredentialsProvider(credentialsProvider) + .build(); try (TopicAdminClient topicAdminClient = TopicAdminClient.create(topicAdminSettings)) { TopicName topicName = TopicName.of(PROJECT_ID, topicId); topicAdminClient.createTopic(topicName); } } + // } // createSubscription { - private void createSubscription(String subscriptionId, String topicId, TransportChannelProvider channelProvider, NoCredentialsProvider credentialsProvider) throws IOException { - SubscriptionAdminSettings subscriptionAdminSettings = SubscriptionAdminSettings.newBuilder() - .setTransportChannelProvider(channelProvider) - .setCredentialsProvider(credentialsProvider) - .build(); + private void createSubscription( + String subscriptionId, + String topicId, + TransportChannelProvider channelProvider, + NoCredentialsProvider credentialsProvider + ) throws IOException { + SubscriptionAdminSettings subscriptionAdminSettings = SubscriptionAdminSettings + .newBuilder() + .setTransportChannelProvider(channelProvider) + .setCredentialsProvider(credentialsProvider) + .build(); SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create(subscriptionAdminSettings); SubscriptionName subscriptionName = SubscriptionName.of(PROJECT_ID, subscriptionId); - subscriptionAdminClient.createSubscription(subscriptionName, TopicName.of(PROJECT_ID, topicId), PushConfig.getDefaultInstance(), 10); + subscriptionAdminClient.createSubscription( + subscriptionName, + TopicName.of(PROJECT_ID, topicId), + PushConfig.getDefaultInstance(), + 10 + ); } // } diff --git a/modules/gcloud/src/test/java/org/testcontainers/containers/SpannerEmulatorContainerTest.java b/modules/gcloud/src/test/java/org/testcontainers/containers/SpannerEmulatorContainerTest.java index 64b81546499..b246e7e1f0d 100644 --- a/modules/gcloud/src/test/java/org/testcontainers/containers/SpannerEmulatorContainerTest.java +++ b/modules/gcloud/src/test/java/org/testcontainers/containers/SpannerEmulatorContainerTest.java @@ -1,7 +1,5 @@ package org.testcontainers.containers; -import static org.assertj.core.api.Assertions.assertThat; - import com.google.cloud.NoCredentials; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseAdminClient; @@ -16,12 +14,15 @@ import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.Statement; -import java.util.Arrays; -import java.util.concurrent.ExecutionException; import org.junit.Rule; import org.junit.Test; import org.testcontainers.utility.DockerImageName; +import java.util.Arrays; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; + public class SpannerEmulatorContainerTest { @Rule @@ -29,20 +30,24 @@ public class SpannerEmulatorContainerTest { public SpannerEmulatorContainer emulator = new SpannerEmulatorContainer( DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator:1.4.0") ); + // } private static final String PROJECT_NAME = "test-project"; + private static final String INSTANCE_NAME = "test-instance"; + private static final String DATABASE_NAME = "test-database"; // testWithEmulatorContainer { @Test public void testSimple() throws ExecutionException, InterruptedException { - SpannerOptions options = SpannerOptions.newBuilder() - .setEmulatorHost(emulator.getEmulatorGrpcEndpoint()) - .setCredentials(NoCredentials.getInstance()) - .setProjectId(PROJECT_NAME) - .build(); + SpannerOptions options = SpannerOptions + .newBuilder() + .setEmulatorHost(emulator.getEmulatorGrpcEndpoint()) + .setCredentials(NoCredentials.getInstance()) + .setProjectId(PROJECT_NAME) + .build(); Spanner spanner = options.getService(); @@ -52,28 +57,38 @@ public void testSimple() throws ExecutionException, InterruptedException { DatabaseId databaseId = DatabaseId.of(instanceId, DATABASE_NAME); DatabaseClient dbClient = spanner.getDatabaseClient(databaseId); - dbClient.readWriteTransaction() - .run(tx -> { - String sql1 = "Delete from TestTable where 1=1"; - tx.executeUpdate(Statement.of(sql1)); - String sql = "INSERT INTO TestTable (Key, Value) VALUES (1, 'Java'), (2, 'Go')"; - tx.executeUpdate(Statement.of(sql)); - return null; - }); - - ResultSet resultSet = dbClient.readOnlyTransaction() - .executeQuery(Statement.of("select * from TestTable order by Key")); + dbClient + .readWriteTransaction() + .run(tx -> { + String sql1 = "Delete from TestTable where 1=1"; + tx.executeUpdate(Statement.of(sql1)); + String sql = "INSERT INTO TestTable (Key, Value) VALUES (1, 'Java'), (2, 'Go')"; + tx.executeUpdate(Statement.of(sql)); + return null; + }); + + ResultSet resultSet = dbClient + .readOnlyTransaction() + .executeQuery(Statement.of("select * from TestTable order by Key")); resultSet.next(); assertThat(resultSet.getLong(0)).isEqualTo(1); assertThat(resultSet.getString(1)).isEqualTo("Java"); } + // } // createDatabase { private void createDatabase(Spanner spanner) throws InterruptedException, ExecutionException { DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient(); - Database database = dbAdminClient.createDatabase(INSTANCE_NAME, DATABASE_NAME, Arrays.asList("CREATE TABLE TestTable (Key INT64, Value STRING(MAX)) PRIMARY KEY (Key)")).get(); + Database database = dbAdminClient + .createDatabase( + INSTANCE_NAME, + DATABASE_NAME, + Arrays.asList("CREATE TABLE TestTable (Key INT64, Value STRING(MAX)) PRIMARY KEY (Key)") + ) + .get(); } + // } // createInstance { @@ -81,7 +96,16 @@ private InstanceId createInstance(Spanner spanner) throws InterruptedException, InstanceConfigId instanceConfig = InstanceConfigId.of(PROJECT_NAME, "emulator-config"); InstanceId instanceId = InstanceId.of(PROJECT_NAME, INSTANCE_NAME); InstanceAdminClient insAdminClient = spanner.getInstanceAdminClient(); - Instance instance = insAdminClient.createInstance(InstanceInfo.newBuilder(instanceId).setNodeCount(1).setDisplayName("Test instance").setInstanceConfigId(instanceConfig).build()).get(); + Instance instance = insAdminClient + .createInstance( + InstanceInfo + .newBuilder(instanceId) + .setNodeCount(1) + .setDisplayName("Test instance") + .setInstanceConfigId(instanceConfig) + .build() + ) + .get(); return instanceId; } // } diff --git a/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQContainer.java b/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQContainer.java index 5bb8935c39e..242cc7bdb43 100644 --- a/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQContainer.java +++ b/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQContainer.java @@ -34,27 +34,38 @@ public class HiveMQContainer extends GenericContainer { private static final Logger LOGGER = LoggerFactory.getLogger(HiveMQContainer.class); private static final DockerImageName DEFAULT_HIVEMQ_EE_IMAGE_NAME = DockerImageName.parse("hivemq/hivemq4"); + private static final DockerImageName DEFAULT_HIVEMQ_CE_IMAGE_NAME = DockerImageName.parse("hivemq/hivemq-ce"); private static final int DEBUGGING_PORT = 9000; + private static final int MQTT_PORT = 1883; + private static final int CONTROL_CENTER_PORT = 8080; + @SuppressWarnings("OctalInteger") private static final int MODE = 0777; - private static final @NotNull Pattern EXTENSION_ID_PATTERN = Pattern.compile("(.+?)"); - private final @NotNull ConcurrentHashMap containerOutputLatches = new ConcurrentHashMap<>(); + @NotNull + private static final Pattern EXTENSION_ID_PATTERN = Pattern.compile("(.+?)"); + + @NotNull + private final ConcurrentHashMap containerOutputLatches = new ConcurrentHashMap<>(); + private boolean controlCenterEnabled = false; + private boolean debugging = false; - private final @NotNull Set prepackagedExtensionsToRemove = new HashSet<>(); + @NotNull + private final Set prepackagedExtensionsToRemove = new HashSet<>(); + private boolean removeAllPrepackagedExtensions = false; - private final @NotNull WaitAllStrategy waitStrategy = new WaitAllStrategy(); + @NotNull + private final WaitAllStrategy waitStrategy = new WaitAllStrategy(); public HiveMQContainer(final @NotNull DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_HIVEMQ_CE_IMAGE_NAME, DEFAULT_HIVEMQ_EE_IMAGE_NAME); addExposedPort(MQTT_PORT); @@ -96,13 +107,14 @@ protected void configure() { withCreateContainerCmdModifier(it -> it.withEntrypoint("/bin/sh")); if (removeAllPrepackagedExtensions || !prepackagedExtensionsToRemove.isEmpty()) { - if (removeAllPrepackagedExtensions) { removeCommand = "rm -rf /opt/hivemq/extensions/** &&"; } else { - removeCommand = prepackagedExtensionsToRemove.stream() - .map(extensionId -> "rm -rf /opt/hivemq/extensions/" + extensionId + "&&") - .collect(Collectors.joining()); + removeCommand = + prepackagedExtensionsToRemove + .stream() + .map(extensionId -> "rm -rf /opt/hivemq/extensions/" + extensionId + "&&") + .collect(Collectors.joining()); } } else { removeCommand = ""; @@ -110,16 +122,20 @@ protected void configure() { setCommand( "-c", removeCommand + - "cp -r '/opt/hivemq/temp-extensions/'* /opt/hivemq/extensions/ " + - "; rm -rf /opt/hivemq/temp-extensions/** " + - "&& chmod -R 777 /opt/hivemq/extensions " + - "&& /opt/docker-entrypoint.sh /opt/hivemq/bin/run.sh" + "cp -r '/opt/hivemq/temp-extensions/'* /opt/hivemq/extensions/ " + + "; rm -rf /opt/hivemq/temp-extensions/** " + + "&& chmod -R 777 /opt/hivemq/extensions " + + "&& /opt/docker-entrypoint.sh /opt/hivemq/bin/run.sh" ); } protected void containerIsStarted(final @NotNull InspectContainerResponse containerInfo) { if (controlCenterEnabled) { - LOGGER.info("The HiveMQ Control Center is reachable under: http://{}:{}", getHost(), getMappedPort(CONTROL_CENTER_PORT)); + LOGGER.info( + "The HiveMQ Control Center is reachable under: http://{}:{}", + getHost(), + getMappedPort(CONTROL_CENTER_PORT) + ); } } @@ -159,7 +175,10 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai public @NotNull HiveMQContainer withDebugging() { debugging = true; addExposedPorts(DEBUGGING_PORT); - withEnv("JAVA_OPTS", "-agentlib:jdwp=transport=dt_socket,address=0.0.0.0:" + DEBUGGING_PORT + ",server=y,suspend=y"); + withEnv( + "JAVA_OPTS", + "-agentlib:jdwp=transport=dt_socket,address=0.0.0.0:" + DEBUGGING_PORT + ",server=y,suspend=y" + ); return self(); } @@ -213,10 +232,16 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai public @NotNull HiveMQContainer withExtension(final @NotNull MountableFile mountableExtension) { final File extensionDir = new File(mountableExtension.getResolvedPath()); if (!extensionDir.exists()) { - throw new ContainerLaunchException("Extension '" + mountableExtension.getFilesystemPath() + "' could not be mounted. It does not exist."); + throw new ContainerLaunchException( + "Extension '" + mountableExtension.getFilesystemPath() + "' could not be mounted. It does not exist." + ); } if (!extensionDir.isDirectory()) { - throw new ContainerLaunchException("Extension '" + mountableExtension.getFilesystemPath() + "' could not be mounted. It is not a directory."); + throw new ContainerLaunchException( + "Extension '" + + mountableExtension.getFilesystemPath() + + "' could not be mounted. It is not a directory." + ); } try { final String extensionDirName = getExtensionDirectoryName(extensionDir); @@ -277,10 +302,14 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai public @NotNull HiveMQContainer withLicense(final @NotNull MountableFile mountableLicense) { final File licenseFile = new File(mountableLicense.getResolvedPath()); if (!licenseFile.exists()) { - throw new ContainerLaunchException("License file '" + mountableLicense.getFilesystemPath() + "' does not exist."); + throw new ContainerLaunchException( + "License file '" + mountableLicense.getFilesystemPath() + "' does not exist." + ); } if (!licenseFile.getName().endsWith(".lic") && !licenseFile.getName().endsWith(".elic")) { - throw new ContainerLaunchException("License file '" + mountableLicense.getFilesystemPath() + "' does not end wit '.lic' or '.elic'."); + throw new ContainerLaunchException( + "License file '" + mountableLicense.getFilesystemPath() + "' does not end wit '.lic' or '.elic'." + ); } final String containerPath = "/opt/hivemq/license/" + licenseFile.getName(); withCopyFileToContainer(cloneWithFileMode(mountableLicense), containerPath); @@ -299,7 +328,9 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai public @NotNull HiveMQContainer withHiveMQConfig(final @NotNull MountableFile mountableConfig) { final File config = new File(mountableConfig.getResolvedPath()); if (!config.exists()) { - throw new ContainerLaunchException("HiveMQ config file '" + mountableConfig.getFilesystemPath() + "' does not exist."); + throw new ContainerLaunchException( + "HiveMQ config file '" + mountableConfig.getFilesystemPath() + "' does not exist." + ); } final String containerPath = "/opt/hivemq/conf/config.xml"; withCopyFileToContainer(cloneWithFileMode(mountableConfig), containerPath); @@ -320,8 +351,8 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai */ public @NotNull HiveMQContainer withFileInExtensionHomeFolder( final @NotNull MountableFile file, - final @NotNull String extensionId) { - + final @NotNull String extensionId + ) { return withFileInExtensionHomeFolder(file, extensionId, ""); } @@ -340,9 +371,12 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai public @NotNull HiveMQContainer withFileInExtensionHomeFolder( final @NotNull MountableFile file, final @NotNull String extensionId, - final @NotNull String pathInExtensionHome) { - - return withFileInHomeFolder(file, "/temp-extensions/" + extensionId + PathUtil.prepareAppendPath(pathInExtensionHome)); + final @NotNull String pathInExtensionHome + ) { + return withFileInHomeFolder( + file, + "/temp-extensions/" + extensionId + PathUtil.prepareAppendPath(pathInExtensionHome) + ); } /** @@ -356,8 +390,8 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai */ public @NotNull HiveMQContainer withFileInHomeFolder( final @NotNull MountableFile mountableFile, - final @NotNull String pathInHomeFolder) { - + final @NotNull String pathInHomeFolder + ) { final File file = new File(mountableFile.getResolvedPath()); if (pathInHomeFolder.trim().isEmpty()) { @@ -388,11 +422,12 @@ protected void containerIsStarted(final @NotNull InspectContainerResponse contai public void disableExtension( final @NotNull String extensionName, final @NotNull String extensionDirectory, - final @NotNull Duration timeout) throws TimeoutException { - + final @NotNull Duration timeout + ) throws TimeoutException { final String regEX = "(.*)Extension \"" + extensionName + "\" version (.*) stopped successfully(.*)"; try { - final String containerPath = "/opt/hivemq/extensions" + PathUtil.prepareInnerPath(extensionDirectory) + "DISABLED"; + final String containerPath = + "/opt/hivemq/extensions" + PathUtil.prepareInnerPath(extensionDirectory) + "DISABLED"; final CountDownLatch latch = new CountDownLatch(1); containerOutputLatches.put(regEX, latch); @@ -402,9 +437,13 @@ public void disableExtension( final boolean await = latch.await(timeout.getSeconds(), TimeUnit.SECONDS); if (!await) { - throw new TimeoutException("Extension disabling timed out after '" + timeout.getSeconds() + "' seconds. " + + throw new TimeoutException( + "Extension disabling timed out after '" + + timeout.getSeconds() + + "' seconds. " + "Maybe you are using a HiveMQ Community Edition image, " + - "which does not support disabling of extensions"); + "which does not support disabling of extensions" + ); } } catch (final InterruptedException | IOException e) { throw new RuntimeException(e); @@ -424,9 +463,8 @@ public void disableExtension( * @param extensionDirectory the name of the extension's directory * @throws TimeoutException if the extension was not disabled within 60 seconds */ - public void disableExtension( - final @NotNull String extensionName, - final @NotNull String extensionDirectory) throws TimeoutException { + public void disableExtension(final @NotNull String extensionName, final @NotNull String extensionDirectory) + throws TimeoutException { disableExtension(extensionName, extensionDirectory, Duration.ofSeconds(60)); } @@ -441,9 +479,8 @@ public void disableExtension( * @param timeout the timeout * @throws TimeoutException if the extension was not disabled within the configured timeout */ - public void disableExtension( - final @NotNull HiveMQExtension hiveMQExtension, - final @NotNull Duration timeout) throws TimeoutException { + public void disableExtension(final @NotNull HiveMQExtension hiveMQExtension, final @NotNull Duration timeout) + throws TimeoutException { disableExtension(hiveMQExtension.getName(), hiveMQExtension.getId(), timeout); } @@ -476,11 +513,12 @@ public void disableExtension(final @NotNull HiveMQExtension hiveMQExtension) thr public void enableExtension( final @NotNull String extensionName, final @NotNull String extensionDirectory, - final @NotNull Duration timeout) throws TimeoutException { - + final @NotNull Duration timeout + ) throws TimeoutException { final String regEX = "(.*)Extension \"" + extensionName + "\" version (.*) started successfully(.*)"; try { - final String containerPath = "/opt/hivemq/extensions" + PathUtil.prepareInnerPath(extensionDirectory) + "DISABLED"; + final String containerPath = + "/opt/hivemq/extensions" + PathUtil.prepareInnerPath(extensionDirectory) + "DISABLED"; final CountDownLatch latch = new CountDownLatch(1); containerOutputLatches.put(regEX, latch); @@ -490,9 +528,13 @@ public void enableExtension( final boolean await = latch.await(timeout.getSeconds(), TimeUnit.SECONDS); if (!await) { - throw new TimeoutException("Extension enabling timed out after '" + timeout.getSeconds() + "' seconds. " + + throw new TimeoutException( + "Extension enabling timed out after '" + + timeout.getSeconds() + + "' seconds. " + "Maybe you are using a HiveMQ Community Edition image, " + - "which does not support disabling of extensions"); + "which does not support disabling of extensions" + ); } } catch (final InterruptedException | IOException e) { throw new RuntimeException(e); @@ -512,9 +554,8 @@ public void enableExtension( * @param extensionDirectory the name of the extension's directory * @throws TimeoutException if the extension was not enabled within 60 seconds */ - public void enableExtension( - final @NotNull String extensionName, - final @NotNull String extensionDirectory) throws TimeoutException { + public void enableExtension(final @NotNull String extensionName, final @NotNull String extensionDirectory) + throws TimeoutException { enableExtension(extensionName, extensionDirectory, Duration.ofSeconds(60)); } @@ -529,9 +570,8 @@ public void enableExtension( * @param timeout the timeout * @throws TimeoutException if the extension was not enabled within the configured timeout */ - public void enableExtension( - final @NotNull HiveMQExtension hiveMQExtension, - final @NotNull Duration timeout) throws TimeoutException { + public void enableExtension(final @NotNull HiveMQExtension hiveMQExtension, final @NotNull Duration timeout) + throws TimeoutException { enableExtension(hiveMQExtension.getName(), hiveMQExtension.getId(), timeout); } diff --git a/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQExtension.java b/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQExtension.java index 934dfd0c29c..91e984835d6 100644 --- a/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQExtension.java +++ b/modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQExtension.java @@ -1,7 +1,5 @@ package org.testcontainers.hivemq; -import javassist.ClassPool; -import javassist.NotFoundException; import lombok.Getter; import org.apache.commons.io.FileUtils; import org.jboss.shrinkwrap.api.ExtensionLoader; @@ -23,28 +21,35 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import javassist.ClassPool; +import javassist.NotFoundException; public class HiveMQExtension { private static final String VALID_EXTENSION_XML = "" + // - " %s" + // - " %s" + // - " %s" + // - " %s" + // - " %s" + // - ""; + " %s" + // + " %s" + // + " %s" + // + " %s" + // + " %s" + // + ""; + private static final String EXTENSION_MAIN_CLASS_NAME = "com.hivemq.extension.sdk.api.ExtensionMain"; + private static final Logger LOGGER = LoggerFactory.getLogger(HiveMQExtension.class); @Getter - private final @NotNull String id; + @NotNull + private final String id; @Getter - private final @NotNull String name; + @NotNull + private final String name; @Getter - private final @NotNull String version; + @NotNull + private final String version; @Getter private final int priority; @@ -56,9 +61,11 @@ public class HiveMQExtension { private final boolean disabledOnStartup; @Getter - private final @NotNull Class mainClass; + @NotNull + private final Class mainClass; - private final @NotNull List> additionalClasses; + @NotNull + private final List> additionalClasses; private HiveMQExtension( final @NotNull String id, @@ -68,8 +75,8 @@ private HiveMQExtension( final int startPriority, final boolean disabledOnStartup, final @NotNull Class mainClass, - final @NotNull List> additionalClasses) { - + final @NotNull List> additionalClasses + ) { this.id = id; this.name = name; this.version = version; @@ -80,27 +87,31 @@ private HiveMQExtension( this.additionalClasses = additionalClasses; } - @NotNull File createExtension(final @NotNull HiveMQExtension hiveMQExtension) - throws Exception { - + @NotNull + File createExtension(final @NotNull HiveMQExtension hiveMQExtension) throws Exception { final File tempDir = Files.createTempDirectory("").toFile(); final File extensionDir = new File(tempDir, hiveMQExtension.getId()); - FileUtils.writeStringToFile(new File(extensionDir, "hivemq-extension.xml"), + FileUtils.writeStringToFile( + new File(extensionDir, "hivemq-extension.xml"), String.format( VALID_EXTENSION_XML, hiveMQExtension.getId(), hiveMQExtension.getName(), hiveMQExtension.getVersion(), hiveMQExtension.getPriority(), - hiveMQExtension.getStartPriority()), - Charset.defaultCharset()); + hiveMQExtension.getStartPriority() + ), + Charset.defaultCharset() + ); if (hiveMQExtension.isDisabledOnStartup()) { final File disabled = new File(extensionDir, "DISABLED"); final boolean newFile = disabled.createNewFile(); if (!newFile) { - throw new ContainerLaunchException("Could not create DISABLED file '" + disabled.getAbsolutePath() + "' on host machine."); + throw new ContainerLaunchException( + "Could not create DISABLED file '" + disabled.getAbsolutePath() + "' on host machine." + ); } } @@ -129,11 +140,15 @@ private HiveMQExtension( private void putSubclassesIntoJar( final @NotNull String extensionId, final @Nullable Class clazz, - final @NotNull JavaArchive javaArchive) throws NotFoundException { - + final @NotNull JavaArchive javaArchive + ) throws NotFoundException { if (clazz != null) { - final Set subClassNames = - ClassPool.getDefault().get(clazz.getName()).getClassFile().getConstPool().getClassNames(); + final Set subClassNames = ClassPool + .getDefault() + .get(clazz.getName()) + .getClassFile() + .getConstPool() + .getClassNames(); for (final String subClassName : subClassNames) { final String className = subClassName.replaceAll("/", "."); @@ -156,14 +171,27 @@ private void putSubclassesIntoJar( } public static final class Builder { - private @Nullable String id; - private @Nullable String name; - private @Nullable String version; + + @Nullable + private String id; + + @Nullable + private String name; + + @Nullable + private String version; + private int priority = 0; + private int startPriority = 0; + private boolean disabledOnStartup = false; - private @Nullable Class mainClass; - private final @NotNull LinkedList> additionalClasses = new LinkedList<>(); + + @Nullable + private Class mainClass; + + @NotNull + private final LinkedList> additionalClasses = new LinkedList<>(); /** * Builds the {@link HiveMQExtension} with the provided values or default values. @@ -274,12 +302,16 @@ public static final class Builder { try { final Class extensionMain = Class.forName(EXTENSION_MAIN_CLASS_NAME); if (!extensionMain.isAssignableFrom(mainClass)) { - throw new IllegalArgumentException("The provided class does not implement '" + EXTENSION_MAIN_CLASS_NAME + "'"); + throw new IllegalArgumentException( + "The provided class does not implement '" + EXTENSION_MAIN_CLASS_NAME + "'" + ); } this.mainClass = mainClass; return this; } catch (final ClassNotFoundException e) { - throw new IllegalStateException("The class '" + EXTENSION_MAIN_CLASS_NAME + "' was not found in the classpath."); + throw new IllegalStateException( + "The class '" + EXTENSION_MAIN_CLASS_NAME + "' was not found in the classpath." + ); } } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithControlCenterIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithControlCenterIT.java index f88d60b22ed..a3e8a20216d 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithControlCenterIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithControlCenterIT.java @@ -17,18 +17,18 @@ public class ContainerWithControlCenterIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) public void test() throws Exception { - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) - .withControlCenter()) { - + try ( + final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + .withControlCenter() + ) { hivemq.start(); try (final CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { - final HttpUriRequest request = new HttpGet("http://" + hivemq.getHost() + ":" + hivemq.getMappedPort(CONTROL_CENTER_PORT)); + final HttpUriRequest request = new HttpGet( + "http://" + hivemq.getHost() + ":" + hivemq.getMappedPort(CONTROL_CENTER_PORT) + ); httpClient.execute(request); } } - } } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithCustomConfigIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithCustomConfigIT.java index 57d3b75bc24..fe119854c80 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithCustomConfigIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithCustomConfigIT.java @@ -18,13 +18,14 @@ public class ContainerWithCustomConfigIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - - try (final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) - .withHiveMQConfig(MountableFile.forClasspathResource("/config.xml"))) { - + try ( + final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + .withHiveMQConfig(MountableFile.forClasspathResource("/config.xml")) + ) { hivemq.start(); - final Mqtt5BlockingClient publisher = Mqtt5Client.builder() + final Mqtt5BlockingClient publisher = Mqtt5Client + .builder() .identifier("publisher") .serverPort(hivemq.getMqttPort()) .serverHost(hivemq.getHost()) @@ -32,13 +33,13 @@ void test() throws Exception { publisher.connect(); - assertThrows(MqttSessionExpiredException.class, () -> { - // this should fail since only QoS 0 is allowed by the configuration - publisher.publishWith() - .topic("test/topic") - .qos(MqttQos.EXACTLY_ONCE) - .send(); - }); + assertThrows( + MqttSessionExpiredException.class, + () -> { + // this should fail since only QoS 0 is allowed by the configuration + publisher.publishWith().topic("test/topic").qos(MqttQos.EXACTLY_ONCE).send(); + } + ); } } } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionFromDirectoryIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionFromDirectoryIT.java index 4b89e418b05..c1e6e72cc32 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionFromDirectoryIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionFromDirectoryIT.java @@ -15,13 +15,14 @@ public class ContainerWithExtensionFromDirectoryIT { @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { try ( - final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withExtension(MountableFile.forClasspathResource("/modifier-extension")) - .waitForExtension("Modifier Extension") - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .withLogLevel(Level.DEBUG)) { - + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withExtension(MountableFile.forClasspathResource("/modifier-extension")) + .waitForExtension("Modifier Extension") + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .withLogLevel(Level.DEBUG) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } @@ -30,12 +31,14 @@ void test() throws Exception { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test_wrongDirectoryName() throws Exception { - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) .withExtension(MountableFile.forClasspathResource("/modifier-extension-wrong-name")) .waitForExtension("Modifier Extension") - .withLogLevel(Level.DEBUG)) { - + .withLogLevel(Level.DEBUG) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionIT.java index 8979d2c17b0..01a67e0dcfb 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionIT.java @@ -14,18 +14,22 @@ public class ContainerWithExtensionIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - final HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(MyExtension.class).build(); - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .waitForExtension(hiveMQExtension) - .withExtension(hiveMQExtension)) { - + .mainClass(MyExtension.class) + .build(); + + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .waitForExtension(hiveMQExtension) + .withExtension(hiveMQExtension) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); hivemq.stop(); diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionSubclassIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionSubclassIT.java index 53714123aff..1f3d9de4aeb 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionSubclassIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithExtensionSubclassIT.java @@ -15,19 +15,23 @@ public class ContainerWithExtensionSubclassIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - final HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(MyExtensionWithSubclasses.class).build(); - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .waitForExtension(hiveMQExtension) - .withExtension(hiveMQExtension) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .withLogLevel(Level.DEBUG)) { + .mainClass(MyExtensionWithSubclasses.class) + .build(); + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .waitForExtension(hiveMQExtension) + .withExtension(hiveMQExtension) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .withLogLevel(Level.DEBUG) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInExtensionHomeIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInExtensionHomeIT.java index 559737c8868..a5b5238ce25 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInExtensionHomeIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInExtensionHomeIT.java @@ -22,26 +22,30 @@ public class ContainerWithFileInExtensionHomeIT { - @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - final HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(FileCheckerExtension.class).build(); - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .withExtension(hiveMQExtension) - .waitForExtension(hiveMQExtension) - .withFileInExtensionHomeFolder( - MountableFile.forClasspathResource("/additionalFile.txt"), - "extension-1", - "/additionalFiles/my-file.txt")) { - + .mainClass(FileCheckerExtension.class) + .build(); + + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .withExtension(hiveMQExtension) + .waitForExtension(hiveMQExtension) + .withFileInExtensionHomeFolder( + MountableFile.forClasspathResource("/additionalFile.txt"), + "extension-1", + "/additionalFiles/my-file.txt" + ) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } @@ -50,28 +54,33 @@ void test() throws Exception { public static class FileCheckerExtension implements ExtensionMain { @Override - public void extensionStart(final @NotNull ExtensionStartInput extensionStartInput, final @NotNull ExtensionStartOutput extensionStartOutput) { - + public void extensionStart( + final @NotNull ExtensionStartInput extensionStartInput, + final @NotNull ExtensionStartOutput extensionStartOutput + ) { final PublishInboundInterceptor publishInboundInterceptor = (publishInboundInput, publishInboundOutput) -> { - final File extensionHomeFolder = extensionStartInput.getExtensionInformation().getExtensionHomeFolder(); final File additionalFile = new File(extensionHomeFolder, "additionalFiles/my-file.txt"); if (additionalFile.exists()) { - publishInboundOutput.getPublishPacket().setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); + publishInboundOutput + .getPublishPacket() + .setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); } }; - final ClientInitializer clientInitializer = (initializerInput, clientContext) -> clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + final ClientInitializer clientInitializer = (initializerInput, clientContext) -> { + clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + }; Services.initializerRegistry().setClientInitializer(clientInitializer); } @Override - public void extensionStop(final @NotNull ExtensionStopInput extensionStopInput, final @NotNull ExtensionStopOutput extensionStopOutput) { - - } + public void extensionStop( + final @NotNull ExtensionStopInput extensionStopInput, + final @NotNull ExtensionStopOutput extensionStopOutput + ) {} } - } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInHomeIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInHomeIT.java index efdf6ad298d..2fd387f394c 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInHomeIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithFileInHomeIT.java @@ -25,21 +25,26 @@ public class ContainerWithFileInHomeIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - final HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(FileCheckerExtension.class).build(); - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .withExtension(hiveMQExtension) - .waitForExtension(hiveMQExtension) - .withFileInHomeFolder(MountableFile.forClasspathResource("/additionalFile.txt"), - "/additionalFiles/my-file.txt")) { - - + .mainClass(FileCheckerExtension.class) + .build(); + + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .withExtension(hiveMQExtension) + .waitForExtension(hiveMQExtension) + .withFileInHomeFolder( + MountableFile.forClasspathResource("/additionalFile.txt"), + "/additionalFiles/my-file.txt" + ) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } @@ -48,28 +53,33 @@ void test() throws Exception { public static class FileCheckerExtension implements ExtensionMain { @Override - public void extensionStart(@NotNull ExtensionStartInput extensionStartInput, @NotNull ExtensionStartOutput extensionStartOutput) { - + public void extensionStart( + @NotNull ExtensionStartInput extensionStartInput, + @NotNull ExtensionStartOutput extensionStartOutput + ) { final PublishInboundInterceptor publishInboundInterceptor = (publishInboundInput, publishInboundOutput) -> { - final File homeFolder = extensionStartInput.getServerInformation().getHomeFolder(); final File additionalFile = new File(homeFolder, "additionalFiles/my-file.txt"); if (additionalFile.exists()) { - publishInboundOutput.getPublishPacket().setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); + publishInboundOutput + .getPublishPacket() + .setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); } }; - final ClientInitializer clientInitializer = (initializerInput, clientContext) -> clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + final ClientInitializer clientInitializer = (initializerInput, clientContext) -> { + clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + }; Services.initializerRegistry().setClientInitializer(clientInitializer); } @Override - public void extensionStop(@NotNull ExtensionStopInput extensionStopInput, @NotNull ExtensionStopOutput extensionStopOutput) { - - } + public void extensionStop( + @NotNull ExtensionStopInput extensionStopInput, + @NotNull ExtensionStopOutput extensionStopOutput + ) {} } - } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithLicenseIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithLicenseIT.java index ba2dc472cdb..9d82188c35c 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithLicenseIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithLicenseIT.java @@ -25,21 +25,24 @@ public class ContainerWithLicenseIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - final HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(LicenceCheckerExtension.class).build(); - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .withExtension(hiveMQExtension) - .waitForExtension(hiveMQExtension) - .withLicense(MountableFile.forClasspathResource("/myLicense.lic")) - .withLicense(MountableFile.forClasspathResource("/myExtensionLicense.elic"))) { - - + .mainClass(LicenceCheckerExtension.class) + .build(); + + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .withExtension(hiveMQExtension) + .waitForExtension(hiveMQExtension) + .withLicense(MountableFile.forClasspathResource("/myLicense.lic")) + .withLicense(MountableFile.forClasspathResource("/myExtensionLicense.elic")) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } @@ -49,16 +52,19 @@ void test() throws Exception { public static class LicenceCheckerExtension implements ExtensionMain { @Override - public void extensionStart(@NotNull ExtensionStartInput extensionStartInput, @NotNull ExtensionStartOutput extensionStartOutput) { - + public void extensionStart( + @NotNull ExtensionStartInput extensionStartInput, + @NotNull ExtensionStartOutput extensionStartOutput + ) { final PublishInboundInterceptor publishInboundInterceptor = (publishInboundInput, publishInboundOutput) -> { - final File homeFolder = extensionStartInput.getServerInformation().getHomeFolder(); final File myLicence = new File(homeFolder, "license/myLicense.lic"); final File myExtensionLicence = new File(homeFolder, "license/myExtensionLicense.elic"); if (myLicence.exists() && myExtensionLicence.exists()) { - publishInboundOutput.getPublishPacket().setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); + publishInboundOutput + .getPublishPacket() + .setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); } }; @@ -70,9 +76,9 @@ public void extensionStart(@NotNull ExtensionStartInput extensionStartInput, @No } @Override - public void extensionStop(@NotNull ExtensionStopInput extensionStopInput, @NotNull ExtensionStopOutput extensionStopOutput) { - - } + public void extensionStop( + @NotNull ExtensionStopInput extensionStopInput, + @NotNull ExtensionStopOutput extensionStopOutput + ) {} } - } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithoutPlatformExtensionsIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithoutPlatformExtensionsIT.java index eaec72cb038..75d308e3f90 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithoutPlatformExtensionsIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/ContainerWithoutPlatformExtensionsIT.java @@ -29,25 +29,28 @@ public class ContainerWithoutPlatformExtensionsIT { - private final @NotNull HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + @NotNull + private final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .name("MyExtension") .id("my-extension") .version("1.0.0") - .mainClass(CheckerExtension.class).build(); - + .mainClass(CheckerExtension.class) + .build(); @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) public void removeAllPlatformExtensions() throws InterruptedException { - - try (final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) - .withExtension(hiveMQExtension) - .waitForExtension(hiveMQExtension) - .withoutPrepackagedExtensions()) { - + try ( + final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + .withExtension(hiveMQExtension) + .waitForExtension(hiveMQExtension) + .withoutPrepackagedExtensions() + ) { hivemq.start(); - final Mqtt5BlockingClient client = MqttClient.builder() + final Mqtt5BlockingClient client = MqttClient + .builder() .serverPort(hivemq.getMqttPort()) .serverHost(hivemq.getHost()) .useMqttVersion5() @@ -73,15 +76,16 @@ public void removeAllPlatformExtensions() throws InterruptedException { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) public void removeKafkaExtension() throws InterruptedException { - - try (final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) - .withExtension(hiveMQExtension) - .waitForExtension(hiveMQExtension) - .withoutPrepackagedExtensions("hivemq-kafka-extension")) { - + try ( + final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + .withExtension(hiveMQExtension) + .waitForExtension(hiveMQExtension) + .withoutPrepackagedExtensions("hivemq-kafka-extension") + ) { hivemq.start(); - final Mqtt5BlockingClient client = MqttClient.builder() + final Mqtt5BlockingClient client = MqttClient + .builder() .serverPort(hivemq.getMqttPort()) .serverHost(hivemq.getHost()) .useMqttVersion5() @@ -107,31 +111,32 @@ public static class CheckerExtension implements ExtensionMain { @Override public void extensionStart( final @NotNull ExtensionStartInput extensionStartInput, - final @NotNull ExtensionStartOutput extensionStartOutput) { - - final String extensionFolders = Arrays.stream(extensionStartInput.getServerInformation().getExtensionsFolder().listFiles()) + final @NotNull ExtensionStartOutput extensionStartOutput + ) { + final String extensionFolders = Arrays + .stream(extensionStartInput.getServerInformation().getExtensionsFolder().listFiles()) .filter(File::isDirectory) .map(File::getName) .collect(Collectors.joining("\n")); final byte[] bytes = extensionFolders.getBytes(StandardCharsets.UTF_8); - Services.publishService().publish(Builders.publish() - .topic("extensions") - .retain(true) - .payload(ByteBuffer.wrap(bytes)) - .build()); - - Services.securityRegistry().setAuthenticatorProvider(authenticatorProviderInput -> - (SimpleAuthenticator) (simpleAuthInput, simpleAuthOutput) -> - simpleAuthOutput.authenticateSuccessfully()); - + Services + .publishService() + .publish(Builders.publish().topic("extensions").retain(true).payload(ByteBuffer.wrap(bytes)).build()); + + Services + .securityRegistry() + .setAuthenticatorProvider(authenticatorProviderInput -> { + return (SimpleAuthenticator) (simpleAuthInput, simpleAuthOutput) -> { + simpleAuthOutput.authenticateSuccessfully(); + }; + }); } @Override public void extensionStop( final @NotNull ExtensionStopInput extensionStopInput, - final @NotNull ExtensionStopOutput extensionStopOutput) { - - } + final @NotNull ExtensionStopOutput extensionStopOutput + ) {} } } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInCopiedDirectoryIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInCopiedDirectoryIT.java index 58b70c3d1d9..191ea41f303 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInCopiedDirectoryIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInCopiedDirectoryIT.java @@ -37,19 +37,23 @@ public class CreateFileInCopiedDirectoryIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - final HiveMQExtension extension = HiveMQExtension.builder() + final HiveMQExtension extension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(FileCreatorExtension.class).build(); - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .withExtension(extension) - .waitForExtension(extension) - .withFileInHomeFolder(createDirectory(), "directory")) { - + .mainClass(FileCreatorExtension.class) + .build(); + + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .withExtension(extension) + .waitForExtension(extension) + .withFileInHomeFolder(createDirectory(), "directory") + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } @@ -58,10 +62,11 @@ void test() throws Exception { public static class FileCreatorExtension implements ExtensionMain { @Override - public void extensionStart(@NotNull ExtensionStartInput extensionStartInput, @NotNull ExtensionStartOutput extensionStartOutput) { - + public void extensionStart( + @NotNull ExtensionStartInput extensionStartInput, + @NotNull ExtensionStartOutput extensionStartOutput + ) { final PublishInboundInterceptor publishInboundInterceptor = (publishInboundInput, publishInboundOutput) -> { - final File homeFolder = extensionStartInput.getServerInformation().getHomeFolder(); final File dir = new File(homeFolder, "directory"); @@ -71,22 +76,26 @@ public void extensionStart(@NotNull ExtensionStartInput extensionStartInput, @No try { if (dirFile.createNewFile() && subDirFile.createNewFile()) { - publishInboundOutput.getPublishPacket().setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); + publishInboundOutput + .getPublishPacket() + .setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); } } catch (IOException e) { e.printStackTrace(); } }; - final ClientInitializer clientInitializer = (initializerInput, clientContext) -> clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + final ClientInitializer clientInitializer = (initializerInput, clientContext) -> { + clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + }; Services.initializerRegistry().setClientInitializer(clientInitializer); } @Override - public void extensionStop(@NotNull ExtensionStopInput extensionStopInput, @NotNull ExtensionStopOutput extensionStopOutput) { - - } + public void extensionStop( + @NotNull ExtensionStopInput extensionStopInput, + @NotNull ExtensionStopOutput extensionStopOutput + ) {} } - } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInExtensionDirectoryIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInExtensionDirectoryIT.java index c41137f58c3..44f5f4f632d 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInExtensionDirectoryIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/CreateFileInExtensionDirectoryIT.java @@ -26,18 +26,22 @@ public class CreateFileInExtensionDirectoryIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - final HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(FileCreatorExtension.class).build(); - - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .waitForExtension(hiveMQExtension) - .withExtension(hiveMQExtension)) { - + .mainClass(FileCreatorExtension.class) + .build(); + + try ( + final HiveMQContainer hivemq = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .waitForExtension(hiveMQExtension) + .withExtension(hiveMQExtension) + ) { hivemq.start(); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } @@ -46,31 +50,36 @@ void test() throws Exception { public static class FileCreatorExtension implements ExtensionMain { @Override - public void extensionStart(@NotNull ExtensionStartInput extensionStartInput, @NotNull ExtensionStartOutput extensionStartOutput) { - + public void extensionStart( + @NotNull ExtensionStartInput extensionStartInput, + @NotNull ExtensionStartOutput extensionStartOutput + ) { final PublishInboundInterceptor publishInboundInterceptor = (publishInboundInput, publishInboundOutput) -> { - final File extensionHomeFolder = extensionStartInput.getExtensionInformation().getExtensionHomeFolder(); final File file = new File(extensionHomeFolder, "myfile.txt"); try { if (file.createNewFile()) { - publishInboundOutput.getPublishPacket().setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); + publishInboundOutput + .getPublishPacket() + .setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); } } catch (IOException e) { e.printStackTrace(); } }; - final ClientInitializer clientInitializer = (initializerInput, clientContext) -> clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + final ClientInitializer clientInitializer = (initializerInput, clientContext) -> { + clientContext.addPublishInboundInterceptor(publishInboundInterceptor); + }; Services.initializerRegistry().setClientInitializer(clientInitializer); } @Override - public void extensionStop(@NotNull ExtensionStopInput extensionStopInput, @NotNull ExtensionStopOutput extensionStopOutput) { - - } + public void extensionStop( + @NotNull ExtensionStopInput extensionStopInput, + @NotNull ExtensionStopOutput extensionStopOutput + ) {} } - } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionFromDirectoryIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionFromDirectoryIT.java index f6b1b9b5cd7..9588e3404e6 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionFromDirectoryIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionFromDirectoryIT.java @@ -17,21 +17,22 @@ public class DisableEnableExtensionFromDirectoryIT { @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) - .withExtension(MountableFile.forClasspathResource("/modifier-extension")) - .waitForExtension("Modifier Extension") - .withLogLevel(Level.DEBUG)) { - + try ( + final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + .withExtension(MountableFile.forClasspathResource("/modifier-extension")) + .waitForExtension("Modifier Extension") + .withLogLevel(Level.DEBUG) + ) { hivemq.start(); - TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); hivemq.disableExtension("Modifier Extension", "modifier-extension"); - assertThrows(ExecutionException.class, () -> TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost())); + assertThrows( + ExecutionException.class, + () -> TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()) + ); hivemq.enableExtension("Modifier Extension", "modifier-extension"); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } } - } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionIT.java index 5b3c6ab107f..e50664f240e 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/DisableEnableExtensionIT.java @@ -15,32 +15,39 @@ public class DisableEnableExtensionIT { - private final @NotNull HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + @NotNull + private final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") .disabledOnStartup(true) - .mainClass(MyExtension.class).build(); + .mainClass(MyExtension.class) + .build(); @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) void test() throws Exception { - try (final HiveMQContainer hivemq = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) - .withExtension(hiveMQExtension) - .withLogLevel(Level.DEBUG)) { - - + try ( + final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + .withExtension(hiveMQExtension) + .withLogLevel(Level.DEBUG) + ) { hivemq.start(); - assertThrows(ExecutionException.class, () -> TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost())); + assertThrows( + ExecutionException.class, + () -> TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()) + ); hivemq.enableExtension(hiveMQExtension); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); hivemq.disableExtension(hiveMQExtension); - assertThrows(ExecutionException.class, () -> TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost())); + assertThrows( + ExecutionException.class, + () -> TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()) + ); hivemq.enableExtension(hiveMQExtension); TestPublishModifiedUtil.testPublishModified(hivemq.getMqttPort(), hivemq.getHost()); } } - } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQExtensionTest.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQExtensionTest.java index d614a59bd8c..08e1df797a1 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQExtensionTest.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQExtensionTest.java @@ -8,6 +8,9 @@ class HiveMQExtensionTest { @Test void builder_classDoesNotImplementExtensionMain_exception() { - assertThrows(IllegalArgumentException.class, () -> HiveMQExtension.builder().mainClass(HiveMQExtensionTest.class)); + assertThrows( + IllegalArgumentException.class, + () -> HiveMQExtension.builder().mainClass(HiveMQExtensionTest.class) + ); } } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQTestContainerCore.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQTestContainerCore.java index 40820e33ded..d4dd2be9621 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQTestContainerCore.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/HiveMQTestContainerCore.java @@ -15,7 +15,8 @@ class HiveMQTestContainerCore { - final @NotNull HiveMQContainer container = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")); + @NotNull + final HiveMQContainer container = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")); @TempDir File tempDir; @@ -69,14 +70,23 @@ void withFileInHomeFolder_pathEmpty_Exception() { @Test void withFileInExtensionHomeFolder_withPath_fileDoesNotExist_Exception() { final MountableFile mountableFile = MountableFile.forHostPath("/this/does/not/exist"); - assertThrows(ContainerLaunchException.class, () -> container.withFileInExtensionHomeFolder(mountableFile, "my-extension", "some/path")); + assertThrows( + ContainerLaunchException.class, + () -> container.withFileInExtensionHomeFolder(mountableFile, "my-extension", "some/path") + ); } @Test void withFileInExtensionHomeFolder_fileDoesNotExist_Exception() { final MountableFile mountableFile = MountableFile.forHostPath("/this/does/not/exist"); - assertThrows(ContainerLaunchException.class, () -> { - final HiveMQContainer hiveMQContainer = container.withFileInExtensionHomeFolder(mountableFile, "my-extension"); - }); + assertThrows( + ContainerLaunchException.class, + () -> { + final HiveMQContainer hiveMQContainer = container.withFileInExtensionHomeFolder( + mountableFile, + "my-extension" + ); + } + ); } } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java index e9d9463653e..97a1365ac91 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java @@ -14,43 +14,54 @@ public class DemoDisableExtensionsIT { // noExtensions { @Container - final HiveMQContainer hivemqNoExtensions = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + final HiveMQContainer hivemqNoExtensions = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4") + ) .withoutPrepackagedExtensions(); + // } // noKafkaExtension { @Container - final HiveMQContainer hivemqNoKafkaExtension = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + final HiveMQContainer hivemqNoKafkaExtension = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4") + ) .withoutPrepackagedExtensions("hivemq-kafka-extension"); + // } // startDisabled { - private final HiveMQExtension hiveMQExtension = HiveMQExtension.builder() + private final HiveMQExtension hiveMQExtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") .disabledOnStartup(true) - .mainClass(MyExtension.class).build(); + .mainClass(MyExtension.class) + .build(); @Container final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) .withExtension(hiveMQExtension); - // } + // } // startFromFilesystem { @Container - final HiveMQContainer hivemqExtensionFromFilesystem = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) + final HiveMQContainer hivemqExtensionFromFilesystem = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4") + ) .withExtension(MountableFile.forHostPath("src/test/resources/modifier-extension")); - // } + // } - // runtimeEnable { + // hiveRuntimeEnable { @Test void test_disable_enable_extension() throws Exception { hivemq.enableExtension(hiveMQExtension); hivemq.disableExtension(hiveMQExtension); } + // } // runtimeEnableFilesystem { diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java index 3a8ccc1bebe..e5385369d3a 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java @@ -19,33 +19,39 @@ public class DemoExtensionTestsIT { // waitStrategy { @Container - final HiveMQContainer hivemqWithWaitStrategy = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4")) - .withExtension(MountableFile.forClasspathResource("/modifier-extension")) - .waitForExtension("Modifier Extension"); + final HiveMQContainer hivemqWithWaitStrategy = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq4").withTag("4.7.4") + ) + .withExtension(MountableFile.forClasspathResource("/modifier-extension")) + .waitForExtension("Modifier Extension"); + // } // extensionClasspath { - final HiveMQExtension hiveMQEClasspathxtension = HiveMQExtension.builder() + final HiveMQExtension hiveMQEClasspathxtension = HiveMQExtension + .builder() .id("extension-1") .name("my-extension") .version("1.0") - .mainClass(MyExtensionWithSubclasses.class).build(); + .mainClass(MyExtensionWithSubclasses.class) + .build(); @Container - final HiveMQContainer hivemqWithClasspathExtension = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .waitForExtension(hiveMQEClasspathxtension) - .withExtension(hiveMQEClasspathxtension) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")); + final HiveMQContainer hivemqWithClasspathExtension = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .waitForExtension(hiveMQEClasspathxtension) + .withExtension(hiveMQEClasspathxtension) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")); + // } @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) public void test() throws Exception { - // mqtt5client { - final Mqtt5BlockingClient client = Mqtt5Client.builder() + final Mqtt5BlockingClient client = Mqtt5Client + .builder() .serverPort(hivemqWithClasspathExtension.getMqttPort()) .serverHost(hivemqWithClasspathExtension.getHost()) .buildBlocking(); diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java index 7ec777d02b8..d0bf6fc6b9c 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java @@ -18,24 +18,36 @@ public class DemoFilesIT { // hivemqHome { - final HiveMQContainer hivemqFileInHome = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) + final HiveMQContainer hivemqFileInHome = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) .withFileInHomeFolder( MountableFile.forHostPath("src/test/resources/additionalFile.txt"), - "/path/in/home/folder"); + "/path/in/home/folder" + ); + // } // extensionHome { @Container - final HiveMQContainer hivemqFileInExtensionHome = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withExtension(HiveMQExtension.builder() - .id("extension-1") - .name("my-extension") - .version("1.0") - .mainClass(MyExtension.class).build()) + final HiveMQContainer hivemqFileInExtensionHome = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withExtension( + HiveMQExtension + .builder() + .id("extension-1") + .name("my-extension") + .version("1.0") + .mainClass(MyExtension.class) + .build() + ) .withFileInExtensionHomeFolder( MountableFile.forHostPath("src/test/resources/additionalFile.txt"), "extension-1", - "/path/in/extension/home"); + "/path/in/extension/home" + ); + // } // withLicenses { @@ -43,14 +55,15 @@ public class DemoFilesIT { final HiveMQContainer hivemq = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) .withLicense(MountableFile.forHostPath("src/test/resources/myLicense.lic")) .withLicense(MountableFile.forHostPath("src/test/resources/myExtensionLicense.elic")); + // } @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) public void test() throws Exception { - // mqtt5client { - final Mqtt5BlockingClient client = Mqtt5Client.builder() + final Mqtt5BlockingClient client = Mqtt5Client + .builder() .serverPort(hivemq.getMqttPort()) .serverHost(hivemq.getHost()) .buildBlocking(); diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java index 51e3a43d9e5..be39fe6d7f2 100644 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java @@ -18,38 +18,41 @@ public class DemoHiveMQContainerIT { // ceVersion { @Container - final HiveMQContainer hivemqCe = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withLogLevel(Level.DEBUG); + final HiveMQContainer hivemqCe = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) + .withLogLevel(Level.DEBUG); + // } - // eeVersion { + // hiveEEVersion { @Container - final HiveMQContainer hivemqEe = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withLogLevel(Level.DEBUG); + final HiveMQContainer hivemqEe = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) + .withLogLevel(Level.DEBUG); + // } // eeVersionWithControlCenter { @Container - final HiveMQContainer hivemqEeWithControLCenter = - new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3")) - .withLogLevel(Level.DEBUG) - .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) - .withControlCenter(); + final HiveMQContainer hivemqEeWithControlCenter = new HiveMQContainer( + DockerImageName.parse("hivemq/hivemq-ce").withTag("2021.3") + ) + .withLogLevel(Level.DEBUG) + .withHiveMQConfig(MountableFile.forClasspathResource("/inMemoryConfig.xml")) + .withControlCenter(); + // } // specificVersion { @Container final HiveMQContainer hivemqSpecificVersion = new HiveMQContainer(DockerImageName.parse("hivemq/hivemq-ce:2021.3")); + // } @Test @Timeout(value = 3, unit = TimeUnit.MINUTES) public void test() throws Exception { - // mqtt5client { - final Mqtt5BlockingClient client = Mqtt5Client.builder() + final Mqtt5BlockingClient client = Mqtt5Client + .builder() .serverPort(hivemqCe.getMqttPort()) .serverHost(hivemqCe.getHost()) .buildBlocking(); diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtension.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtension.java index e707859be77..4c3991122d7 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtension.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtension.java @@ -1,7 +1,6 @@ package org.testcontainers.hivemq.util; import com.hivemq.extension.sdk.api.ExtensionMain; -import org.jetbrains.annotations.NotNull; import com.hivemq.extension.sdk.api.interceptor.publish.PublishInboundInterceptor; import com.hivemq.extension.sdk.api.parameter.ExtensionStartInput; import com.hivemq.extension.sdk.api.parameter.ExtensionStartOutput; @@ -9,6 +8,7 @@ import com.hivemq.extension.sdk.api.parameter.ExtensionStopOutput; import com.hivemq.extension.sdk.api.services.Services; import com.hivemq.extension.sdk.api.services.intializer.ClientInitializer; +import org.jetbrains.annotations.NotNull; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -17,10 +17,14 @@ public class MyExtension implements ExtensionMain { @Override - public void extensionStart(final @NotNull ExtensionStartInput extensionStartInput, final @NotNull ExtensionStartOutput extensionStartOutput) { - + public void extensionStart( + final @NotNull ExtensionStartInput extensionStartInput, + final @NotNull ExtensionStartOutput extensionStartOutput + ) { final PublishInboundInterceptor publishInboundInterceptor = (publishInboundInput, publishInboundOutput) -> { - publishInboundOutput.getPublishPacket().setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); + publishInboundOutput + .getPublishPacket() + .setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); }; final ClientInitializer clientInitializer = (initializerInput, clientContext) -> { @@ -31,7 +35,8 @@ public void extensionStart(final @NotNull ExtensionStartInput extensionStartInpu } @Override - public void extensionStop(final @NotNull ExtensionStopInput extensionStopInput, final @NotNull ExtensionStopOutput extensionStopOutput) { - - } + public void extensionStop( + final @NotNull ExtensionStopInput extensionStopInput, + final @NotNull ExtensionStopOutput extensionStopOutput + ) {} } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtensionWithSubclasses.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtensionWithSubclasses.java index abc24585358..9e4565b15c9 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtensionWithSubclasses.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/MyExtensionWithSubclasses.java @@ -1,26 +1,31 @@ package org.testcontainers.hivemq.util; import com.hivemq.extension.sdk.api.ExtensionMain; -import org.jetbrains.annotations.NotNull; import com.hivemq.extension.sdk.api.parameter.ExtensionStartInput; import com.hivemq.extension.sdk.api.parameter.ExtensionStartOutput; import com.hivemq.extension.sdk.api.parameter.ExtensionStopInput; import com.hivemq.extension.sdk.api.parameter.ExtensionStopOutput; import com.hivemq.extension.sdk.api.services.Services; import com.hivemq.extension.sdk.api.services.intializer.ClientInitializer; +import org.jetbrains.annotations.NotNull; public class MyExtensionWithSubclasses implements ExtensionMain { @Override - public void extensionStart(final @NotNull ExtensionStartInput extensionStartInput, final @NotNull ExtensionStartOutput extensionStartOutput) { - - final ClientInitializer clientInitializer = (initializerInput, clientContext) -> clientContext.addPublishInboundInterceptor(new PublishModifier()); + public void extensionStart( + final @NotNull ExtensionStartInput extensionStartInput, + final @NotNull ExtensionStartOutput extensionStartOutput + ) { + final ClientInitializer clientInitializer = (initializerInput, clientContext) -> { + clientContext.addPublishInboundInterceptor(new PublishModifier()); + }; Services.initializerRegistry().setClientInitializer(clientInitializer); } @Override - public void extensionStop(final @NotNull ExtensionStopInput extensionStopInput, final @NotNull ExtensionStopOutput extensionStopOutput) { - - } + public void extensionStop( + final @NotNull ExtensionStopInput extensionStopInput, + final @NotNull ExtensionStopOutput extensionStopOutput + ) {} } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/PublishModifier.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/PublishModifier.java index d33f29a9c10..ec5b63ee1e6 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/PublishModifier.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/PublishModifier.java @@ -1,16 +1,22 @@ package org.testcontainers.hivemq.util; -import org.jetbrains.annotations.NotNull; import com.hivemq.extension.sdk.api.interceptor.publish.PublishInboundInterceptor; import com.hivemq.extension.sdk.api.interceptor.publish.parameter.PublishInboundInput; import com.hivemq.extension.sdk.api.interceptor.publish.parameter.PublishInboundOutput; +import org.jetbrains.annotations.NotNull; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; public class PublishModifier implements PublishInboundInterceptor { + @Override - public void onInboundPublish(final @NotNull PublishInboundInput publishInboundInput, final @NotNull PublishInboundOutput publishInboundOutput) { - publishInboundOutput.getPublishPacket().setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); + public void onInboundPublish( + final @NotNull PublishInboundInput publishInboundInput, + final @NotNull PublishInboundOutput publishInboundOutput + ) { + publishInboundOutput + .getPublishPacket() + .setPayload(ByteBuffer.wrap("modified".getBytes(StandardCharsets.UTF_8))); } } diff --git a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/TestPublishModifiedUtil.java b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/TestPublishModifiedUtil.java index f2f1cfd692f..963570c07c4 100755 --- a/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/TestPublishModifiedUtil.java +++ b/modules/hivemq/src/test/java/org/testcontainers/hivemq/util/TestPublishModifiedUtil.java @@ -14,27 +14,38 @@ public class TestPublishModifiedUtil { public static void testPublishModified(final int mqttPort, final @NotNull String host) throws Exception { final CompletableFuture publishReceived = new CompletableFuture<>(); - final Mqtt5BlockingClient publisher = Mqtt5Client.builder() + final Mqtt5BlockingClient publisher = Mqtt5Client + .builder() .serverPort(mqttPort) .serverHost(host) .identifier("publisher") .buildBlocking(); publisher.connect(); - final Mqtt5BlockingClient subscriber = Mqtt5Client.builder() + final Mqtt5BlockingClient subscriber = Mqtt5Client + .builder() .serverPort(mqttPort) .serverHost(host) .identifier("subscriber") .buildBlocking(); subscriber.connect(); subscriber.subscribeWith().topicFilter("test/topic").send(); - subscriber.toAsync().publishes(MqttGlobalPublishFilter.ALL, publish -> { - if (Arrays.equals(publish.getPayloadAsBytes(), "modified".getBytes(StandardCharsets.UTF_8))) { - publishReceived.complete(null); - } else { - publishReceived.completeExceptionally(new IllegalArgumentException("unexpected payload: " + new String(publish.getPayloadAsBytes()))); - } - }); + subscriber + .toAsync() + .publishes( + MqttGlobalPublishFilter.ALL, + publish -> { + if (Arrays.equals(publish.getPayloadAsBytes(), "modified".getBytes(StandardCharsets.UTF_8))) { + publishReceived.complete(null); + } else { + publishReceived.completeExceptionally( + new IllegalArgumentException( + "unexpected payload: " + new String(publish.getPayloadAsBytes()) + ) + ); + } + } + ); publisher.publishWith().topic("test/topic").payload("unmodified".getBytes(StandardCharsets.UTF_8)).send(); @@ -45,6 +56,4 @@ public static void testPublishModified(final int mqttPort, final @NotNull String subscriber.disconnect(); } } - - } diff --git a/modules/influxdb/src/main/java/org/testcontainers/containers/InfluxDBContainer.java b/modules/influxdb/src/main/java/org/testcontainers/containers/InfluxDBContainer.java index 7ebfbff1a86..40eea721b57 100644 --- a/modules/influxdb/src/main/java/org/testcontainers/containers/InfluxDBContainer.java +++ b/modules/influxdb/src/main/java/org/testcontainers/containers/InfluxDBContainer.java @@ -17,17 +17,22 @@ public class InfluxDBContainer> extends Gen public static final Integer INFLUXDB_PORT = 8086; private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("influxdb"); + private static final String DEFAULT_TAG = "1.4.3"; @Deprecated public static final String VERSION = DEFAULT_TAG; private boolean authEnabled = true; + private String admin = "admin"; + private String adminPassword = "password"; private String database; + private String username = "any"; + private String password = "any"; /** @@ -48,12 +53,12 @@ public InfluxDBContainer(final String version) { public InfluxDBContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - waitStrategy = new WaitAllStrategy() - .withStrategy(Wait.forHttp("/ping").withBasicCredentials(username, password).forStatusCode(204)) - .withStrategy(Wait.forListeningPort()); + waitStrategy = + new WaitAllStrategy() + .withStrategy(Wait.forHttp("/ping").withBasicCredentials(username, password).forStatusCode(204)) + .withStrategy(Wait.forListeningPort()); addExposedPort(INFLUXDB_PORT); } @@ -144,7 +149,6 @@ public SELF withPassword(final String password) { return self(); } - /** * @return a url to influxDb */ diff --git a/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerTest.java b/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerTest.java index 7acf030b5e4..c7fc71a3a19 100644 --- a/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerTest.java +++ b/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerTest.java @@ -4,14 +4,16 @@ import org.junit.ClassRule; import org.junit.Test; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; public class InfluxDBContainerTest { @ClassRule - public static InfluxDBContainer influxDBContainer = new InfluxDBContainer<>(InfluxDBTestImages.INFLUXDB_TEST_IMAGE); + public static InfluxDBContainer influxDBContainer = new InfluxDBContainer<>( + InfluxDBTestImages.INFLUXDB_TEST_IMAGE + ); @Test public void getUrl() { diff --git a/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerWithUserTest.java b/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerWithUserTest.java index b045ca297c1..a7ae347e7cc 100644 --- a/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerWithUserTest.java +++ b/modules/influxdb/src/test/java/org/testcontainers/containers/InfluxDBContainerWithUserTest.java @@ -9,17 +9,20 @@ import java.util.concurrent.TimeUnit; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; public class InfluxDBContainerWithUserTest { private static final String TEST_VERSION = InfluxDBTestImages.INFLUXDB_TEST_IMAGE.getVersionPart(); + private static final String DATABASE = "test"; + private static final String USER = "test-user"; + private static final String PASSWORD = "test-password"; @Rule @@ -52,7 +55,8 @@ public void checkVersion() { public void queryForWriteAndRead() { InfluxDB influxDB = influxDBContainer.getNewInfluxDB(); - Point point = Point.measurement("cpu") + Point point = Point + .measurement("cpu") .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS) .addField("idle", 90L) .addField("user", 9L) @@ -67,6 +71,5 @@ public void queryForWriteAndRead() { assertThat(actual.getError(), nullValue()); assertThat(actual.getResults(), notNullValue()); assertThat(actual.getResults().size(), is(1)); - } } diff --git a/modules/jdbc-test/src/main/java/org/testcontainers/db/AbstractContainerDatabaseTest.java b/modules/jdbc-test/src/main/java/org/testcontainers/db/AbstractContainerDatabaseTest.java index 6a5ca5094d6..6d3080c7ee3 100644 --- a/modules/jdbc-test/src/main/java/org/testcontainers/db/AbstractContainerDatabaseTest.java +++ b/modules/jdbc-test/src/main/java/org/testcontainers/db/AbstractContainerDatabaseTest.java @@ -4,11 +4,12 @@ import com.zaxxer.hikari.HikariDataSource; import org.testcontainers.containers.JdbcDatabaseContainer; -import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import javax.sql.DataSource; + public abstract class AbstractContainerDatabaseTest { protected ResultSet performQuery(JdbcDatabaseContainer container, String sql) throws SQLException { diff --git a/modules/jdbc-test/src/main/java/org/testcontainers/jdbc/AbstractJDBCDriverTest.java b/modules/jdbc-test/src/main/java/org/testcontainers/jdbc/AbstractJDBCDriverTest.java index 4e5eb03bb49..5566db6244e 100644 --- a/modules/jdbc-test/src/main/java/org/testcontainers/jdbc/AbstractJDBCDriverTest.java +++ b/modules/jdbc-test/src/main/java/org/testcontainers/jdbc/AbstractJDBCDriverTest.java @@ -25,22 +25,19 @@ protected enum Options { CharacterSet, CustomIniFile, JDBCParams, - PmdKnownBroken + PmdKnownBroken, } @Parameter public String jdbcUrl; + @Parameter(1) public EnumSet options; public static void sampleInitFunction(Connection connection) throws SQLException { - connection.createStatement().execute("CREATE TABLE bar (\n" + - " foo VARCHAR(255)\n" + - ");"); + connection.createStatement().execute("CREATE TABLE bar (\n" + " foo VARCHAR(255)\n" + ");"); connection.createStatement().execute("INSERT INTO bar (foo) VALUES ('hello world');"); - connection.createStatement().execute("CREATE TABLE my_counter (\n" + - " n INT\n" + - ");"); + connection.createStatement().execute("CREATE TABLE my_counter (\n" + " n INT\n" + ");"); } @AfterClass @@ -79,67 +76,99 @@ private void performSimpleTest(HikariDataSource dataSource) throws SQLException query = "SELECT 1 FROM SYSIBM.SYSDUMMY1"; } - boolean result = new QueryRunner(dataSource, options.contains(Options.PmdKnownBroken)).query(query, rs -> { - rs.next(); - int resultSetInt = rs.getInt(1); - assertEquals("A basic SELECT query succeeds", 1, resultSetInt); - return true; - }); + boolean result = new QueryRunner(dataSource, options.contains(Options.PmdKnownBroken)) + .query( + query, + rs -> { + rs.next(); + int resultSetInt = rs.getInt(1); + assertEquals("A basic SELECT query succeeds", 1, resultSetInt); + return true; + } + ); assertTrue("The database returned a record as expected", result); } private void performTestForScriptedSchema(HikariDataSource dataSource) throws SQLException { - boolean result = new QueryRunner(dataSource).query("SELECT foo FROM bar WHERE foo LIKE '%world'", rs -> { - rs.next(); - String resultSetString = rs.getString(1); - assertEquals("A basic SELECT query succeeds where the schema has been applied from a script", "hello world", resultSetString); - return true; - }); + boolean result = new QueryRunner(dataSource) + .query( + "SELECT foo FROM bar WHERE foo LIKE '%world'", + rs -> { + rs.next(); + String resultSetString = rs.getString(1); + assertEquals( + "A basic SELECT query succeeds where the schema has been applied from a script", + "hello world", + resultSetString + ); + return true; + } + ); assertTrue("The database returned a record as expected", result); } private void performTestForJDBCParamUsage(HikariDataSource dataSource) throws SQLException { - boolean result = new QueryRunner(dataSource).query("select CURRENT_USER", rs -> { - rs.next(); - String resultUser = rs.getString(1); - // Not all databases (eg. Postgres) return @% at the end of user name. We just need to make sure the user name matches. - if (resultUser.endsWith("@%")) { - resultUser = resultUser.substring(0, resultUser.length() - 2); - } - assertEquals("User from query param is created.", "someuser", resultUser); - return true; - }); + boolean result = new QueryRunner(dataSource) + .query( + "select CURRENT_USER", + rs -> { + rs.next(); + String resultUser = rs.getString(1); + // Not all databases (eg. Postgres) return @% at the end of user name. We just need to make sure the user name matches. + if (resultUser.endsWith("@%")) { + resultUser = resultUser.substring(0, resultUser.length() - 2); + } + assertEquals("User from query param is created.", "someuser", resultUser); + return true; + } + ); assertTrue("The database returned a record as expected", result); String databaseQuery = "SELECT DATABASE()"; // Postgres does not have Database() as a function String databaseType = ConnectionUrl.newInstance(jdbcUrl).getDatabaseType(); - if (databaseType.equalsIgnoreCase("postgresql") || + if ( + databaseType.equalsIgnoreCase("postgresql") || databaseType.equalsIgnoreCase("postgis") || - databaseType.equalsIgnoreCase("timescaledb")) { + databaseType.equalsIgnoreCase("timescaledb") + ) { databaseQuery = "SELECT CURRENT_DATABASE()"; } - result = new QueryRunner(dataSource).query(databaseQuery, rs -> { - rs.next(); - String resultDB = rs.getString(1); - assertEquals("Database name from URL String is used.", "databasename", resultDB); - return true; - }); + result = + new QueryRunner(dataSource) + .query( + databaseQuery, + rs -> { + rs.next(); + String resultDB = rs.getString(1); + assertEquals("Database name from URL String is used.", "databasename", resultDB); + return true; + } + ); assertTrue("The database returned a record as expected", result); } - private void performTestForCharacterEncodingForInitialScriptConnection(HikariDataSource dataSource) throws SQLException { - boolean result = new QueryRunner(dataSource).query("SELECT foo FROM bar WHERE foo LIKE '%мир'", rs -> { - rs.next(); - String resultSetString = rs.getString(1); - assertEquals("A SELECT query succeed and the correct charset has been applied for the init script", "привет мир", resultSetString); - return true; - }); + private void performTestForCharacterEncodingForInitialScriptConnection(HikariDataSource dataSource) + throws SQLException { + boolean result = new QueryRunner(dataSource) + .query( + "SELECT foo FROM bar WHERE foo LIKE '%мир'", + rs -> { + rs.next(); + String resultSetString = rs.getString(1); + assertEquals( + "A SELECT query succeed and the correct charset has been applied for the init script", + "привет мир", + resultSetString + ); + return true; + } + ); assertTrue("The database returned a record as expected", result); } @@ -160,12 +189,19 @@ private void performSimpleTestWithCharacterSet(String jdbcUrl) throws SQLExcepti private HikariDataSource verifyCharacterSet(String jdbcUrl) throws SQLException { HikariDataSource dataSource = getDataSource(jdbcUrl, 1); - boolean result = new QueryRunner(dataSource).query("SHOW VARIABLES LIKE 'character\\_set\\_connection'", rs -> { - rs.next(); - String resultSetString = rs.getString(2); - assertTrue("Passing query parameters to set DB connection encoding is successful", resultSetString.startsWith("utf8")); - return true; - }); + boolean result = new QueryRunner(dataSource) + .query( + "SHOW VARIABLES LIKE 'character\\_set\\_connection'", + rs -> { + rs.next(); + String resultSetString = rs.getString(2); + assertTrue( + "Passing query parameters to set DB connection encoding is successful", + resultSetString.startsWith("utf8") + ); + return true; + } + ); assertTrue("The database returned a record as expected", result); return dataSource; diff --git a/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java b/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java index 5e5342f1ee1..84d242a29c7 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java +++ b/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainer.java @@ -20,23 +20,29 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.Future; - -import static java.util.stream.Collectors.joining; +import java.util.stream.Collectors; /** * Base class for containers that expose a JDBC connection * * @author richardnorth */ -public abstract class JdbcDatabaseContainer> extends GenericContainer implements LinkableContainer { +public abstract class JdbcDatabaseContainer> + extends GenericContainer + implements LinkableContainer { private static final Object DRIVER_LOAD_MUTEX = new Object(); + private Driver driver; + private String initScriptPath; + protected Map parameters = new HashMap<>(); + protected Map urlParameters = new HashMap<>(); private int startupTimeoutSeconds = 120; + private int connectTimeoutSeconds = 120; private static final String QUERY_PARAM_SEPARATOR = "&"; @@ -135,7 +141,12 @@ public SELF withInitScript(String initScriptPath) { @SneakyThrows(InterruptedException.class) @Override protected void waitUntilContainerStarted() { - logger().info("Waiting for database connection to become available at {} using query '{}'", getJdbcUrl(), getTestQueryString()); + logger() + .info( + "Waiting for database connection to become available at {} using query '{}'", + getJdbcUrl(), + getTestQueryString() + ); // Repeatedly try and open a connection to the DB and execute a test query long start = System.currentTimeMillis(); @@ -144,8 +155,7 @@ protected void waitUntilContainerStarted() { if (!isRunning()) { Thread.sleep(100L); } else { - try (Connection connection = createConnection(""); - Statement statement = connection.createStatement()) { + try (Connection connection = createConnection(""); Statement statement = connection.createStatement()) { boolean testQuerySucceeded = statement.execute(this.getTestQueryString()); if (testQuerySucceeded) { logger().info("Container is started (JDBC URL: {})", this.getJdbcUrl()); @@ -163,8 +173,10 @@ protected void waitUntilContainerStarted() { } throw new IllegalStateException( - String.format("Container is started, but cannot be accessed by (JDBC URL: %s), please check container logs", - this.getJdbcUrl()) + String.format( + "Container is started, but cannot be accessed by (JDBC URL: %s), please check container logs", + this.getJdbcUrl() + ) ); } @@ -179,7 +191,6 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) { * @return a JDBC Driver */ public Driver getJdbcDriverInstance() throws NoDriverFoundException { - synchronized (DRIVER_LOAD_MUTEX) { if (driver == null) { try { @@ -215,7 +226,13 @@ public Connection createConnection(String queryString) throws SQLException, NoDr // give up if we hit the time limit or the container stops running for some reason while (System.currentTimeMillis() < start + (1000 * connectTimeoutSeconds) && isRunning()) { try { - logger().debug("Trying to create JDBC connection using {} to {} with properties: {}", driver.getClass().getName(), url, info); + logger() + .debug( + "Trying to create JDBC connection using {} to {} with properties: {}", + driver.getClass().getName(), + url, + info + ); return jdbcDriverInstance.connect(url, info); } catch (SQLException e) { @@ -261,15 +278,18 @@ protected String constructUrlParameters(String startCharacter, String delimiter) protected String constructUrlParameters(String startCharacter, String delimiter, String endCharacter) { String urlParameters = ""; if (!this.urlParameters.isEmpty()) { - String additionalParameters = this.urlParameters.entrySet().stream() - .map(Object::toString) - .collect(joining(delimiter)); + String additionalParameters = + this.urlParameters.entrySet().stream().map(Object::toString).collect(Collectors.joining(delimiter)); urlParameters = startCharacter + additionalParameters + endCharacter; } return urlParameters; } - protected void optionallyMapResourceParameterAsVolume(@NotNull String paramName, @NotNull String pathNameInContainer, @NotNull String defaultResource) { + protected void optionallyMapResourceParameterAsVolume( + @NotNull String paramName, + @NotNull String pathNameInContainer, + @NotNull String defaultResource + ) { String resourceName = parameters.getOrDefault(paramName, defaultResource); if (resourceName != null) { @@ -319,6 +339,7 @@ protected DatabaseDelegate getDatabaseDelegate() { } public static class NoDriverFoundException extends RuntimeException { + public NoDriverFoundException(String message, Throwable e) { super(message, e); } diff --git a/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainerProvider.java b/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainerProvider.java index f8694306384..3cd74dc98d4 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainerProvider.java +++ b/modules/jdbc/src/main/java/org/testcontainers/containers/JdbcDatabaseContainerProvider.java @@ -1,8 +1,7 @@ package org.testcontainers.containers; -import org.testcontainers.jdbc.ConnectionUrl; - import lombok.extern.slf4j.Slf4j; +import org.testcontainers.jdbc.ConnectionUrl; import java.util.Objects; @@ -26,9 +25,12 @@ public abstract class JdbcDatabaseContainerProvider { * @return Instance of {@link JdbcDatabaseContainer} */ public JdbcDatabaseContainer newInstance() { - log.warn("No explicit version tag was provided in JDBC URL and this class ({}) does not " + + log.warn( + "No explicit version tag was provided in JDBC URL and this class ({}) does not " + "override newInstance() to set a default tag. `latest` will be used but results may " + - "be unreliable!", this.getClass().getCanonicalName()); + "be unreliable!", + this.getClass().getCanonicalName() + ); return this.newInstance("latest"); } @@ -55,7 +57,11 @@ public JdbcDatabaseContainer newInstance(ConnectionUrl url) { return result; } - protected JdbcDatabaseContainer newInstanceFromConnectionUrl(ConnectionUrl connectionUrl, final String userParamName, final String pwdParamName) { + protected JdbcDatabaseContainer newInstanceFromConnectionUrl( + ConnectionUrl connectionUrl, + final String userParamName, + final String pwdParamName + ) { Objects.requireNonNull(connectionUrl, "Connection URL cannot be null"); final String databaseName = connectionUrl.getDatabaseName().orElse("test"); diff --git a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionDelegate.java b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionDelegate.java index e7f59b2df4f..47d3cadc823 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionDelegate.java +++ b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionDelegate.java @@ -1,13 +1,13 @@ package org.testcontainers.jdbc; import lombok.RequiredArgsConstructor; -import lombok.Value; import lombok.experimental.Delegate; import java.sql.Connection; @RequiredArgsConstructor class ConnectionDelegate implements Connection { + @Delegate private final Connection delegate; } diff --git a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionUrl.java b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionUrl.java index 3354ed45c39..b4aef740da0 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionUrl.java +++ b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionUrl.java @@ -1,5 +1,10 @@ package org.testcontainers.jdbc; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import org.testcontainers.UnstableAPI; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -10,13 +15,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import org.testcontainers.UnstableAPI; - -import static java.util.stream.Collectors.toMap; - /** * This is an Immutable class holding JDBC Connection Url and its parsed components, used by {@link ContainerDatabaseDriver}. *

@@ -60,6 +58,7 @@ public class ConnectionUrl { private Map containerParameters; private Map queryParameters; + private Map tmpfsOptions = new HashMap<>(); public static ConnectionUrl newInstance(final String url) { @@ -94,7 +93,9 @@ private void parseUrl() { //Try for Oracle pattern urlMatcher = Patterns.ORACLE_URL_MATCHING_PATTERN.matcher(this.getUrl()); if (!urlMatcher.matches()) { - throw new IllegalArgumentException("JDBC URL matches jdbc:tc: prefix but the database or tag name could not be identified"); + throw new IllegalArgumentException( + "JDBC URL matches jdbc:tc: prefix but the database or tag name could not be identified" + ); } } databaseType = urlMatcher.group("databaseType"); @@ -113,9 +114,10 @@ private void parseUrl() { databaseName = Optional.of(dbInstanceMatcher.group("databaseName")); } - queryParameters = Collections.unmodifiableMap( - parseQueryParameters( - Optional.ofNullable(urlMatcher.group("queryParameters")).orElse(""))); + queryParameters = + Collections.unmodifiableMap( + parseQueryParameters(Optional.ofNullable(urlMatcher.group("queryParameters")).orElse("")) + ); String query = queryParameters .entrySet() @@ -133,7 +135,6 @@ private void parseUrl() { tmpfsOptions = parseTmpfsOptions(containerParameters); - initScriptPath = Optional.ofNullable(containerParameters.get("TC_INITSCRIPT")); reusable = Boolean.parseBoolean(containerParameters.get("TC_REUSABLE")); @@ -145,7 +146,6 @@ private void parseUrl() { Matcher daemonMatcher = Patterns.DAEMON_MATCHING_PATTERN.matcher(this.getUrl()); inDaemonMode = daemonMatcher.matches() && Boolean.parseBoolean(daemonMatcher.group(2)); - } private Map parseTmpfsOptions(Map containerParameters) { @@ -155,10 +155,9 @@ private Map parseTmpfsOptions(Map containerParam String tmpfsOptions = containerParameters.get("TC_TMPFS"); - return Stream.of(tmpfsOptions.split(",")) - .collect(toMap( - string -> string.split(":")[0], - string -> string.split(":")[1])); + return Stream + .of(tmpfsOptions.split(",")) + .collect(Collectors.toMap(string -> string.split(":")[0], string -> string.split(":")[1])); } /** @@ -167,7 +166,6 @@ private Map parseTmpfsOptions(Map containerParam * @return {@link Map} */ private Map parseContainerParameters() { - Map results = new HashMap<>(); Matcher matcher = Patterns.TC_PARAM_MATCHING_PATTERN.matcher(this.getUrl()); @@ -186,14 +184,14 @@ private Map parseContainerParameters() { * @return {@link Map} */ private Map parseQueryParameters(final String queryString) { - Map results = new HashMap<>(); Matcher matcher = Patterns.QUERY_PARAM_MATCHING_PATTERN.matcher(queryString); while (matcher.find()) { String key = matcher.group(1); String value = matcher.group(2); - if (!key.matches(Patterns.TC_PARAM_NAME_PATTERN)) + if (!key.matches(Patterns.TC_PARAM_NAME_PATTERN)) { results.put(key, value); + } } return results; @@ -211,36 +209,36 @@ public Map getTmpfsOptions() { public interface Patterns { Pattern URL_MATCHING_PATTERN = Pattern.compile( "jdbc:tc:" + - "(?[a-z0-9]+)" + - "(:(?[^:]+))?" + - "://" + - "(?[^?]+)" + - "(?\\?.*)?" + "(?[a-z0-9]+)" + + "(:(?[^:]+))?" + + "://" + + "(?[^?]+)" + + "(?\\?.*)?" ); Pattern ORACLE_URL_MATCHING_PATTERN = Pattern.compile( "jdbc:tc:" + - "(?[a-z]+)" + - "(:(?(?!thin).+))?:thin:(//)?" + - "(" + - "(?[^:" + - "?^/]+)/(?[^?^/]+)" + - ")?" + - "@" + - "(?[^?]+)" + - "(?\\?.*)?" + "(?[a-z]+)" + + "(:(?(?!thin).+))?:thin:(//)?" + + "(" + + "(?[^:" + + "?^/]+)/(?[^?^/]+)" + + ")?" + + "@" + + "(?[^?]+)" + + "(?\\?.*)?" ); //Matches to part of string - hostname:port/databasename Pattern DB_INSTANCE_MATCHING_PATTERN = Pattern.compile( "(?[^:]+)" + - "(:(?[0-9]+))?" + - "(" + - "(?[:/])" + - "|" + - ";databaseName=" + - ")" + - "(?[^\\\\?]+)" + "(:(?[0-9]+))?" + + "(" + + "(?[:/])" + + "|" + + ";databaseName=" + + ")" + + "(?[^\\\\?]+)" ); Pattern DAEMON_MATCHING_PATTERN = Pattern.compile(".*([?&]?)TC_DAEMON=([^?&]+).*"); @@ -251,24 +249,27 @@ public interface Patterns { @Deprecated Pattern INITSCRIPT_MATCHING_PATTERN = Pattern.compile(".*([?&]?)TC_INITSCRIPT=([^?&]+).*"); - Pattern INITFUNCTION_MATCHING_PATTERN = Pattern.compile(".*([?&]?)TC_INITFUNCTION=" + + Pattern INITFUNCTION_MATCHING_PATTERN = Pattern.compile( + ".*([?&]?)TC_INITFUNCTION=" + "((\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*\\.)*\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)" + "::" + "(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)" + - ".*"); + ".*" + ); String TC_PARAM_NAME_PATTERN = "(TC_[A-Z_]+)"; Pattern TC_PARAM_MATCHING_PATTERN = Pattern.compile(TC_PARAM_NAME_PATTERN + "=([^?&]+)"); Pattern QUERY_PARAM_MATCHING_PATTERN = Pattern.compile("([^?&=]+)=([^?&]*)"); - } @Getter @AllArgsConstructor public class InitFunctionDef { + private String className; + private String methodName; } } diff --git a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionWrapper.java b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionWrapper.java index 3e1f67c5b86..4f245590f78 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionWrapper.java +++ b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ConnectionWrapper.java @@ -17,7 +17,7 @@ public void close() throws SQLException { super.close(); try { closeCallback.run(); - } catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } } diff --git a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ContainerDatabaseDriver.java b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ContainerDatabaseDriver.java index 4b3a7ba98f7..23ed9d78b25 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ContainerDatabaseDriver.java +++ b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ContainerDatabaseDriver.java @@ -7,7 +7,6 @@ import org.testcontainers.delegate.DatabaseDelegate; import org.testcontainers.ext.ScriptUtils; -import javax.script.ScriptException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -17,6 +16,8 @@ import java.util.*; import java.util.logging.Logger; +import javax.script.ScriptException; + /** * Test Containers JDBC proxy driver. This driver will handle JDBC URLs of the form: *

@@ -38,9 +39,13 @@ public class ContainerDatabaseDriver implements Driver { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(ContainerDatabaseDriver.class); private Driver delegate; + private static final Map> containerConnections = new HashMap<>(); + private static final Map jdbcUrlContainerCache = new HashMap<>(); + private static final Set initializedContainers = new HashSet<>(); + private static final String FILE_PATH_PREFIX = "file:"; static { @@ -62,7 +67,6 @@ public boolean acceptsURL(String url) throws SQLException { @Override public synchronized Connection connect(String url, final Properties info) throws SQLException { - /* The driver should return "null" if it realizes it is the wrong kind of driver to connect to the given URL. */ @@ -73,7 +77,6 @@ public synchronized Connection connect(String url, final Properties info) throws ConnectionUrl connectionUrl = ConnectionUrl.newInstance(url); synchronized (jdbcUrlContainerCache) { - String queryString = connectionUrl.getQueryString().orElse(""); /* If we already have a running container for this exact connection string, we want to connect @@ -81,7 +84,6 @@ public synchronized Connection connect(String url, final Properties info) throws */ JdbcDatabaseContainer container = jdbcUrlContainerCache.get(connectionUrl.getUrl()); if (container == null) { - LOGGER.debug("Container not found in cache, creating new instance"); Map parameters = connectionUrl.getContainerParameters(); @@ -89,7 +91,9 @@ public synchronized Connection connect(String url, final Properties info) throws /* Find a matching container type using ServiceLoader. */ - ServiceLoader databaseContainers = ServiceLoader.load(JdbcDatabaseContainerProvider.class); + ServiceLoader databaseContainers = ServiceLoader.load( + JdbcDatabaseContainerProvider.class + ); for (JdbcDatabaseContainerProvider candidateContainerType : databaseContainers) { if (candidateContainerType.supports(connectionUrl.getDatabaseType())) { container = candidateContainerType.newInstance(connectionUrl); @@ -98,7 +102,9 @@ public synchronized Connection connect(String url, final Properties info) throws } } if (container == null) { - throw new UnsupportedOperationException("Database name " + connectionUrl.getDatabaseType() + " not supported"); + throw new UnsupportedOperationException( + "Database name " + connectionUrl.getDatabaseType() + " not supported" + ); } /* @@ -138,7 +144,6 @@ public synchronized Connection connect(String url, final Properties info) throws } } - /** * Wrap the connection, setting up a callback to be called when the connection is closed. *

@@ -149,25 +154,34 @@ public synchronized Connection connect(String url, final Properties info) throws * @param connectionUrl {@link ConnectionUrl} instance representing JDBC Url for this connection * @return the connection, wrapped */ - private Connection wrapConnection(final Connection connection, final JdbcDatabaseContainer container, final ConnectionUrl connectionUrl) { - + private Connection wrapConnection( + final Connection connection, + final JdbcDatabaseContainer container, + final ConnectionUrl connectionUrl + ) { final boolean isDaemon = connectionUrl.isInDaemonMode() || connectionUrl.isReusable(); - Set connections = containerConnections.computeIfAbsent(container.getContainerId(), k -> new HashSet<>()); + Set connections = containerConnections.computeIfAbsent( + container.getContainerId(), + k -> new HashSet<>() + ); connections.add(connection); final Set finalConnections = connections; - return new ConnectionWrapper(connection, () -> { - finalConnections.remove(connection); - if (!isDaemon && finalConnections.isEmpty()) { - synchronized (jdbcUrlContainerCache) { - container.stop(); - jdbcUrlContainerCache.remove(connectionUrl.getUrl()); + return new ConnectionWrapper( + connection, + () -> { + finalConnections.remove(connection); + if (!isDaemon && finalConnections.isEmpty()) { + synchronized (jdbcUrlContainerCache) { + container.stop(); + jdbcUrlContainerCache.remove(connectionUrl.getUrl()); + } } } - }); + ); } /** @@ -177,7 +191,8 @@ private Connection wrapConnection(final Connection connection, final JdbcDatabas * @param databaseDelegate database delegate to apply init scripts to the database * @throws SQLException on script or DB error */ - private void runInitScriptIfRequired(final ConnectionUrl connectionUrl, DatabaseDelegate databaseDelegate) throws SQLException { + private void runInitScriptIfRequired(final ConnectionUrl connectionUrl, DatabaseDelegate databaseDelegate) + throws SQLException { if (connectionUrl.getInitScriptPath().isPresent()) { String initScriptPath = connectionUrl.getInitScriptPath().get(); try { @@ -191,7 +206,9 @@ private void runInitScriptIfRequired(final ConnectionUrl connectionUrl, Database } if (resource == null) { LOGGER.warn("Could not load classpath init script: {}", initScriptPath); - throw new SQLException("Could not load classpath init script: " + initScriptPath + ". Resource not found."); + throw new SQLException( + "Could not load classpath init script: " + initScriptPath + ". Resource not found." + ); } String sql = IOUtils.toString(resource, StandardCharsets.UTF_8); @@ -213,7 +230,8 @@ private void runInitScriptIfRequired(final ConnectionUrl connectionUrl, Database * @param connection JDBC connection to apply init functions to. * @throws SQLException on script or DB error */ - private void runInitFunctionIfRequired(final ConnectionUrl connectionUrl, Connection connection) throws SQLException { + private void runInitFunctionIfRequired(final ConnectionUrl connectionUrl, Connection connection) + throws SQLException { if (connectionUrl.getInitFunction().isPresent()) { String className = connectionUrl.getInitFunction().get().getClassName(); String methodName = connectionUrl.getInitFunction().get().getMethodName(); @@ -223,7 +241,9 @@ private void runInitFunctionIfRequired(final ConnectionUrl connectionUrl, Connec Method method = initFunctionClazz.getMethod(methodName, Connection.class); method.invoke(null, connection); - } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + } catch ( + ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e + ) { LOGGER.error("Error while executing init function: {}::{}", className, methodName, e); throw new SQLException("Error while executing init function: " + className + "::" + methodName, e); } @@ -270,7 +290,6 @@ public static void killContainers() { containerConnections.clear(); initializedContainers.clear(); } - } /** diff --git a/modules/jdbc/src/main/java/org/testcontainers/jdbc/JdbcDatabaseDelegate.java b/modules/jdbc/src/main/java/org/testcontainers/jdbc/JdbcDatabaseDelegate.java index 6173a8f6a37..7ed2f7ffde1 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/jdbc/JdbcDatabaseDelegate.java +++ b/modules/jdbc/src/main/java/org/testcontainers/jdbc/JdbcDatabaseDelegate.java @@ -18,6 +18,7 @@ public class JdbcDatabaseDelegate extends AbstractDatabaseDelegate { private JdbcDatabaseContainer container; + private String queryString; public JdbcDatabaseDelegate(JdbcDatabaseContainer container, String queryString) { @@ -35,16 +36,27 @@ protected Statement createNewConnection() { } } - @Override - public void execute(String statement, String scriptPath, int lineNumber, boolean continueOnError, boolean ignoreFailedDrops) { + public void execute( + String statement, + String scriptPath, + int lineNumber, + boolean continueOnError, + boolean ignoreFailedDrops + ) { try { boolean rowsAffected = getConnection().execute(statement); log.debug("{} returned as updateCount for SQL: {}", rowsAffected, statement); } catch (SQLException ex) { boolean dropStatement = statement.trim().toLowerCase().startsWith("drop"); if (continueOnError || (dropStatement && ignoreFailedDrops)) { - log.debug("Failed to execute SQL script statement at line {} of resource {}: {}", lineNumber, scriptPath, statement, ex); + log.debug( + "Failed to execute SQL script statement at line {} of resource {}: {}", + lineNumber, + scriptPath, + statement, + ex + ); } else { throw new ScriptUtils.ScriptStatementFailedException(statement, lineNumber, scriptPath, ex); } diff --git a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ext/ScriptUtils.java b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ext/ScriptUtils.java index 76b7a044c9d..c6a3c0fa3ed 100644 --- a/modules/jdbc/src/main/java/org/testcontainers/jdbc/ext/ScriptUtils.java +++ b/modules/jdbc/src/main/java/org/testcontainers/jdbc/ext/ScriptUtils.java @@ -18,10 +18,11 @@ import org.testcontainers.jdbc.ContainerLessJdbcDelegate; -import javax.script.ScriptException; import java.sql.Connection; import java.util.List; +import javax.script.ScriptException; + /** * Wrapper for database-agnostic ScriptUtils * @@ -68,9 +69,24 @@ private ScriptUtils() { * @see org.testcontainers.ext.ScriptUtils * @deprecated Needed only to keep binary compatibility for this internal API. Consider using database-agnostic ScriptUtils */ - public static void splitSqlScript(String resource, String script, String separator, String commentPrefix, - String blockCommentStartDelimiter, String blockCommentEndDelimiter, List statements) { - org.testcontainers.ext.ScriptUtils.splitSqlScript(resource, script, separator, commentPrefix, blockCommentStartDelimiter, blockCommentEndDelimiter, statements); + public static void splitSqlScript( + String resource, + String script, + String separator, + String commentPrefix, + String blockCommentStartDelimiter, + String blockCommentEndDelimiter, + List statements + ) { + org.testcontainers.ext.ScriptUtils.splitSqlScript( + resource, + script, + separator, + commentPrefix, + blockCommentStartDelimiter, + blockCommentEndDelimiter, + statements + ); } /** @@ -85,18 +101,40 @@ public static boolean containsSqlScriptDelimiters(String script, String delim) { * @see org.testcontainers.ext.ScriptUtils * @deprecated Needed only to keep binary compatibility for this internal API. Consider using database-agnostic ScriptUtils */ - public static void executeSqlScript(Connection connection, String scriptPath, String script) throws ScriptException { - org.testcontainers.ext.ScriptUtils.executeDatabaseScript(new ContainerLessJdbcDelegate(connection), scriptPath, script); + public static void executeSqlScript(Connection connection, String scriptPath, String script) + throws ScriptException { + org.testcontainers.ext.ScriptUtils.executeDatabaseScript( + new ContainerLessJdbcDelegate(connection), + scriptPath, + script + ); } /** * @see org.testcontainers.ext.ScriptUtils * @deprecated Needed only to keep binary compatibility for this internal API. Consider using database-agnostic ScriptUtils */ - public static void executeSqlScript(Connection connection, String scriptPath, String script, boolean continueOnError, - boolean ignoreFailedDrops, String commentPrefix, String separator, String blockCommentStartDelimiter, - String blockCommentEndDelimiter) throws ScriptException { - org.testcontainers.ext.ScriptUtils.executeDatabaseScript(new ContainerLessJdbcDelegate(connection), scriptPath, - script, continueOnError, ignoreFailedDrops, commentPrefix, separator, blockCommentStartDelimiter, blockCommentEndDelimiter); + public static void executeSqlScript( + Connection connection, + String scriptPath, + String script, + boolean continueOnError, + boolean ignoreFailedDrops, + String commentPrefix, + String separator, + String blockCommentStartDelimiter, + String blockCommentEndDelimiter + ) throws ScriptException { + org.testcontainers.ext.ScriptUtils.executeDatabaseScript( + new ContainerLessJdbcDelegate(connection), + scriptPath, + script, + continueOnError, + ignoreFailedDrops, + commentPrefix, + separator, + blockCommentStartDelimiter, + blockCommentEndDelimiter + ); } -} \ No newline at end of file +} diff --git a/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java b/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java index 9f0cf514558..1dc6646bd17 100644 --- a/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java +++ b/modules/jdbc/src/test/java/org/testcontainers/containers/JdbcDatabaseContainerTest.java @@ -1,11 +1,12 @@ package org.testcontainers.containers; -import java.sql.Connection; -import java.sql.SQLException; import lombok.NonNull; import org.junit.Test; import org.slf4j.Logger; +import java.sql.Connection; +import java.sql.SQLException; + import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.mock; diff --git a/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlDriversTests.java b/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlDriversTests.java index 12ca5c28c3d..9b88e6b503d 100644 --- a/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlDriversTests.java +++ b/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlDriversTests.java @@ -5,9 +5,9 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; +import java.util.Arrays; import java.util.Optional; -import static java.util.Arrays.asList; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; /** @@ -20,35 +20,106 @@ public class ConnectionUrlDriversTests { @Parameter public String jdbcUrl; + @Parameter(1) public String databaseType; + @Parameter(2) public Optional tag; + @Parameter(3) public String dbHostString; + @Parameter(4) public String databaseName; @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:mysql:5.7.34://hostname/test", "mysql", Optional.of("5.7.34"), "hostname/test", "test"}, - {"jdbc:tc:mysql://hostname/test", "mysql", Optional.empty(), "hostname/test", "test"}, - {"jdbc:tc:postgresql:1.2.3://hostname/test", "postgresql", Optional.of("1.2.3"), "hostname/test", "test"}, - {"jdbc:tc:postgresql://hostname/test", "postgresql", Optional.empty(), "hostname/test", "test"}, - {"jdbc:tc:sqlserver:1.2.3://localhost;instance=SQLEXPRESS:1433;databaseName=test", "sqlserver", Optional.of("1.2.3"), "localhost;instance=SQLEXPRESS:1433;databaseName=test", "test"}, - {"jdbc:tc:sqlserver://localhost;instance=SQLEXPRESS:1433;databaseName=test", "sqlserver", Optional.empty(), "localhost;instance=SQLEXPRESS:1433;databaseName=test", "test"}, - {"jdbc:tc:mariadb:1.2.3://localhost:3306/test", "mariadb", Optional.of("1.2.3"), "localhost:3306/test", "test"}, - {"jdbc:tc:mariadb://localhost:3306/test", "mariadb", Optional.empty(), "localhost:3306/test", "test"}, - {"jdbc:tc:oracle:1.2.3:thin://@localhost:1521/test", "oracle", Optional.of("1.2.3"), "localhost:1521/test", "test"}, - {"jdbc:tc:oracle:1.2.3:thin:@localhost:1521/test", "oracle", Optional.of("1.2.3"), "localhost:1521/test", "test"}, - {"jdbc:tc:oracle:thin:@localhost:1521/test", "oracle", Optional.empty(), "localhost:1521/test", "test"}, - {"jdbc:tc:oracle:1.2.3:thin:@localhost:1521:test", "oracle", Optional.of("1.2.3"), "localhost:1521:test", "test"}, - {"jdbc:tc:oracle:1.2.3:thin://@localhost:1521:test", "oracle", Optional.of("1.2.3"), "localhost:1521:test", "test"}, - {"jdbc:tc:oracle:1.2.3-anything:thin://@localhost:1521:test", "oracle", Optional.of("1.2.3-anything"), "localhost:1521:test", "test"}, - {"jdbc:tc:oracle:thin:@localhost:1521:test", "oracle", Optional.empty(), "localhost:1521:test", "test"} - }); + return Arrays.asList( + new Object[][] { + { "jdbc:tc:mysql:5.7.34://hostname/test", "mysql", Optional.of("5.7.34"), "hostname/test", "test" }, + { "jdbc:tc:mysql://hostname/test", "mysql", Optional.empty(), "hostname/test", "test" }, + { + "jdbc:tc:postgresql:1.2.3://hostname/test", + "postgresql", + Optional.of("1.2.3"), + "hostname/test", + "test", + }, + { "jdbc:tc:postgresql://hostname/test", "postgresql", Optional.empty(), "hostname/test", "test" }, + { + "jdbc:tc:sqlserver:1.2.3://localhost;instance=SQLEXPRESS:1433;databaseName=test", + "sqlserver", + Optional.of("1.2.3"), + "localhost;instance=SQLEXPRESS:1433;databaseName=test", + "test", + }, + { + "jdbc:tc:sqlserver://localhost;instance=SQLEXPRESS:1433;databaseName=test", + "sqlserver", + Optional.empty(), + "localhost;instance=SQLEXPRESS:1433;databaseName=test", + "test", + }, + { + "jdbc:tc:mariadb:1.2.3://localhost:3306/test", + "mariadb", + Optional.of("1.2.3"), + "localhost:3306/test", + "test", + }, + { "jdbc:tc:mariadb://localhost:3306/test", "mariadb", Optional.empty(), "localhost:3306/test", "test" }, + { + "jdbc:tc:oracle:1.2.3:thin://@localhost:1521/test", + "oracle", + Optional.of("1.2.3"), + "localhost:1521/test", + "test", + }, + { + "jdbc:tc:oracle:1.2.3:thin:@localhost:1521/test", + "oracle", + Optional.of("1.2.3"), + "localhost:1521/test", + "test", + }, + { + "jdbc:tc:oracle:thin:@localhost:1521/test", + "oracle", + Optional.empty(), + "localhost:1521/test", + "test", + }, + { + "jdbc:tc:oracle:1.2.3:thin:@localhost:1521:test", + "oracle", + Optional.of("1.2.3"), + "localhost:1521:test", + "test", + }, + { + "jdbc:tc:oracle:1.2.3:thin://@localhost:1521:test", + "oracle", + Optional.of("1.2.3"), + "localhost:1521:test", + "test", + }, + { + "jdbc:tc:oracle:1.2.3-anything:thin://@localhost:1521:test", + "oracle", + Optional.of("1.2.3-anything"), + "localhost:1521:test", + "test", + }, + { + "jdbc:tc:oracle:thin:@localhost:1521:test", + "oracle", + Optional.empty(), + "localhost:1521:test", + "test", + }, + } + ); } @Test diff --git a/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlTest.java b/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlTest.java index 4fefd5d1e13..6888f881ec4 100644 --- a/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlTest.java +++ b/modules/jdbc/src/test/java/org/testcontainers/jdbc/ConnectionUrlTest.java @@ -13,7 +13,6 @@ public class ConnectionUrlTest { @Rule public ExpectedException thrown = ExpectedException.none(); - @Test public void testConnectionUrl1() { String urlString = "jdbc:tc:mysql:5.7.34://somehostname:3306/databasename?a=b&c=d"; @@ -31,7 +30,6 @@ public void testConnectionUrl1() { assertEquals("Parameter c is captured", "d", url.getQueryParameters().get("c")); } - @Test public void testConnectionUrl2() { String urlString = "jdbc:tc:mysql://somehostname/databasename"; @@ -46,7 +44,6 @@ public void testConnectionUrl2() { assertEquals("Database Name value is as expected", "databasename", url.getDatabaseName().get()); assertTrue("Connection Parameters set is empty", url.getQueryParameters().isEmpty()); - } @Test @@ -62,40 +59,55 @@ public void testTmpfsOption() { assertTrue("Connection Parameters set is empty", url.getQueryParameters().isEmpty()); assertFalse("Container Parameters set is not empty", url.getContainerParameters().isEmpty()); - assertEquals("Container Parameter TC_TMPFS is true", "key:value,key1:value1", url.getContainerParameters().get("TC_TMPFS")); + assertEquals( + "Container Parameter TC_TMPFS is true", + "key:value,key1:value1", + url.getContainerParameters().get("TC_TMPFS") + ); assertTrue("tmpfs option key exists", url.getTmpfsOptions().containsKey("key")); - assertEquals("tmpfs option key has correct value", "value" , url.getTmpfsOptions().get("key")); + assertEquals("tmpfs option key has correct value", "value", url.getTmpfsOptions().get("key")); assertTrue("tmpfs option key1 exists", url.getTmpfsOptions().containsKey("key1")); - assertEquals("tmpfs option key1 has correct value", "value1" , url.getTmpfsOptions().get("key1")); + assertEquals("tmpfs option key1 has correct value", "value1", url.getTmpfsOptions().get("key1")); } - @Test public void testInitScriptPathCapture() { - String urlString = "jdbc:tc:mysql:5.7.34://somehostname:3306/databasename?a=b&c=d&TC_INITSCRIPT=somepath/init_mysql.sql"; + String urlString = + "jdbc:tc:mysql:5.7.34://somehostname:3306/databasename?a=b&c=d&TC_INITSCRIPT=somepath/init_mysql.sql"; ConnectionUrl url = ConnectionUrl.newInstance(urlString); assertEquals("Database Type value is as expected", "somepath/init_mysql.sql", url.getInitScriptPath().get()); assertEquals("Query String value is as expected", "?a=b&c=d", url.getQueryString().get()); - assertEquals("INIT SCRIPT Path exists in Container Parameters", "somepath/init_mysql.sql", url.getContainerParameters().get("TC_INITSCRIPT")); + assertEquals( + "INIT SCRIPT Path exists in Container Parameters", + "somepath/init_mysql.sql", + url.getContainerParameters().get("TC_INITSCRIPT") + ); //Parameter sets are unmodifiable thrown.expect(UnsupportedOperationException.class); url.getContainerParameters().remove("TC_INITSCRIPT"); url.getQueryParameters().remove("a"); - } @Test public void testInitFunctionCapture() { - String urlString = "jdbc:tc:mysql:5.7.34://somehostname:3306/databasename?a=b&c=d&TC_INITFUNCTION=org.testcontainers.jdbc.JDBCDriverTest::sampleInitFunction"; + String urlString = + "jdbc:tc:mysql:5.7.34://somehostname:3306/databasename?a=b&c=d&TC_INITFUNCTION=org.testcontainers.jdbc.JDBCDriverTest::sampleInitFunction"; ConnectionUrl url = ConnectionUrl.newInstance(urlString); assertTrue("Init Function parameter exists", url.getInitFunction().isPresent()); - assertEquals("Init function class is as expected", "org.testcontainers.jdbc.JDBCDriverTest", url.getInitFunction().get().getClassName()); - assertEquals("Init function class is as expected", "sampleInitFunction", url.getInitFunction().get().getMethodName()); - + assertEquals( + "Init function class is as expected", + "org.testcontainers.jdbc.JDBCDriverTest", + url.getInitFunction().get().getClassName() + ); + assertEquals( + "Init function class is as expected", + "sampleInitFunction", + url.getInitFunction().get().getMethodName() + ); } @Test @@ -104,6 +116,5 @@ public void testDaemonCapture() { ConnectionUrl url = ConnectionUrl.newInstance(urlString); assertTrue("Daemon flag is set to true.", url.isInDaemonMode()); - } } diff --git a/modules/jdbc/src/test/java/org/testcontainers/jdbc/ContainerDatabaseDriverTest.java b/modules/jdbc/src/test/java/org/testcontainers/jdbc/ContainerDatabaseDriverTest.java index d33e399db27..5b4d223cd36 100644 --- a/modules/jdbc/src/test/java/org/testcontainers/jdbc/ContainerDatabaseDriverTest.java +++ b/modules/jdbc/src/test/java/org/testcontainers/jdbc/ContainerDatabaseDriverTest.java @@ -13,23 +13,22 @@ public class ContainerDatabaseDriverTest { - private static final String PLAIN_POSTGRESQL_JDBC_URL = "jdbc:postgresql://localhost:5432/test"; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void shouldNotTryToConnectToNonMatchingJdbcUrlDirectly() throws SQLException { - ContainerDatabaseDriver driver = new ContainerDatabaseDriver(); - Connection connection = driver.connect(PLAIN_POSTGRESQL_JDBC_URL, new Properties()); - Assert.assertNull(connection); - } - - @Test - public void shouldNotTryToConnectToNonMatchingJdbcUrlViaDriverManager() throws SQLException { - thrown.expect(SQLException.class); - thrown.expectMessage(CoreMatchers.startsWith("No suitable driver found for ")); - DriverManager.getConnection(PLAIN_POSTGRESQL_JDBC_URL); - } - + private static final String PLAIN_POSTGRESQL_JDBC_URL = "jdbc:postgresql://localhost:5432/test"; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void shouldNotTryToConnectToNonMatchingJdbcUrlDirectly() throws SQLException { + ContainerDatabaseDriver driver = new ContainerDatabaseDriver(); + Connection connection = driver.connect(PLAIN_POSTGRESQL_JDBC_URL, new Properties()); + Assert.assertNull(connection); + } + + @Test + public void shouldNotTryToConnectToNonMatchingJdbcUrlViaDriverManager() throws SQLException { + thrown.expect(SQLException.class); + thrown.expectMessage(CoreMatchers.startsWith("No suitable driver found for ")); + DriverManager.getConnection(PLAIN_POSTGRESQL_JDBC_URL); + } } diff --git a/modules/jdbc/src/test/java/org/testcontainers/jdbc/MissingJdbcDriverTest.java b/modules/jdbc/src/test/java/org/testcontainers/jdbc/MissingJdbcDriverTest.java index 46138d91347..68afe8692e8 100644 --- a/modules/jdbc/src/test/java/org/testcontainers/jdbc/MissingJdbcDriverTest.java +++ b/modules/jdbc/src/test/java/org/testcontainers/jdbc/MissingJdbcDriverTest.java @@ -17,7 +17,6 @@ public class MissingJdbcDriverTest { @Test public void shouldFailFastIfNoDriverFound() { - final MissingDriverContainer container = new MissingDriverContainer(); try { @@ -37,6 +36,7 @@ public void shouldFailFastIfNoDriverFound() { * Container class for the purposes of testing, with a known non-existent driver */ static class MissingDriverContainer extends JdbcDatabaseContainer { + private final AtomicInteger connectionAttempts = new AtomicInteger(); MissingDriverContainer() { diff --git a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGenerator.java b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGenerator.java index ef8560b3f19..a8612fc1516 100644 --- a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGenerator.java +++ b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGenerator.java @@ -1,22 +1,22 @@ package org.testcontainers.junit.jupiter; import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.platform.commons.util.StringUtils; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.junit.platform.commons.util.StringUtils.isBlank; +import java.nio.charset.StandardCharsets; class FilesystemFriendlyNameGenerator { + private static final String UNKNOWN_NAME = "unknown"; static String filesystemFriendlyNameOf(ExtensionContext context) { String contextId = context.getUniqueId(); try { - return (isBlank(contextId)) + return (StringUtils.isBlank(contextId)) ? UNKNOWN_NAME - : URLEncoder.encode(contextId, UTF_8.toString()); + : URLEncoder.encode(contextId, StandardCharsets.UTF_8.toString()); } catch (UnsupportedEncodingException e) { return UNKNOWN_NAME; } diff --git a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/Testcontainers.java b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/Testcontainers.java index db8273563a7..730339f0fd5 100644 --- a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/Testcontainers.java +++ b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/Testcontainers.java @@ -59,7 +59,6 @@ @ExtendWith(TestcontainersExtension.class) @Inherited public @interface Testcontainers { - /** * Whether tests should be disabled (rather than failing) when Docker is not available. */ diff --git a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersExtension.java b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersExtension.java index 990940be14d..47ed56d9ac5 100644 --- a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersExtension.java +++ b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersExtension.java @@ -29,33 +29,38 @@ import java.util.Optional; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Collectors; import java.util.stream.Stream; -import static java.util.stream.Collectors.toList; -import static org.testcontainers.junit.jupiter.FilesystemFriendlyNameGenerator.filesystemFriendlyNameOf; - -class TestcontainersExtension implements BeforeEachCallback, BeforeAllCallback, AfterEachCallback, AfterAllCallback, ExecutionCondition { +class TestcontainersExtension + implements BeforeEachCallback, BeforeAllCallback, AfterEachCallback, AfterAllCallback, ExecutionCondition { private static final Namespace NAMESPACE = Namespace.create(TestcontainersExtension.class); private static final String SHARED_LIFECYCLE_AWARE_CONTAINERS = "sharedLifecycleAwareContainers"; + private static final String LOCAL_LIFECYCLE_AWARE_CONTAINERS = "localLifecycleAwareContainers"; @Override public void beforeAll(ExtensionContext context) { - Class testClass = context.getTestClass() - .orElseThrow(() -> new ExtensionConfigurationException("TestcontainersExtension is only supported for classes.")); + Class testClass = context + .getTestClass() + .orElseThrow(() -> { + return new ExtensionConfigurationException("TestcontainersExtension is only supported for classes."); + }); Store store = context.getStore(NAMESPACE); List sharedContainersStoreAdapters = findSharedContainers(testClass); - sharedContainersStoreAdapters.forEach(adapter -> store.getOrComputeIfAbsent(adapter.getKey(), k -> adapter.start())); + sharedContainersStoreAdapters.forEach(adapter -> { + store.getOrComputeIfAbsent(adapter.getKey(), k -> adapter.start()); + }); List lifecycleAwareContainers = sharedContainersStoreAdapters .stream() .filter(this::isTestLifecycleAware) .map(lifecycleAwareAdapter -> (TestLifecycleAware) lifecycleAwareAdapter.container) - .collect(toList()); + .collect(Collectors.toList()); store.put(SHARED_LIFECYCLE_AWARE_CONTAINERS, lifecycleAwareContainers); signalBeforeTestToContainers(lifecycleAwareContainers, testDescriptionFrom(context)); @@ -70,12 +75,13 @@ public void afterAll(ExtensionContext context) { public void beforeEach(final ExtensionContext context) { Store store = context.getStore(NAMESPACE); - List lifecycleAwareContainers = collectParentTestInstances(context).parallelStream() + List lifecycleAwareContainers = collectParentTestInstances(context) + .parallelStream() .flatMap(this::findRestartContainers) .peek(adapter -> store.getOrComputeIfAbsent(adapter.getKey(), k -> adapter.start())) .filter(this::isTestLifecycleAware) .map(lifecycleAwareAdapter -> (TestLifecycleAware) lifecycleAwareAdapter.container) - .collect(toList()); + .collect(Collectors.toList()); store.put(LOCAL_LIFECYCLE_AWARE_CONTAINERS, lifecycleAwareContainers); signalBeforeTestToContainers(lifecycleAwareContainers, testDescriptionFrom(context)); @@ -86,13 +92,17 @@ public void afterEach(ExtensionContext context) { signalAfterTestToContainersFor(LOCAL_LIFECYCLE_AWARE_CONTAINERS, context); } - private void signalBeforeTestToContainers(List lifecycleAwareContainers, TestDescription testDescription) { + private void signalBeforeTestToContainers( + List lifecycleAwareContainers, + TestDescription testDescription + ) { lifecycleAwareContainers.forEach(container -> container.beforeTest(testDescription)); } private void signalAfterTestToContainersFor(String storeKey, ExtensionContext context) { - List lifecycleAwareContainers = - (List) context.getStore(NAMESPACE).get(storeKey); + List lifecycleAwareContainers = (List) context + .getStore(NAMESPACE) + .get(storeKey); if (lifecycleAwareContainers != null) { TestDescription description = testDescriptionFrom(context); Optional throwable = context.getExecutionException(); @@ -103,7 +113,7 @@ private void signalAfterTestToContainersFor(String storeKey, ExtensionContext co private TestDescription testDescriptionFrom(ExtensionContext context) { return new TestcontainersTestDescription( context.getUniqueId(), - filesystemFriendlyNameOf(context) + FilesystemFriendlyNameGenerator.filesystemFriendlyNameOf(context) ); } @@ -113,14 +123,18 @@ private boolean isTestLifecycleAware(StoreAdapter adapter) { @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - return findTestcontainers(context).map(this::evaluate) + return findTestcontainers(context) + .map(this::evaluate) .orElseThrow(() -> new ExtensionConfigurationException("@Testcontainers not found")); } private Optional findTestcontainers(ExtensionContext context) { Optional current = Optional.of(context); while (current.isPresent()) { - Optional testcontainers = AnnotationUtils.findAnnotation(current.get().getRequiredTestClass(), Testcontainers.class); + Optional testcontainers = AnnotationUtils.findAnnotation( + current.get().getRequiredTestClass(), + Testcontainers.class + ); if (testcontainers.isPresent()) { return testcontainers; } @@ -155,13 +169,11 @@ private Set collectParentTestInstances(final ExtensionContext context) { } private List findSharedContainers(Class testClass) { - return ReflectionUtils.findFields( - testClass, - isSharedContainer(), - ReflectionUtils.HierarchyTraversalMode.TOP_DOWN) + return ReflectionUtils + .findFields(testClass, isSharedContainer(), ReflectionUtils.HierarchyTraversalMode.TOP_DOWN) .stream() .map(f -> getContainerInstance(null, f)) - .collect(toList()); + .collect(Collectors.toList()); } private Predicate isSharedContainer() { @@ -169,10 +181,8 @@ private Predicate isSharedContainer() { } private Stream findRestartContainers(Object testInstance) { - return ReflectionUtils.findFields( - testInstance.getClass(), - isRestartContainer(), - ReflectionUtils.HierarchyTraversalMode.TOP_DOWN) + return ReflectionUtils + .findFields(testInstance.getClass(), isRestartContainer(), ReflectionUtils.HierarchyTraversalMode.TOP_DOWN) .stream() .map(f -> getContainerInstance(testInstance, f)); } @@ -188,7 +198,9 @@ private static Predicate isContainer() { boolean isStartable = Startable.class.isAssignableFrom(field.getType()); if (!isStartable) { - throw new ExtensionConfigurationException(String.format("FieldName: %s does not implement Startable", field.getName())); + throw new ExtensionConfigurationException( + String.format("FieldName: %s does not implement Startable", field.getName()) + ); } return true; } @@ -199,7 +211,10 @@ private static Predicate isContainer() { private static StoreAdapter getContainerInstance(final Object testInstance, final Field field) { try { field.setAccessible(true); - Startable containerInstance = Preconditions.notNull((Startable) field.get(testInstance), "Container " + field.getName() + " needs to be initialized"); + Startable containerInstance = Preconditions.notNull( + (Startable) field.get(testInstance), + "Container " + field.getName() + " needs to be initialized" + ); return new StoreAdapter(field.getDeclaringClass(), field.getName(), containerInstance); } catch (IllegalAccessException e) { throw new ExtensionConfigurationException("Can not access container defined in field " + field.getName()); diff --git a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersTestDescription.java b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersTestDescription.java index 568d228e08c..3cf466a5708 100644 --- a/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersTestDescription.java +++ b/modules/junit-jupiter/src/main/java/org/testcontainers/junit/jupiter/TestcontainersTestDescription.java @@ -5,6 +5,8 @@ @Value class TestcontainersTestDescription implements TestDescription { + String testId; + String filesystemFriendlyName; } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/ComposeContainerTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/ComposeContainerTests.java index 11b9027b392..f49aa8732f5 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/ComposeContainerTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/ComposeContainerTests.java @@ -18,7 +18,8 @@ class ComposeContainerTests { @Container private DockerComposeContainer composeContainer = new DockerComposeContainer( - new File("src/test/resources/docker-compose.yml")) + new File("src/test/resources/docker-compose.yml") + ) .withExposedService("whoami_1", 80, Wait.forHttp("/")); private String host; diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGeneratorTest.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGeneratorTest.java index 96617b0e063..9050df6f257 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGeneratorTest.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/FilesystemFriendlyNameGeneratorTest.java @@ -10,7 +10,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.testcontainers.junit.jupiter.FilesystemFriendlyNameGenerator.filesystemFriendlyNameOf; class FilesystemFriendlyNameGeneratorTest { @@ -18,10 +17,9 @@ class FilesystemFriendlyNameGeneratorTest { @MethodSource("provideDisplayNamesAndFilesystemFriendlyNames") void should_generate_filesystem_friendly_name(String displayName, String expectedName) { ExtensionContext context = mock(ExtensionContext.class); - doReturn(displayName) - .when(context).getUniqueId(); + doReturn(displayName).when(context).getUniqueId(); - String filesystemFriendlyName = filesystemFriendlyNameOf(context); + String filesystemFriendlyName = FilesystemFriendlyNameGenerator.filesystemFriendlyNameOf(context); assertThat(filesystemFriendlyName).isEqualTo(expectedName); } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/MixedLifecycleTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/MixedLifecycleTests.java index 791c887cc19..6c44d978b69 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/MixedLifecycleTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/MixedLifecycleTests.java @@ -1,19 +1,11 @@ package org.testcontainers.junit.jupiter; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.HttpClientBuilder; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.testcontainers.containers.DockerComposeContainer; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.containers.wait.strategy.Wait; import static org.junit.jupiter.api.Assertions.assertTrue; - // testClass { @Testcontainers class MixedLifecycleTests { diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/PostgresContainerTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/PostgresContainerTests.java index 4cbc331e64b..186d4095b0d 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/PostgresContainerTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/PostgresContainerTests.java @@ -9,16 +9,17 @@ import java.sql.Statement; import static org.junit.Assert.assertEquals; -import static org.testcontainers.junit.jupiter.JUnitJupiterTestImages.POSTGRES_IMAGE; @Testcontainers class PostgresContainerTests { @Container - private static final PostgreSQLContainer POSTGRE_SQL_CONTAINER = new PostgreSQLContainer<>(POSTGRES_IMAGE) - .withDatabaseName("foo") - .withUsername("foo") - .withPassword("secret"); + private static final PostgreSQLContainer POSTGRE_SQL_CONTAINER = new PostgreSQLContainer<>( + JUnitJupiterTestImages.POSTGRES_IMAGE + ) + .withDatabaseName("foo") + .withUsername("foo") + .withPassword("secret"); @Test void waits_until_postgres_accepts_jdbc_connections() throws Exception { @@ -37,5 +38,4 @@ void waits_until_postgres_accepts_jdbc_connections() throws Exception { assertEquals(1, resultSetInt); } } - } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareContainerMock.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareContainerMock.java index 38751c8789a..a8217d60840 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareContainerMock.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareContainerMock.java @@ -11,9 +11,11 @@ public class TestLifecycleAwareContainerMock implements Startable, TestLifecycleAware { static final String BEFORE_TEST = "beforeTest"; + static final String AFTER_TEST = "afterTest"; private final List lifecycleMethodCalls = new ArrayList<>(); + private final List lifecycleFilesystemFriendlyNames = new ArrayList<>(); private Throwable capturedThrowable; @@ -43,12 +45,8 @@ public List getLifecycleFilesystemFriendlyNames() { } @Override - public void start() { - - } + public void start() {} @Override - public void stop() { - - } + public void stop() {} } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareExceptionCapturingTest.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareExceptionCapturingTest.java index 85d837a7880..09b816be56e 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareExceptionCapturingTest.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareExceptionCapturingTest.java @@ -14,6 +14,7 @@ @Testcontainers @TestMethodOrder(OrderAnnotation.class) class TestLifecycleAwareExceptionCapturingTest { + @Container private final TestLifecycleAwareContainerMock testContainer = new TestLifecycleAwareContainerMock(); diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareMethodTest.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareMethodTest.java index cecdff490ef..a77242e1d3a 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareMethodTest.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestLifecycleAwareMethodTest.java @@ -10,14 +10,13 @@ import org.junit.jupiter.api.extension.ExtensionContext; import static org.assertj.core.api.Assertions.assertThat; -import static org.testcontainers.junit.jupiter.TestLifecycleAwareContainerMock.AFTER_TEST; -import static org.testcontainers.junit.jupiter.TestLifecycleAwareContainerMock.BEFORE_TEST; // The order of @ExtendsWith and @Testcontainers is crucial for the tests -@ExtendWith({TestLifecycleAwareMethodTest.SharedContainerAfterAllTestExtension.class}) +@ExtendWith({ TestLifecycleAwareMethodTest.SharedContainerAfterAllTestExtension.class }) @Testcontainers @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class TestLifecycleAwareMethodTest { + @Container private final TestLifecycleAwareContainerMock testContainer = new TestLifecycleAwareContainerMock(); @@ -28,8 +27,8 @@ class TestLifecycleAwareMethodTest { @BeforeAll static void beforeAll() { - assertThat(SHARED_CONTAINER.getLifecycleMethodCalls()).containsExactly(BEFORE_TEST); - + assertThat(SHARED_CONTAINER.getLifecycleMethodCalls()) + .containsExactly(TestLifecycleAwareContainerMock.BEFORE_TEST); } @Test @@ -43,7 +42,7 @@ void should_prepare_before_and_after_test() { @Order(2) void should_call_beforeTest_first_afterTest_later_with_filesystem_friendly_name() { assertThat(startedTestContainer.getLifecycleMethodCalls()) - .containsExactly(BEFORE_TEST, AFTER_TEST); + .containsExactly(TestLifecycleAwareContainerMock.BEFORE_TEST, TestLifecycleAwareContainerMock.AFTER_TEST); } @Test @@ -63,11 +62,15 @@ void static_container_should_have_a_filesystem_friendly_name_after_container_has } static class SharedContainerAfterAllTestExtension implements AfterAllCallback { + // Unfortunately it's not possible to write a @Test that is run after all tests @Override public void afterAll(ExtensionContext context) { assertThat(SHARED_CONTAINER.getLifecycleMethodCalls()) - .containsExactly(BEFORE_TEST, AFTER_TEST); + .containsExactly( + TestLifecycleAwareContainerMock.BEFORE_TEST, + TestLifecycleAwareContainerMock.AFTER_TEST + ); } } } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersExtensionTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersExtensionTests.java index f3aea9bb850..526038853c9 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersExtensionTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersExtensionTests.java @@ -46,14 +46,10 @@ private ExtensionContext extensionContext(Class clazz) { } @Testcontainers(disabledWithoutDocker = true) - static final class DisabledWithoutDocker { - - } + static final class DisabledWithoutDocker {} @Testcontainers - static final class EnabledWithoutDocker { - - } + static final class EnabledWithoutDocker {} static final class TestTestcontainersExtension extends TestcontainersExtension { @@ -66,7 +62,5 @@ private TestTestcontainersExtension(boolean dockerAvailable) { boolean isDockerAvailable() { return dockerAvailable; } - } - } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedRestartedContainerTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedRestartedContainerTests.java index 6e02e31b774..c41b184defa 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedRestartedContainerTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedRestartedContainerTests.java @@ -6,15 +6,15 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.testcontainers.junit.jupiter.JUnitJupiterTestImages.HTTPD_IMAGE; // testClass { @Testcontainers class TestcontainersNestedRestartedContainerTests { @Container - private final GenericContainer topLevelContainer = new GenericContainer<>(HTTPD_IMAGE) + private final GenericContainer topLevelContainer = new GenericContainer<>(JUnitJupiterTestImages.HTTPD_IMAGE) .withExposedPorts(80); + // }} private static String topLevelContainerId; @@ -25,16 +25,16 @@ class TestcontainersNestedRestartedContainerTests { @Test void top_level_container_should_be_running() { assertTrue(topLevelContainer.isRunning()); -// }} + // }} topLevelContainerId = topLevelContainer.getContainerId(); -// testClass {{ + // testClass {{ } @Nested class NestedTestCase { @Container - private final GenericContainer nestedContainer = new GenericContainer<>(HTTPD_IMAGE) + private final GenericContainer nestedContainer = new GenericContainer<>(JUnitJupiterTestImages.HTTPD_IMAGE) .withExposedPorts(80); @Test @@ -43,13 +43,13 @@ void both_containers_should_be_running() { assertTrue(topLevelContainer.isRunning()); // nested containers are only available inside their nested class assertTrue(nestedContainer.isRunning()); -// }}} + // }}} if (nestedContainerId == null) { nestedContainerId = nestedContainer.getContainerId(); } else { assertNotEquals(nestedContainerId, nestedContainer.getContainerId()); } -// testClass {{ + // testClass {{ } // } @@ -74,7 +74,7 @@ void ids_should_not_change() { assertNotEquals(nestedContainerId, nestedContainer.getContainerId()); } } -// testClass {{{ + // testClass {{{ } } // } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedSharedContainerTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedSharedContainerTests.java index cf59e0338a2..c00e66c2d9d 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedSharedContainerTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersNestedSharedContainerTests.java @@ -6,13 +6,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.testcontainers.junit.jupiter.JUnitJupiterTestImages.HTTPD_IMAGE; @Testcontainers class TestcontainersNestedSharedContainerTests { @Container - private static final GenericContainer TOP_LEVEL_CONTAINER = new GenericContainer<>(HTTPD_IMAGE) + private static final GenericContainer TOP_LEVEL_CONTAINER = new GenericContainer<>( + JUnitJupiterTestImages.HTTPD_IMAGE + ) .withExposedPorts(80); private static String topLevelContainerId; diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersRestartBetweenTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersRestartBetweenTests.java index eeb63b72380..46c6045984f 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersRestartBetweenTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersRestartBetweenTests.java @@ -4,14 +4,13 @@ import org.testcontainers.containers.GenericContainer; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.testcontainers.junit.jupiter.JUnitJupiterTestImages.HTTPD_IMAGE; @Testcontainers class TestcontainersRestartBetweenTests { @Container - private GenericContainer genericContainer = new GenericContainer<>(HTTPD_IMAGE) - .withExposedPorts(80); + private GenericContainer genericContainer = new GenericContainer<>(JUnitJupiterTestImages.HTTPD_IMAGE) + .withExposedPorts(80); private static String lastContainerId; @@ -19,7 +18,7 @@ class TestcontainersRestartBetweenTests { void first_test() { if (lastContainerId == null) { lastContainerId = genericContainer.getContainerId(); - } else { + } else { assertNotEquals(lastContainerId, genericContainer.getContainerId()); } } @@ -28,9 +27,8 @@ void first_test() { void second_test() { if (lastContainerId == null) { lastContainerId = genericContainer.getContainerId(); - } else { + } else { assertNotEquals(lastContainerId, genericContainer.getContainerId()); } } - } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersSharedContainerTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersSharedContainerTests.java index 60094994f69..b23b2fe0e53 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersSharedContainerTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/TestcontainersSharedContainerTests.java @@ -6,13 +6,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.testcontainers.junit.jupiter.JUnitJupiterTestImages.HTTPD_IMAGE; @Testcontainers class TestcontainersSharedContainerTests { @Container - private static final GenericContainer GENERIC_CONTAINER = new GenericContainer<>(HTTPD_IMAGE) + private static final GenericContainer GENERIC_CONTAINER = new GenericContainer<>( + JUnitJupiterTestImages.HTTPD_IMAGE + ) .withExposedPorts(80); private static String lastContainerId; @@ -39,5 +40,4 @@ void second_test() { assertEquals(lastContainerId, GENERIC_CONTAINER.getContainerId()); } } - } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/WrongAnnotationUsageTests.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/WrongAnnotationUsageTests.java index bec99894307..9fe9893d9ee 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/WrongAnnotationUsageTests.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/WrongAnnotationUsageTests.java @@ -1,10 +1,8 @@ package org.testcontainers.junit.jupiter; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; - @Disabled @Testcontainers class WrongAnnotationUsageTests { @@ -16,5 +14,4 @@ class WrongAnnotationUsageTests { void extension_throws_exception() { assert true; } - } diff --git a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/inheritance/AbstractTestBase.java b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/inheritance/AbstractTestBase.java index 3766c3f7a60..70614d3dbc7 100644 --- a/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/inheritance/AbstractTestBase.java +++ b/modules/junit-jupiter/src/test/java/org/testcontainers/junit/jupiter/inheritance/AbstractTestBase.java @@ -11,5 +11,4 @@ abstract class AbstractTestBase { @Container RedisContainer redisPerTest = new RedisContainer(); - } diff --git a/modules/k3s/src/main/java/org/testcontainers/k3s/K3sContainer.java b/modules/k3s/src/main/java/org/testcontainers/k3s/K3sContainer.java index 7f21ca7dbb8..c9dad93a06e 100644 --- a/modules/k3s/src/main/java/org/testcontainers/k3s/K3sContainer.java +++ b/modules/k3s/src/main/java/org/testcontainers/k3s/K3sContainer.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.node.TextNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.github.dockerjava.api.command.InspectContainerResponse; -import com.github.dockerjava.api.model.DockerObjectAccessor; import lombok.SneakyThrows; import org.apache.commons.io.IOUtils; import org.testcontainers.containers.BindMode; @@ -42,17 +41,14 @@ public K3sContainer(DockerImageName dockerImageName) { tmpFsMapping.put("/var/run", ""); setTmpFsMapping(tmpFsMapping); - setCommand( - "server", - "--no-deploy=traefik", - "--tls-san=" + this.getHost() - ); + setCommand("server", "--no-deploy=traefik", "--tls-san=" + this.getHost()); setWaitStrategy(new LogMessageWaitStrategy().withRegEx(".*Node controller sync successful.*")); } @Override protected void containerIsStarted(InspectContainerResponse containerInfo) { - String rawKubeConfig = copyFileFromContainer("/etc/rancher/k3s/k3s.yaml", + String rawKubeConfig = copyFileFromContainer( + "/etc/rancher/k3s/k3s.yaml", is -> IOUtils.toString(is, StandardCharsets.UTF_8) ); String serverUrl = "https://" + this.getHost() + ":" + this.getMappedPort(KUBE_SECURE_PORT); @@ -100,7 +96,6 @@ private String kubeConfigWithServerUrl(String kubeConfigYaml, String serverUrl) kubeConfigObjectNode.set("current-context", new TextNode("default")); - return objectMapper.writerWithDefaultPrettyPrinter() - .writeValueAsString(kubeConfigObjectNode); + return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(kubeConfigObjectNode); } } diff --git a/modules/k3s/src/test/java/org/testcontainers/k3s/Fabric8K3sContainerTest.java b/modules/k3s/src/test/java/org/testcontainers/k3s/Fabric8K3sContainerTest.java index 8b31c299634..6f9550eab2a 100644 --- a/modules/k3s/src/test/java/org/testcontainers/k3s/Fabric8K3sContainerTest.java +++ b/modules/k3s/src/test/java/org/testcontainers/k3s/Fabric8K3sContainerTest.java @@ -10,19 +10,17 @@ import io.fabric8.kubernetes.api.model.ProbeBuilder; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.DefaultKubernetesClient; -import io.fabric8.kubernetes.client.dsl.PodResource; import io.fabric8.kubernetes.client.dsl.Readiable; import lombok.extern.slf4j.Slf4j; -import org.assertj.core.api.Assertions; -import org.assertj.core.api.Condition; import org.junit.Test; import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.utility.DockerImageName; import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; +import static org.assertj.core.api.Assertions.assertThat; + @Slf4j public class Fabric8K3sContainerTest { @@ -49,14 +47,14 @@ public void shouldStartAndHaveListableNode() { List nodes = client.nodes().list().getItems(); // } - Assertions.assertThat(nodes).hasSize(1); + assertThat(nodes).hasSize(1); // verify that we can start a pod Pod helloworld = dummyStartablePod(); client.pods().create(helloworld); client.pods().inNamespace("default").withName("helloworld").waitUntilReady(30, TimeUnit.SECONDS); - Assertions.assertThat(client.pods().inNamespace("default").withName("helloworld")) + assertThat(client.pods().inNamespace("default").withName("helloworld")) .extracting(Readiable::isReady) .isEqualTo(true); } diff --git a/modules/kafka/src/main/java/org/testcontainers/containers/KafkaContainer.java b/modules/kafka/src/main/java/org/testcontainers/containers/KafkaContainer.java index 8b1128efef0..02342351b83 100644 --- a/modules/kafka/src/main/java/org/testcontainers/containers/KafkaContainer.java +++ b/modules/kafka/src/main/java/org/testcontainers/containers/KafkaContainer.java @@ -11,6 +11,7 @@ public class KafkaContainer extends GenericContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("confluentinc/cp-kafka"); + private static final String DEFAULT_TAG = "5.4.3"; public static final int KAFKA_PORT = 9093; @@ -39,7 +40,6 @@ public KafkaContainer(String confluentPlatformVersion) { public KafkaContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(KAFKA_PORT); @@ -77,12 +77,7 @@ public String getBootstrapServers() { protected void configure() { withEnv( "KAFKA_ADVERTISED_LISTENERS", - String.format( - "BROKER://%s:9092", - getNetwork() != null - ? getNetworkAliases().get(0) - : "localhost" - ) + String.format("BROKER://%s:9092", getNetwork() != null ? getNetworkAliases().get(0) : "localhost") ); String command = "#!/bin/bash\n"; @@ -111,9 +106,12 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) { ExecResult result = execInContainer( "kafka-configs", "--alter", - "--bootstrap-server", brokerAdvertisedListener, - "--entity-type", "brokers", - "--entity-name", getEnvMap().get("KAFKA_BROKER_ID"), + "--bootstrap-server", + brokerAdvertisedListener, + "--entity-type", + "brokers", + "--entity-name", + getEnvMap().get("KAFKA_BROKER_ID"), "--add-config", "advertised.listeners=[" + String.join(",", getBootstrapServers(), brokerAdvertisedListener) + "]" ); diff --git a/modules/kafka/src/test/java/org/testcontainers/containers/KafkaContainerTest.java b/modules/kafka/src/test/java/org/testcontainers/containers/KafkaContainerTest.java index f0ef0db2067..380df00e9e9 100644 --- a/modules/kafka/src/test/java/org/testcontainers/containers/KafkaContainerTest.java +++ b/modules/kafka/src/test/java/org/testcontainers/containers/KafkaContainerTest.java @@ -20,17 +20,20 @@ import java.time.Duration; import java.util.Collection; +import java.util.Collections; import java.util.UUID; import java.util.concurrent.TimeUnit; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; public class KafkaContainerTest { private static final DockerImageName KAFKA_TEST_IMAGE = DockerImageName.parse("confluentinc/cp-kafka:6.2.1"); - private static final DockerImageName ZOOKEEPER_TEST_IMAGE = DockerImageName.parse("confluentinc/cp-zookeeper:4.0.0"); + + private static final DockerImageName ZOOKEEPER_TEST_IMAGE = DockerImageName.parse( + "confluentinc/cp-zookeeper:4.0.0" + ); @Test public void testUsage() throws Exception { @@ -40,7 +43,6 @@ public void testUsage() throws Exception { } } - @Test public void testUsageWithSpecificImage() throws Exception { try ( @@ -50,18 +52,16 @@ public void testUsageWithSpecificImage() throws Exception { ) { kafka.start(); testKafkaFunctionality( - // getBootstrapServers { - kafka.getBootstrapServers() - // } + // getBootstrapServers { + kafka.getBootstrapServers() + // } ); } } @Test public void testUsageWithVersion() throws Exception { - try ( - KafkaContainer kafka = new KafkaContainer("6.2.1") - ) { + try (KafkaContainer kafka = new KafkaContainer("6.2.1")) { kafka.start(); testKafkaFunctionality(kafka.getBootstrapServers()); } @@ -71,7 +71,6 @@ public void testUsageWithVersion() throws Exception { public void testExternalZookeeperWithExternalNetwork() throws Exception { try ( Network network = Network.newNetwork(); - // withExternalZookeeper { KafkaContainer kafka = new KafkaContainer(KAFKA_TEST_IMAGE) .withNetwork(network) @@ -82,11 +81,10 @@ public void testExternalZookeeperWithExternalNetwork() throws Exception { .withNetwork(network) .withNetworkAliases("zookeeper") .withEnv("ZOOKEEPER_CLIENT_PORT", "2181"); - // withKafkaNetwork { GenericContainer application = new GenericContainer<>(DockerImageName.parse("alpine")) .withNetwork(network) - // } + // } .withNetworkAliases("dummy") .withCommand("sleep 10000") ) { @@ -100,9 +98,7 @@ public void testExternalZookeeperWithExternalNetwork() throws Exception { @Test public void testConfluentPlatformVersion5() throws Exception { - try ( - KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:5.4.3")) - ) { + try (KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:5.4.3"))) { kafka.start(); testKafkaFunctionality(kafka.getBootstrapServers()); } @@ -132,24 +128,27 @@ protected void testKafkaFunctionality(String bootstrapServers) throws Exception protected void testKafkaFunctionality(String bootstrapServers, int partitions, int rf) throws Exception { try ( - AdminClient adminClient = AdminClient.create(ImmutableMap.of( - AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers - )); - + AdminClient adminClient = AdminClient.create( + ImmutableMap.of(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers) + ); KafkaProducer producer = new KafkaProducer<>( ImmutableMap.of( - ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers, - ProducerConfig.CLIENT_ID_CONFIG, UUID.randomUUID().toString() + ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, + bootstrapServers, + ProducerConfig.CLIENT_ID_CONFIG, + UUID.randomUUID().toString() ), new StringSerializer(), new StringSerializer() ); - KafkaConsumer consumer = new KafkaConsumer<>( ImmutableMap.of( - ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers, - ConsumerConfig.GROUP_ID_CONFIG, "tc-" + UUID.randomUUID(), - ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest" + ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, + bootstrapServers, + ConsumerConfig.GROUP_ID_CONFIG, + "tc-" + UUID.randomUUID(), + ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, + "earliest" ), new StringDeserializer(), new StringDeserializer() @@ -157,30 +156,33 @@ protected void testKafkaFunctionality(String bootstrapServers, int partitions, i ) { String topicName = "messages-" + UUID.randomUUID(); - Collection topics = singletonList(new NewTopic(topicName, partitions, (short) rf)); + Collection topics = Collections.singletonList(new NewTopic(topicName, partitions, (short) rf)); adminClient.createTopics(topics).all().get(30, TimeUnit.SECONDS); - consumer.subscribe(singletonList(topicName)); + consumer.subscribe(Collections.singletonList(topicName)); producer.send(new ProducerRecord<>(topicName, "testcontainers", "rulezzz")).get(); - Unreliables.retryUntilTrue(10, TimeUnit.SECONDS, () -> { - ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); + Unreliables.retryUntilTrue( + 10, + TimeUnit.SECONDS, + () -> { + ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); - if (records.isEmpty()) { - return false; - } + if (records.isEmpty()) { + return false; + } - assertThat(records) - .hasSize(1) - .extracting(ConsumerRecord::topic, ConsumerRecord::key, ConsumerRecord::value) - .containsExactly(tuple(topicName, "testcontainers", "rulezzz")); + assertThat(records) + .hasSize(1) + .extracting(ConsumerRecord::topic, ConsumerRecord::key, ConsumerRecord::value) + .containsExactly(tuple(topicName, "testcontainers", "rulezzz")); - return true; - }); + return true; + } + ); consumer.unsubscribe(); } } - } diff --git a/modules/localstack/src/main/java/org/testcontainers/containers/localstack/LocalStackContainer.java b/modules/localstack/src/main/java/org/testcontainers/containers/localstack/LocalStackContainer.java index dd03a4206e0..8bd6f14d3fd 100644 --- a/modules/localstack/src/main/java/org/testcontainers/containers/localstack/LocalStackContainer.java +++ b/modules/localstack/src/main/java/org/testcontainers/containers/localstack/LocalStackContainer.java @@ -36,10 +36,13 @@ public class LocalStackContainer extends GenericContainer { static final int PORT = 4566; + private static final String HOSTNAME_EXTERNAL_ENV_VAR = "HOSTNAME_EXTERNAL"; + private final List services = new ArrayList<>(); private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("localstack/localstack"); + private static final String DEFAULT_TAG = "0.11.2"; @Deprecated @@ -88,7 +91,6 @@ public LocalStackContainer(final DockerImageName dockerImageName) { */ public LocalStackContainer(final DockerImageName dockerImageName, boolean useLegacyMode) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); this.legacyMode = useLegacyMode; @@ -109,7 +111,9 @@ private static boolean shouldRunInLegacyMode(String version) { } log.warn("Version {} is not a semantic version, LocalStack will run in legacy mode.", version); - log.warn("Consider using \"LocalStackContainer(DockerImageName dockerImageName, boolean legacyMode)\" constructor if you want to disable legacy mode."); + log.warn( + "Consider using \"LocalStackContainer(DockerImageName dockerImageName, boolean legacyMode)\" constructor if you want to disable legacy mode." + ); return true; } @@ -126,22 +130,25 @@ protected void configure() { // do nothing hostnameExternalReason = "explicitly as environment variable"; } else if (getNetwork() != null && getNetworkAliases() != null && getNetworkAliases().size() >= 1) { - withEnv(HOSTNAME_EXTERNAL_ENV_VAR, getNetworkAliases().get(getNetworkAliases().size() - 1)); // use the last network alias set + withEnv(HOSTNAME_EXTERNAL_ENV_VAR, getNetworkAliases().get(getNetworkAliases().size() - 1)); // use the last network alias set hostnameExternalReason = "to match last network alias on container with non-default network"; } else { withEnv(HOSTNAME_EXTERNAL_ENV_VAR, getHost()); hostnameExternalReason = "to match host-routable address for container"; } - logger().info("{} environment variable set to {} ({})", HOSTNAME_EXTERNAL_ENV_VAR, getEnvMap().get(HOSTNAME_EXTERNAL_ENV_VAR), hostnameExternalReason); + logger() + .info( + "{} environment variable set to {} ({})", + HOSTNAME_EXTERNAL_ENV_VAR, + getEnvMap().get(HOSTNAME_EXTERNAL_ENV_VAR), + hostnameExternalReason + ); exposePorts(); } private void exposePorts() { - services.stream() - .map(this::getServicePort) - .distinct() - .forEach(this::addExposedPort); + services.stream().map(this::getServicePort).distinct().forEach(this::addExposedPort); } public LocalStackContainer withServices(Service... services) { @@ -218,10 +225,7 @@ public URI getEndpointOverride(EnabledService service) { String ipAddress = address; // resolve IP address and use that as the endpoint so that path-style access is automatically used for S3 ipAddress = InetAddress.getByName(address).getHostAddress(); - return new URI("http://" + - ipAddress + - ":" + - getMappedPort(getServicePort(service))); + return new URI("http://" + ipAddress + ":" + getMappedPort(getServicePort(service))); } catch (UnknownHostException | URISyntaxException e) { throw new IllegalStateException("Cannot obtain endpoint URL", e); } @@ -332,7 +336,7 @@ public enum Service implements EnabledService { DYNAMODB("dynamodb", 4569), DYNAMODB_STREAMS("dynamodbstreams", 4570), // TODO: Clarify usage for ELASTICSEARCH and ELASTICSEARCH_SERVICE -// ELASTICSEARCH("es", 4571), + // ELASTICSEARCH("es", 4571), S3("s3", 4572), FIREHOSE("firehose", 4573), LAMBDA("lambda", 4574), diff --git a/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LegacyModeTest.java b/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LegacyModeTest.java index b34f43f79ed..a757c11e928 100644 --- a/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LegacyModeTest.java +++ b/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LegacyModeTest.java @@ -16,48 +16,51 @@ import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertNotEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.S3; -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SQS; -import static org.testcontainers.containers.localstack.LocalstackTestImages.LOCALSTACK_0_10_IMAGE; -import static org.testcontainers.containers.localstack.LocalstackTestImages.LOCALSTACK_0_11_IMAGE; -import static org.testcontainers.containers.localstack.LocalstackTestImages.LOCALSTACK_0_12_IMAGE; -import static org.testcontainers.containers.localstack.LocalstackTestImages.LOCALSTACK_0_7_IMAGE; -import static org.testcontainers.containers.localstack.LocalstackTestImages.LOCALSTACK_IMAGE; @RunWith(Enclosed.class) public class LegacyModeTest { - private static DockerImageName LOCALSTACK_CUSTOM_TAG = LOCALSTACK_IMAGE.withTag("custom"); + + private static DockerImageName LOCALSTACK_CUSTOM_TAG = LocalstackTestImages.LOCALSTACK_IMAGE.withTag("custom"); @RunWith(Parameterized.class) @AllArgsConstructor public static class Off { + private final String description; + private final LocalStackContainer localstack; @Parameterized.Parameters(name = "{0}") public static Iterable constructors() { - return Arrays.asList(new Object[][]{ - {"0.12", new LocalStackContainer(LOCALSTACK_0_12_IMAGE)}, - {"0.11", new LocalStackContainer(LOCALSTACK_0_11_IMAGE)}, - {"0.7 with legacy = off", new LocalStackContainer(LOCALSTACK_0_7_IMAGE, false)} - }); + return Arrays.asList( + new Object[][] { + { "0.12", new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_12_IMAGE) }, + { "0.11", new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_11_IMAGE) }, + { + "0.7 with legacy = off", + new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_7_IMAGE, false), + }, + } + ); } @Test public void samePortIsExposedForAllServices() { - localstack.withServices(S3, SQS); + localstack.withServices(LocalStackContainer.Service.S3, LocalStackContainer.Service.SQS); localstack.start(); try { assertTrue("A single port is exposed", localstack.getExposedPorts().size() == 1); assertEquals( "Endpoint overrides are different", - localstack.getEndpointOverride(S3).toString(), - localstack.getEndpointOverride(SQS).toString()); + localstack.getEndpointOverride(LocalStackContainer.Service.S3).toString(), + localstack.getEndpointOverride(LocalStackContainer.Service.SQS).toString() + ); assertEquals( "Endpoint configuration have different endpoints", - localstack.getEndpointConfiguration(S3).getServiceEndpoint(), - localstack.getEndpointConfiguration(SQS).getServiceEndpoint()); + localstack.getEndpointConfiguration(LocalStackContainer.Service.S3).getServiceEndpoint(), + localstack.getEndpointConfiguration(LocalStackContainer.Service.SQS).getServiceEndpoint() + ); } finally { localstack.stop(); } @@ -67,7 +70,9 @@ public void samePortIsExposedForAllServices() { @RunWith(Parameterized.class) @AllArgsConstructor public static class On { + private final String description; + private final LocalStackContainer localstack; @BeforeClass @@ -75,7 +80,7 @@ public static void createCustomTag() { DockerClient dockerClient = DockerClientFactory.instance().client(); dockerClient .tagImageCmd( - new RemoteDockerImage(LOCALSTACK_0_12_IMAGE).get(), + new RemoteDockerImage(LocalstackTestImages.LOCALSTACK_0_12_IMAGE).get(), LOCALSTACK_CUSTOM_TAG.getRepository(), LOCALSTACK_CUSTOM_TAG.getVersionPart() ) @@ -84,28 +89,35 @@ public static void createCustomTag() { @Parameterized.Parameters(name = "{0}") public static Iterable constructors() { - return Arrays.asList(new Object[][]{ - {"0.10", new LocalStackContainer(LOCALSTACK_0_10_IMAGE)}, - {"custom", new LocalStackContainer(LOCALSTACK_CUSTOM_TAG)}, - {"0.11 with legacy = on", new LocalStackContainer(LOCALSTACK_0_11_IMAGE, true)} - }); + return Arrays.asList( + new Object[][] { + { "0.10", new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_10_IMAGE) }, + { "custom", new LocalStackContainer(LOCALSTACK_CUSTOM_TAG) }, + { + "0.11 with legacy = on", + new LocalStackContainer(LocalstackTestImages.LOCALSTACK_0_11_IMAGE, true), + }, + } + ); } @Test public void differentPortsAreExposed() { - localstack.withServices(S3, SQS); + localstack.withServices(LocalStackContainer.Service.S3, LocalStackContainer.Service.SQS); localstack.start(); try { assertTrue("Multiple ports are exposed", localstack.getExposedPorts().size() > 1); assertNotEquals( "Endpoint overrides are different", - localstack.getEndpointOverride(S3).toString(), - localstack.getEndpointOverride(SQS).toString()); + localstack.getEndpointOverride(LocalStackContainer.Service.S3).toString(), + localstack.getEndpointOverride(LocalStackContainer.Service.SQS).toString() + ); assertNotEquals( "Endpoint configuration have different endpoints", - localstack.getEndpointConfiguration(S3).getServiceEndpoint(), - localstack.getEndpointConfiguration(SQS).getServiceEndpoint()); + localstack.getEndpointConfiguration(LocalStackContainer.Service.S3).getServiceEndpoint(), + localstack.getEndpointConfiguration(LocalStackContainer.Service.SQS).getServiceEndpoint() + ); } finally { localstack.stop(); } diff --git a/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LocalstackContainerTest.java b/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LocalstackContainerTest.java index 6b32ba2c102..cf4e1a813a4 100644 --- a/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LocalstackContainerTest.java +++ b/modules/localstack/src/test/java/org/testcontainers/containers/localstack/LocalstackContainerTest.java @@ -1,17 +1,5 @@ package org.testcontainers.containers.localstack; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; -import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.containers.localstack.LocalStackContainer.PORT; -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.CLOUDWATCHLOGS; -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.KMS; -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.S3; -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SQS; -import static org.testcontainers.containers.localstack.LocalstackTestImages.LOCALSTACK_IMAGE; - import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.services.kms.model.CreateKeyRequest; @@ -29,10 +17,6 @@ import com.amazonaws.services.sqs.AmazonSQS; import com.amazonaws.services.sqs.AmazonSQSClientBuilder; import com.amazonaws.services.sqs.model.CreateQueueResult; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.junit.Assert; @@ -44,12 +28,22 @@ import org.testcontainers.containers.Container; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.utility.DockerImageName; +import org.testcontainers.containers.localstack.LocalStackContainer.Service; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.Matchers.containsString; +import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; +import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; +import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; + /** * Tests for Localstack Container, used both in bridge network (exposed to host) and docker network modes. *

@@ -65,15 +59,22 @@ public static class WithoutNetwork { // without_network { @ClassRule - public static LocalStackContainer localstack = new LocalStackContainer(LOCALSTACK_IMAGE) - .withServices(S3, SQS, CLOUDWATCHLOGS, KMS, LocalStackContainer.EnabledService.named("events")); + public static LocalStackContainer localstack = new LocalStackContainer(LocalstackTestImages.LOCALSTACK_IMAGE) + .withServices( + Service.S3, + Service.SQS, + Service.CLOUDWATCHLOGS, + Service.KMS, + LocalStackContainer.EnabledService.named("events") + ); + // } @Test public void s3TestOverBridgeNetwork() throws IOException { AmazonS3 s3 = AmazonS3ClientBuilder .standard() - .withEndpointConfiguration(localstack.getEndpointConfiguration(S3)) + .withEndpointConfiguration(localstack.getEndpointConfiguration(Service.S3)) .withCredentials(localstack.getDefaultCredentialsProvider()) .build(); @@ -82,7 +83,10 @@ public void s3TestOverBridgeNetwork() throws IOException { s3.putObject(bucketName, "bar", "baz"); final List buckets = s3.listBuckets(); - final Optional maybeBucket = buckets.stream().filter(b -> b.getName().equals(bucketName)).findFirst(); + final Optional maybeBucket = buckets + .stream() + .filter(b -> b.getName().equals(bucketName)) + .findFirst(); assertTrue("The created bucket is present", maybeBucket.isPresent()); final Bucket bucket = maybeBucket.get(); @@ -100,32 +104,49 @@ public void s3TestOverBridgeNetwork() throws IOException { public void s3TestUsingAwsSdkV2() { S3Client s3 = S3Client .builder() - .endpointOverride(localstack.getEndpointOverride(LocalStackContainer.Service.S3)) - .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create( - localstack.getAccessKey(), localstack.getSecretKey() - ))) + .endpointOverride(localstack.getEndpointOverride(Service.S3)) + .credentialsProvider( + StaticCredentialsProvider.create( + AwsBasicCredentials.create(localstack.getAccessKey(), localstack.getSecretKey()) + ) + ) .region(Region.of(localstack.getRegion())) .build(); final String bucketName = "foov2"; s3.createBucket(b -> b.bucket(bucketName)); - assertTrue("New bucket was created", s3.listBuckets().buckets().stream().anyMatch(b -> b.name().equals(bucketName))); + assertTrue( + "New bucket was created", + s3.listBuckets().buckets().stream().anyMatch(b -> b.name().equals(bucketName)) + ); } @Test public void sqsTestOverBridgeNetwork() { - AmazonSQS sqs = AmazonSQSClientBuilder.standard() - .withEndpointConfiguration(localstack.getEndpointConfiguration(SQS)) + AmazonSQS sqs = AmazonSQSClientBuilder + .standard() + .withEndpointConfiguration(localstack.getEndpointConfiguration(Service.SQS)) .withCredentials(localstack.getDefaultCredentialsProvider()) .build(); CreateQueueResult queueResult = sqs.createQueue("baz"); String fooQueueUrl = queueResult.getQueueUrl(); - assertThat("Created queue has external hostname URL", fooQueueUrl, - containsString("http://" + DockerClientFactory.instance().dockerHostIpAddress() + ":" + localstack.getMappedPort(PORT))); + assertThat( + "Created queue has external hostname URL", + fooQueueUrl, + containsString( + "http://" + + DockerClientFactory.instance().dockerHostIpAddress() + + ":" + + localstack.getMappedPort(LocalStackContainer.PORT) + ) + ); sqs.sendMessage(fooQueueUrl, "test"); - final long messageCount = sqs.receiveMessage(fooQueueUrl).getMessages().stream() + final long messageCount = sqs + .receiveMessage(fooQueueUrl) + .getMessages() + .stream() .filter(message -> message.getBody().equals("test")) .count(); assertEquals("the sent message can be received", 1L, messageCount); @@ -133,9 +154,11 @@ public void sqsTestOverBridgeNetwork() { @Test public void cloudWatchLogsTestOverBridgeNetwork() { - AWSLogs logs = AWSLogsClientBuilder.standard() - .withEndpointConfiguration(localstack.getEndpointConfiguration(CLOUDWATCHLOGS)) - .withCredentials(localstack.getDefaultCredentialsProvider()).build(); + AWSLogs logs = AWSLogsClientBuilder + .standard() + .withEndpointConfiguration(localstack.getEndpointConfiguration(Service.CLOUDWATCHLOGS)) + .withCredentials(localstack.getDefaultCredentialsProvider()) + .build(); logs.createLogGroup(new CreateLogGroupRequest("foo")); @@ -146,8 +169,9 @@ public void cloudWatchLogsTestOverBridgeNetwork() { @Test public void kmsKeyCreationTest() { - AWSKMS awskms = AWSKMSClientBuilder.standard() - .withEndpointConfiguration(localstack.getEndpointConfiguration(KMS)) + AWSKMS awskms = AWSKMSClientBuilder + .standard() + .withEndpointConfiguration(localstack.getEndpointConfiguration(Service.KMS)) .withCredentials(localstack.getDefaultCredentialsProvider()) .build(); @@ -156,7 +180,11 @@ public void kmsKeyCreationTest() { CreateKeyRequest req = new CreateKeyRequest().withDescription(desc).withTags(createdByTag); CreateKeyResult key = awskms.createKey(req); - assertEquals("AWS KMS Customer Managed Key should be created ", key.getKeyMetadata().getDescription(), desc); + assertEquals( + "AWS KMS Customer Managed Key should be created ", + key.getKeyMetadata().getDescription(), + desc + ); } @Test @@ -164,35 +192,42 @@ public void samePortIsExposedForAllServices() { assertTrue("A single port is exposed", localstack.getExposedPorts().size() == 1); assertEquals( "Endpoint overrides are different", - localstack.getEndpointOverride(S3).toString(), - localstack.getEndpointOverride(SQS).toString()); + localstack.getEndpointOverride(Service.S3).toString(), + localstack.getEndpointOverride(Service.SQS).toString() + ); assertEquals( "Endpoint configuration have different endpoints", - localstack.getEndpointConfiguration(S3).getServiceEndpoint(), - localstack.getEndpointConfiguration(SQS).getServiceEndpoint()); + localstack.getEndpointConfiguration(Service.S3).getServiceEndpoint(), + localstack.getEndpointConfiguration(Service.SQS).getServiceEndpoint() + ); } } public static class WithNetwork { + // with_network { private static Network network = Network.newNetwork(); @ClassRule - public static LocalStackContainer localstackInDockerNetwork = new LocalStackContainer(LOCALSTACK_IMAGE) + public static LocalStackContainer localstackInDockerNetwork = new LocalStackContainer( + LocalstackTestImages.LOCALSTACK_IMAGE + ) .withNetwork(network) - .withNetworkAliases("notthis", "localstack") // the last alias is used for HOSTNAME_EXTERNAL - .withServices(S3, SQS, CLOUDWATCHLOGS); + .withNetworkAliases("notthis", "localstack") // the last alias is used for HOSTNAME_EXTERNAL + .withServices(Service.S3, Service.SQS, Service.CLOUDWATCHLOGS); + // } @ClassRule - public static GenericContainer awsCliInDockerNetwork = new GenericContainer<>(LocalstackTestImages.AWS_CLI_IMAGE) + public static GenericContainer awsCliInDockerNetwork = new GenericContainer<>( + LocalstackTestImages.AWS_CLI_IMAGE + ) .withNetwork(network) .withCreateContainerCmdModifier(cmd -> cmd.withEntrypoint("top")) .withEnv("AWS_ACCESS_KEY_ID", "accesskey") .withEnv("AWS_SECRET_ACCESS_KEY", "secretkey") .withEnv("AWS_REGION", "eu-west-1"); - @Test public void s3TestOverDockerNetwork() throws Exception { runAwsCliAgainstDockerNetworkContainer("s3api create-bucket --bucket foo"); @@ -202,15 +237,30 @@ public void s3TestOverDockerNetwork() throws Exception { @Test public void sqsTestOverDockerNetwork() throws Exception { - final String queueCreationResponse = runAwsCliAgainstDockerNetworkContainer("sqs create-queue --queue-name baz"); + final String queueCreationResponse = runAwsCliAgainstDockerNetworkContainer( + "sqs create-queue --queue-name baz" + ); - assertThat("Created queue has external hostname URL", queueCreationResponse, - containsString("http://localstack:" + PORT)); + assertThat( + "Created queue has external hostname URL", + queueCreationResponse, + containsString("http://localstack:" + LocalStackContainer.PORT) + ); runAwsCliAgainstDockerNetworkContainer( - String.format("sqs send-message --endpoint http://localstack:%d --queue-url http://localstack:%d/queue/baz --message-body test", PORT, PORT)); + String.format( + "sqs send-message --endpoint http://localstack:%d --queue-url http://localstack:%d/queue/baz --message-body test", + LocalStackContainer.PORT, + LocalStackContainer.PORT + ) + ); final String message = runAwsCliAgainstDockerNetworkContainer( - String.format("sqs receive-message --endpoint http://localstack:%d --queue-url http://localstack:%d/queue/baz", PORT, PORT)); + String.format( + "sqs receive-message --endpoint http://localstack:%d --queue-url http://localstack:%d/queue/baz", + LocalStackContainer.PORT, + LocalStackContainer.PORT + ) + ); assertTrue("the sent message can be received", message.contains("\"Body\": \"test\"")); } @@ -221,7 +271,13 @@ public void cloudWatchLogsTestOverDockerNetwork() throws Exception { } private String runAwsCliAgainstDockerNetworkContainer(String command) throws Exception { - final String[] commandParts = String.format("/usr/bin/aws --region eu-west-1 %s --endpoint-url http://localstack:%d --no-verify-ssl", command, PORT).split(" "); + final String[] commandParts = String + .format( + "/usr/bin/aws --region eu-west-1 %s --endpoint-url http://localstack:%d --no-verify-ssl", + command, + LocalStackContainer.PORT + ) + .split(" "); final Container.ExecResult execResult = awsCliInDockerNetwork.execInContainer(commandParts); Assert.assertEquals(0, execResult.getExitCode()); diff --git a/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainer.java b/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainer.java index 2e28e5d0480..b0944a6d3c0 100644 --- a/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainer.java +++ b/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainer.java @@ -27,10 +27,15 @@ public class MariaDBContainer> extends JdbcD static final String DEFAULT_PASSWORD = "test"; static final Integer MARIADB_PORT = 3306; + private String databaseName = "test"; + private String username = DEFAULT_USER; + private String password = DEFAULT_PASSWORD; + private static final String MARIADB_ROOT_USER = "root"; + private static final String MY_CNF_CONFIG_OVERRIDE_PARAM_NAME = "TC_MY_CNF"; /** @@ -47,7 +52,6 @@ public MariaDBContainer(String dockerImageName) { public MariaDBContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); addExposedPort(MARIADB_PORT); @@ -60,7 +64,11 @@ public Set getLivenessCheckPortNumbers() { @Override protected void configure() { - optionallyMapResourceParameterAsVolume(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, "/etc/mysql/conf.d", "mariadb-default-conf"); + optionallyMapResourceParameterAsVolume( + MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, + "/etc/mysql/conf.d", + "mariadb-default-conf" + ); addEnv("MYSQL_DATABASE", databaseName); addEnv("MYSQL_USER", username); @@ -83,13 +91,14 @@ public String getDriverClassName() { @Override public String getJdbcUrl() { String additionalUrlParams = constructUrlParameters("?", "&"); - return "jdbc:mariadb://" + getHost() + ":" + getMappedPort(MARIADB_PORT) + - "/" + databaseName + additionalUrlParams; + return ( + "jdbc:mariadb://" + getHost() + ":" + getMappedPort(MARIADB_PORT) + "/" + databaseName + additionalUrlParams + ); } @Override public String getDatabaseName() { - return databaseName; + return databaseName; } @Override diff --git a/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainerProvider.java b/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainerProvider.java index 4330465a9c3..6697255ca79 100644 --- a/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainerProvider.java +++ b/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBContainerProvider.java @@ -29,7 +29,6 @@ public JdbcDatabaseContainer newInstance(String tag) { @Override public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) { - return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); + return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); } - } diff --git a/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainer.java b/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainer.java index e37e9b0b6bf..99041e83e28 100644 --- a/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainer.java +++ b/modules/mariadb/src/main/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainer.java @@ -13,7 +13,8 @@ public class MariaDBR2DBCDatabaseContainer implements R2DBCDatabaseContainer { private final MariaDBContainer container; public static ConnectionFactoryOptions getOptions(MariaDBContainer container) { - ConnectionFactoryOptions options = ConnectionFactoryOptions.builder() + ConnectionFactoryOptions options = ConnectionFactoryOptions + .builder() .option(ConnectionFactoryOptions.DRIVER, MariaDBR2DBCDatabaseContainerProvider.DRIVER) .build(); @@ -22,7 +23,8 @@ public static ConnectionFactoryOptions getOptions(MariaDBContainer container) @Override public ConnectionFactoryOptions configure(ConnectionFactoryOptions options) { - return options.mutate() + return options + .mutate() .option(ConnectionFactoryOptions.HOST, container.getHost()) .option(ConnectionFactoryOptions.PORT, container.getMappedPort(MariaDBContainer.MARIADB_PORT)) .option(ConnectionFactoryOptions.DATABASE, container.getDatabaseName()) diff --git a/modules/mariadb/src/test/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainerTest.java b/modules/mariadb/src/test/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainerTest.java index b6fb4dd659e..f2339b0e5f9 100644 --- a/modules/mariadb/src/test/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainerTest.java +++ b/modules/mariadb/src/test/java/org/testcontainers/containers/MariaDBR2DBCDatabaseContainerTest.java @@ -20,5 +20,4 @@ protected String createR2DBCUrl() { protected MariaDBContainer createContainer() { return new MariaDBContainer<>(DockerImageName.parse("mariadb:10.3.6")); } - } diff --git a/modules/mariadb/src/test/java/org/testcontainers/jdbc/mariadb/MariaDBJDBCDriverTest.java b/modules/mariadb/src/test/java/org/testcontainers/jdbc/mariadb/MariaDBJDBCDriverTest.java index ef1dfef2703..ffb26f19734 100644 --- a/modules/mariadb/src/test/java/org/testcontainers/jdbc/mariadb/MariaDBJDBCDriverTest.java +++ b/modules/mariadb/src/test/java/org/testcontainers/jdbc/mariadb/MariaDBJDBCDriverTest.java @@ -4,26 +4,47 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class MariaDBJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:mariadb://hostname/databasename", EnumSet.noneOf(Options.class)}, - {"jdbc:tc:mariadb://hostname/databasename?user=someuser&TC_INITSCRIPT=somepath/init_mariadb.sql", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mariadb:10.2.14://hostname/databasename", EnumSet.noneOf(Options.class)}, - {"jdbc:tc:mariadb:10.2.14://hostname/databasename?TC_INITSCRIPT=somepath/init_unicode_mariadb.sql&useUnicode=yes&characterEncoding=utf8", EnumSet.of(Options.CharacterSet)}, - {"jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&TC_INITSCRIPT=somepath/init_mariadb.sql", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&password=somepwd&TC_INITSCRIPT=somepath/init_mariadb.sql", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&password=somepwd&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mariadb:10.2.14://hostname/databasename?TC_MY_CNF=somepath/mariadb_conf_override", EnumSet.of(Options.CustomIniFile)}, - }); + return Arrays.asList( + new Object[][] { + { "jdbc:tc:mariadb://hostname/databasename", EnumSet.noneOf(Options.class) }, + { + "jdbc:tc:mariadb://hostname/databasename?user=someuser&TC_INITSCRIPT=somepath/init_mariadb.sql", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { "jdbc:tc:mariadb:10.2.14://hostname/databasename", EnumSet.noneOf(Options.class) }, + { + "jdbc:tc:mariadb:10.2.14://hostname/databasename?TC_INITSCRIPT=somepath/init_unicode_mariadb.sql&useUnicode=yes&characterEncoding=utf8", + EnumSet.of(Options.CharacterSet), + }, + { + "jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&TC_INITSCRIPT=somepath/init_mariadb.sql", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&password=somepwd&TC_INITSCRIPT=somepath/init_mariadb.sql", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mariadb:10.2.14://hostname/databasename?user=someuser&password=somepwd&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mariadb:10.2.14://hostname/databasename?TC_MY_CNF=somepath/mariadb_conf_override", + EnumSet.of(Options.CustomIniFile), + }, + } + ); } } diff --git a/modules/mariadb/src/test/java/org/testcontainers/junit/mariadb/SimpleMariaDBTest.java b/modules/mariadb/src/test/java/org/testcontainers/junit/mariadb/SimpleMariaDBTest.java index 2dcdbafd9e3..21a48b6e73c 100644 --- a/modules/mariadb/src/test/java/org/testcontainers/junit/mariadb/SimpleMariaDBTest.java +++ b/modules/mariadb/src/test/java/org/testcontainers/junit/mariadb/SimpleMariaDBTest.java @@ -2,26 +2,24 @@ import org.apache.commons.lang3.SystemUtils; import org.junit.Test; +import org.testcontainers.MariaDBTestImages; import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; import java.sql.ResultSet; import java.sql.SQLException; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; import static org.junit.Assume.assumeFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; -import static org.testcontainers.MariaDBTestImages.MARIADB_IMAGE; - public class SimpleMariaDBTest extends AbstractContainerDatabaseTest { @Test public void testSimple() throws SQLException { - try (MariaDBContainer mariadb = new MariaDBContainer<>(MARIADB_IMAGE)) { - + try (MariaDBContainer mariadb = new MariaDBContainer<>(MariaDBTestImages.MARIADB_IMAGE)) { mariadb.start(); ResultSet resultSet = performQuery(mariadb, "SELECT 1"); @@ -33,14 +31,20 @@ public void testSimple() throws SQLException { @Test public void testSpecificVersion() throws SQLException { - try (MariaDBContainer mariadbOldVersion = new MariaDBContainer<>(MARIADB_IMAGE.withTag("5.5.51"))) { - + try ( + MariaDBContainer mariadbOldVersion = new MariaDBContainer<>( + MariaDBTestImages.MARIADB_IMAGE.withTag("5.5.51") + ) + ) { mariadbOldVersion.start(); ResultSet resultSet = performQuery(mariadbOldVersion, "SELECT VERSION()"); String resultSetString = resultSet.getString(1); - assertTrue("The database version can be set using a container rule parameter", resultSetString.startsWith("5.5.51")); + assertTrue( + "The database version can be set using a container rule parameter", + resultSetString.startsWith("5.5.51") + ); } } @@ -48,8 +52,12 @@ public void testSpecificVersion() throws SQLException { public void testMariaDBWithCustomIniFile() throws SQLException { assumeFalse(SystemUtils.IS_OS_WINDOWS); - try (MariaDBContainer mariadbCustomConfig = new MariaDBContainer<>(MARIADB_IMAGE.withTag("10.1.16")) - .withConfigurationOverride("somepath/mariadb_conf_override")) { + try ( + MariaDBContainer mariadbCustomConfig = new MariaDBContainer<>( + MariaDBTestImages.MARIADB_IMAGE.withTag("10.1.16") + ) + .withConfigurationOverride("somepath/mariadb_conf_override") + ) { mariadbCustomConfig.start(); ResultSet resultSet = performQuery(mariadbCustomConfig, "SELECT @@GLOBAL.innodb_file_format"); @@ -61,9 +69,10 @@ public void testMariaDBWithCustomIniFile() throws SQLException { @Test public void testMariaDBWithCommandOverride() throws SQLException { - - try (MariaDBContainer mariadbCustomConfig = new MariaDBContainer<>(MARIADB_IMAGE) - .withCommand("mysqld --auto_increment_increment=10")) { + try ( + MariaDBContainer mariadbCustomConfig = new MariaDBContainer<>(MariaDBTestImages.MARIADB_IMAGE) + .withCommand("mysqld --auto_increment_increment=10") + ) { mariadbCustomConfig.start(); ResultSet resultSet = performQuery(mariadbCustomConfig, "show variables like 'auto_increment_increment'"); String result = resultSet.getString("Value"); @@ -74,7 +83,7 @@ public void testMariaDBWithCommandOverride() throws SQLException { @Test public void testWithAdditionalUrlParamInJdbcUrl() { - MariaDBContainer mariaDBContainer = new MariaDBContainer<>(MARIADB_IMAGE) + MariaDBContainer mariaDBContainer = new MariaDBContainer<>(MariaDBTestImages.MARIADB_IMAGE) .withUrlParam("connectTimeout", "40000") .withUrlParam("rewriteBatchedStatements", "true"); diff --git a/modules/mockserver/src/main/java/org/testcontainers/containers/MockServerContainer.java b/modules/mockserver/src/main/java/org/testcontainers/containers/MockServerContainer.java index 6ab1c541325..8b39d5d3763 100644 --- a/modules/mockserver/src/main/java/org/testcontainers/containers/MockServerContainer.java +++ b/modules/mockserver/src/main/java/org/testcontainers/containers/MockServerContainer.java @@ -8,6 +8,7 @@ public class MockServerContainer extends GenericContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("jamesdbloom/mockserver"); + private static final String DEFAULT_TAG = "mockserver-5.5.4"; @Deprecated @@ -33,7 +34,6 @@ public MockServerContainer(String version) { public MockServerContainer(DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME, DockerImageName.parse("mockserver/mockserver")); waitingFor(Wait.forHttp("/mockserver/status").withMethod("PUT").forStatusCode(200)); diff --git a/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerRuleTest.java b/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerRuleTest.java index d0c290ad46a..3f34d000603 100644 --- a/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerRuleTest.java +++ b/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerRuleTest.java @@ -5,22 +5,26 @@ import org.mockserver.client.MockServerClient; import org.testcontainers.utility.DockerImageName; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; public class MockServerContainerRuleTest { - public static final DockerImageName MOCKSERVER_IMAGE = DockerImageName.parse("jamesdbloom/mockserver:mockserver-5.5.4"); + public static final DockerImageName MOCKSERVER_IMAGE = DockerImageName.parse( + "jamesdbloom/mockserver:mockserver-5.5.4" + ); // creatingProxy { @Rule public MockServerContainer mockServer = new MockServerContainer(MOCKSERVER_IMAGE); + // } @Test public void shouldReturnExpectation() throws Exception { + // spotless:off // testSimpleExpectation { new MockServerClient(mockServer.getHost(), mockServer.getServerPort()) .when(request() @@ -31,8 +35,10 @@ public void shouldReturnExpectation() throws Exception { // ...a GET request to '/person?name=peter' returns "Peter the person!" // } + // spotless:on - assertThat("Expectation returns expected response body", + assertThat( + "Expectation returns expected response body", SimpleHttpClient.responseFromMockserver(mockServer, "/person?name=peter"), containsString("Peter the person") ); diff --git a/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerTest.java b/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerTest.java index 61a5c33c630..d038b111824 100644 --- a/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerTest.java +++ b/modules/mockserver/src/test/java/org/testcontainers/containers/MockServerContainerTest.java @@ -4,7 +4,7 @@ import org.mockserver.client.MockServerClient; import org.testcontainers.utility.DockerImageName; -import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.Matchers.equalTo; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; import static org.rnorth.visibleassertions.VisibleAssertions.assertThat; @@ -12,12 +12,18 @@ public class MockServerContainerTest { - public static final DockerImageName MOCKSERVER_IMAGE = DockerImageName.parse("jamesdbloom/mockserver:mockserver-5.5.4"); + public static final DockerImageName MOCKSERVER_IMAGE = DockerImageName.parse( + "jamesdbloom/mockserver:mockserver-5.5.4" + ); @Test public void shouldCallActualMockserverVersion() throws Exception { String actualVersion = MockServerClient.class.getPackage().getImplementationVersion(); - try (MockServerContainer mockServer = new MockServerContainer(MOCKSERVER_IMAGE.withTag("mockserver-" + actualVersion))) { + try ( + MockServerContainer mockServer = new MockServerContainer( + MOCKSERVER_IMAGE.withTag("mockserver-" + actualVersion) + ) + ) { mockServer.start(); String expectedBody = "Hello World!"; @@ -26,11 +32,10 @@ public void shouldCallActualMockserverVersion() throws Exception { assertTrue("Mockserver running", client.isRunning()); - client - .when(request().withPath("/hello")) - .respond(response().withBody(expectedBody)); + client.when(request().withPath("/hello")).respond(response().withBody(expectedBody)); - assertThat("MockServer returns correct result", + assertThat( + "MockServer returns correct result", SimpleHttpClient.responseFromMockserver(mockServer, "/hello"), equalTo(expectedBody) ); diff --git a/modules/mockserver/src/test/java/org/testcontainers/containers/SimpleHttpClient.java b/modules/mockserver/src/test/java/org/testcontainers/containers/SimpleHttpClient.java index cd5cb25cabb..da60ca9396a 100644 --- a/modules/mockserver/src/test/java/org/testcontainers/containers/SimpleHttpClient.java +++ b/modules/mockserver/src/test/java/org/testcontainers/containers/SimpleHttpClient.java @@ -9,9 +9,11 @@ import java.net.URLConnection; public class SimpleHttpClient { + public static String responseFromMockserver(MockServerContainer mockServer, String path) throws IOException { URLConnection urlConnection = new URL(mockServer.getEndpoint() + path).openConnection(); - @Cleanup BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + @Cleanup + BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); return reader.readLine(); } } diff --git a/modules/mongodb/src/main/java/org/testcontainers/containers/MongoDBContainer.java b/modules/mongodb/src/main/java/org/testcontainers/containers/MongoDBContainer.java index 87db80846a8..81bb59fd69d 100644 --- a/modules/mongodb/src/main/java/org/testcontainers/containers/MongoDBContainer.java +++ b/modules/mongodb/src/main/java/org/testcontainers/containers/MongoDBContainer.java @@ -18,10 +18,15 @@ public class MongoDBContainer extends GenericContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("mongo"); + private static final String DEFAULT_TAG = "4.0.10"; + private static final int CONTAINER_EXIT_CODE_OK = 0; + private static final int MONGODB_INTERNAL_PORT = 27017; + private static final int AWAIT_INIT_REPLICA_SET_ATTEMPTS = 60; + private static final String MONGODB_DATABASE_NAME_DEFAULT = "test"; /** @@ -38,14 +43,11 @@ public MongoDBContainer(@NonNull final String dockerImageName) { public MongoDBContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(MONGODB_INTERNAL_PORT); withCommand("--replSet", "docker-rs"); - waitingFor( - Wait.forLogMessage("(?i).*waiting for connections.*", 1) - ); + waitingFor(Wait.forLogMessage("(?i).*waiting for connections.*", 1)); } /** @@ -54,11 +56,7 @@ public MongoDBContainer(final DockerImageName dockerImageName) { * @return a connection url pointing to a mongodb instance */ public String getConnectionString() { - return String.format( - "mongodb://%s:%d", - getHost(), - getMappedPort(MONGODB_INTERNAL_PORT) - ); + return String.format("mongodb://%s:%d", getHost(), getMappedPort(MONGODB_INTERNAL_PORT)); } /** @@ -89,7 +87,7 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) { } private String[] buildMongoEvalCommand(final String command) { - return new String[]{"mongo", "--eval", command}; + return new String[] { "mongo", "--eval", command }; } private void checkMongoNodeExitCode(final Container.ExecResult execResult) { @@ -103,21 +101,19 @@ private void checkMongoNodeExitCode(final Container.ExecResult execResult) { private String buildMongoWaitCommand() { return String.format( "var attempt = 0; " + - "while" + - "(%s) " + - "{ " + - "if (attempt > %d) {quit(1);} " + - "print('%s ' + attempt); sleep(100); attempt++; " + - " }", + "while" + + "(%s) " + + "{ " + + "if (attempt > %d) {quit(1);} " + + "print('%s ' + attempt); sleep(100); attempt++; " + + " }", "db.runCommand( { isMaster: 1 } ).ismaster==false", AWAIT_INIT_REPLICA_SET_ATTEMPTS, "An attempt to await for a single node replica set initialization:" ); } - private void checkMongoNodeExitCodeAfterWaiting( - final Container.ExecResult execResultWaitForMaster - ) { + private void checkMongoNodeExitCodeAfterWaiting(final Container.ExecResult execResultWaitForMaster) { if (execResultWaitForMaster.getExitCode() != CONTAINER_EXIT_CODE_OK) { final String errorMessage = String.format( "A single node replica set was not initialized in a set timeout: %d attempts", @@ -128,12 +124,10 @@ private void checkMongoNodeExitCodeAfterWaiting( } } - @SneakyThrows(value = {IOException.class, InterruptedException.class}) + @SneakyThrows(value = { IOException.class, InterruptedException.class }) private void initReplicaSet() { log.debug("Initializing a single node node replica set..."); - final ExecResult execResultInitRs = execInContainer( - buildMongoEvalCommand("rs.initiate();") - ); + final ExecResult execResultInitRs = execInContainer(buildMongoEvalCommand("rs.initiate();")); log.debug(execResultInitRs.getStdout()); checkMongoNodeExitCode(execResultInitRs); @@ -141,15 +135,14 @@ private void initReplicaSet() { "Awaiting for a single node replica set initialization up to {} attempts", AWAIT_INIT_REPLICA_SET_ATTEMPTS ); - final ExecResult execResultWaitForMaster = execInContainer( - buildMongoEvalCommand(buildMongoWaitCommand()) - ); + final ExecResult execResultWaitForMaster = execInContainer(buildMongoEvalCommand(buildMongoWaitCommand())); log.debug(execResultWaitForMaster.getStdout()); checkMongoNodeExitCodeAfterWaiting(execResultWaitForMaster); } public static class ReplicaSetInitializationException extends RuntimeException { + ReplicaSetInitializationException(final String errorMessage) { super(errorMessage); } diff --git a/modules/mongodb/src/test/java/org/testcontainers/containers/MongoDBContainerTest.java b/modules/mongodb/src/test/java/org/testcontainers/containers/MongoDBContainerTest.java index 532a86208c1..6c98978f20a 100644 --- a/modules/mongodb/src/test/java/org/testcontainers/containers/MongoDBContainerTest.java +++ b/modules/mongodb/src/test/java/org/testcontainers/containers/MongoDBContainerTest.java @@ -13,12 +13,11 @@ import org.junit.Test; import org.testcontainers.utility.DockerImageName; -import static org.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.Matchers.endsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; - public class MongoDBContainerTest { /** @@ -31,7 +30,6 @@ public void shouldExecuteTransactions() { final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10")) // } ) { - // startingMongoDBContainer { mongoDBContainer.start(); // } @@ -41,15 +39,25 @@ public void shouldExecuteTransactions() { final String connectionString = mongoDBContainer.getConnectionString(); final MongoClient mongoSyncClientBase = MongoClients.create(connectionString); final MongoClient mongoSyncClient = MongoClients.create(mongoRsUrl); - mongoSyncClient.getDatabase("mydb1").getCollection("foo") - .withWriteConcern(WriteConcern.MAJORITY).insertOne(new Document("abc", 0)); - mongoSyncClient.getDatabase("mydb2").getCollection("bar") - .withWriteConcern(WriteConcern.MAJORITY).insertOne(new Document("xyz", 0)); - mongoSyncClientBase.getDatabase("mydb3").getCollection("baz") - .withWriteConcern(WriteConcern.MAJORITY).insertOne(new Document("def", 0)); + mongoSyncClient + .getDatabase("mydb1") + .getCollection("foo") + .withWriteConcern(WriteConcern.MAJORITY) + .insertOne(new Document("abc", 0)); + mongoSyncClient + .getDatabase("mydb2") + .getCollection("bar") + .withWriteConcern(WriteConcern.MAJORITY) + .insertOne(new Document("xyz", 0)); + mongoSyncClientBase + .getDatabase("mydb3") + .getCollection("baz") + .withWriteConcern(WriteConcern.MAJORITY) + .insertOne(new Document("def", 0)); final ClientSession clientSession = mongoSyncClient.startSession(); - final TransactionOptions txnOptions = TransactionOptions.builder() + final TransactionOptions txnOptions = TransactionOptions + .builder() .readPreference(ReadPreference.primary()) .readConcern(ReadConcern.LOCAL) .writeConcern(WriteConcern.MAJORITY) @@ -58,10 +66,8 @@ public void shouldExecuteTransactions() { final String trxResult = "Inserted into collections in different databases"; TransactionBody txnBody = () -> { - final MongoCollection coll1 = - mongoSyncClient.getDatabase("mydb1").getCollection("foo"); - final MongoCollection coll2 = - mongoSyncClient.getDatabase("mydb2").getCollection("bar"); + final MongoCollection coll1 = mongoSyncClient.getDatabase("mydb1").getCollection("foo"); + final MongoCollection coll2 = mongoSyncClient.getDatabase("mydb2").getCollection("bar"); coll1.insertOne(clientSession, new Document("abc", 1)); coll2.insertOne(clientSession, new Document("xyz", 999)); @@ -82,18 +88,14 @@ public void shouldExecuteTransactions() { @Test public void supportsMongoDB_4_4() { - try ( - final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.4")) - ) { + try (final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.4"))) { mongoDBContainer.start(); } } @Test public void shouldTestDatabaseName() { - try ( - final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10")) - ) { + try (final MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10"))) { mongoDBContainer.start(); final String databaseName = "my-db"; assertThat(mongoDBContainer.getReplicaSetUrl(databaseName), endsWith(databaseName)); diff --git a/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLR2DBCDatabaseContainer.java b/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLR2DBCDatabaseContainer.java index 59c3ed0de68..6a58b3488ff 100644 --- a/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLR2DBCDatabaseContainer.java +++ b/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLR2DBCDatabaseContainer.java @@ -13,7 +13,8 @@ public class MSSQLR2DBCDatabaseContainer implements R2DBCDatabaseContainer { private final MSSQLServerContainer container; public static ConnectionFactoryOptions getOptions(MSSQLServerContainer container) { - ConnectionFactoryOptions options = ConnectionFactoryOptions.builder() + ConnectionFactoryOptions options = ConnectionFactoryOptions + .builder() .option(ConnectionFactoryOptions.DRIVER, MSSQLR2DBCDatabaseContainerProvider.DRIVER) .build(); @@ -22,7 +23,8 @@ public static ConnectionFactoryOptions getOptions(MSSQLServerContainer contai @Override public ConnectionFactoryOptions configure(ConnectionFactoryOptions options) { - return options.mutate() + return options + .mutate() .option(ConnectionFactoryOptions.HOST, container.getHost()) .option(ConnectionFactoryOptions.PORT, container.getMappedPort(MSSQLServerContainer.MS_SQL_SERVER_PORT)) // TODO enable if/when MSSQLServerContainer adds support for customizing the DB name diff --git a/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainer.java b/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainer.java index fe6270d04c7..532316fb967 100644 --- a/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainer.java +++ b/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainer.java @@ -14,6 +14,7 @@ public class MSSQLServerContainer> extends JdbcDatabaseContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("mcr.microsoft.com/mssql/server"); + @Deprecated public static final String DEFAULT_TAG = "2017-CU12"; @@ -30,13 +31,14 @@ public class MSSQLServerContainer> exten private String password = DEFAULT_PASSWORD; private static final int DEFAULT_STARTUP_TIMEOUT_SECONDS = 240; + private static final int DEFAULT_CONNECT_TIMEOUT_SECONDS = 240; - private static final Pattern[] PASSWORD_CATEGORY_VALIDATION_PATTERNS = new Pattern[]{ + private static final Pattern[] PASSWORD_CATEGORY_VALIDATION_PATTERNS = new Pattern[] { Pattern.compile("[A-Z]+"), Pattern.compile("[a-z]+"), Pattern.compile("[0-9]+"), - Pattern.compile("[^a-zA-Z0-9]+", Pattern.CASE_INSENSITIVE) + Pattern.compile("[^a-zA-Z0-9]+", Pattern.CASE_INSENSITIVE), }; /** @@ -53,7 +55,6 @@ public MSSQLServerContainer(final String dockerImageName) { public MSSQLServerContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withStartupTimeoutSeconds(DEFAULT_STARTUP_TIMEOUT_SECONDS); @@ -131,7 +132,6 @@ public SELF withPassword(final String password) { } private void checkPasswordStrength(String password) { - if (password == null) { throw new IllegalArgumentException("Null password is not allowed"); } @@ -144,18 +144,19 @@ private void checkPasswordStrength(String password) { throw new IllegalArgumentException("Password can be up to 128 characters long"); } - long satisfiedCategories = Stream.of(PASSWORD_CATEGORY_VALIDATION_PATTERNS) + long satisfiedCategories = Stream + .of(PASSWORD_CATEGORY_VALIDATION_PATTERNS) .filter(p -> p.matcher(password).find()) .count(); if (satisfiedCategories < 3) { throw new IllegalArgumentException( "Password must contain characters from three of the following four categories:\n" + - " - Latin uppercase letters (A through Z)\n" + - " - Latin lowercase letters (a through z)\n" + - " - Base 10 digits (0 through 9)\n" + - " - Non-alphanumeric characters such as: exclamation point (!), dollar sign ($), number sign (#), " + - "or percent (%)." + " - Latin uppercase letters (A through Z)\n" + + " - Latin lowercase letters (a through z)\n" + + " - Base 10 digits (0 through 9)\n" + + " - Non-alphanumeric characters such as: exclamation point (!), dollar sign ($), number sign (#), " + + "or percent (%)." ); } } diff --git a/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainerProvider.java b/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainerProvider.java index c3495c8a3a6..27e8ab75225 100644 --- a/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainerProvider.java +++ b/modules/mssqlserver/src/main/java/org/testcontainers/containers/MSSQLServerContainerProvider.java @@ -6,6 +6,7 @@ * Factory for MS SQL Server containers. */ public class MSSQLServerContainerProvider extends JdbcDatabaseContainerProvider { + @Override public boolean supports(String databaseType) { return databaseType.equals(MSSQLServerContainer.NAME); diff --git a/modules/mssqlserver/src/test/java/org/testcontainers/jdbc/mssqlserver/MSSQLServerJDBCDriverTest.java b/modules/mssqlserver/src/test/java/org/testcontainers/jdbc/mssqlserver/MSSQLServerJDBCDriverTest.java index 00e22199b46..bdb623136fb 100644 --- a/modules/mssqlserver/src/test/java/org/testcontainers/jdbc/mssqlserver/MSSQLServerJDBCDriverTest.java +++ b/modules/mssqlserver/src/test/java/org/testcontainers/jdbc/mssqlserver/MSSQLServerJDBCDriverTest.java @@ -4,18 +4,21 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class MSSQLServerJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:sqlserver:2017-CU12://hostname:hostport;databaseName=databasename", EnumSet.noneOf(Options.class)}, - }); + return Arrays.asList( + new Object[][] { + { + "jdbc:tc:sqlserver:2017-CU12://hostname:hostport;databaseName=databasename", + EnumSet.noneOf(Options.class), + }, + } + ); } } diff --git a/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomPasswordMSSQLServerTest.java b/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomPasswordMSSQLServerTest.java index 6ebd3624577..49bae13d9e3 100644 --- a/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomPasswordMSSQLServerTest.java +++ b/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomPasswordMSSQLServerTest.java @@ -22,11 +22,15 @@ public class CustomPasswordMSSQLServerTest { private static String UPPER_CASE_LETTERS = "ABCDE"; + private static String LOWER_CASE_LETTERS = "abcde"; + private static String NUMBERS = "12345"; + private static String SPECIAL_CHARS = "_(!)_"; private String password; + private Boolean valid; public CustomPasswordMSSQLServerTest(String password, Boolean valid) { @@ -36,45 +40,41 @@ public CustomPasswordMSSQLServerTest(String password, Boolean valid) { @Parameterized.Parameters public static Collection data() { - return Arrays.asList(new Object[][]{ - new Object[]{null, false}, - // too short - {"abc123", false}, - - // too long - {RandomStringUtils.randomAlphabetic(129), false}, - - // only 2 categories - {UPPER_CASE_LETTERS + NUMBERS, false}, - {UPPER_CASE_LETTERS + SPECIAL_CHARS, false}, - {LOWER_CASE_LETTERS + NUMBERS, false}, - {LOWER_CASE_LETTERS + SPECIAL_CHARS, false}, - {NUMBERS + SPECIAL_CHARS, false}, - - // 3 categories - {UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + NUMBERS, true}, - {UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + SPECIAL_CHARS, true}, - {UPPER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS, true}, - {LOWER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS, true}, - - // 4 categories - {UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS, true}, - - - }); + return Arrays.asList( + new Object[][] { + new Object[] { null, false }, + // too short + { "abc123", false }, + // too long + { RandomStringUtils.randomAlphabetic(129), false }, + // only 2 categories + { UPPER_CASE_LETTERS + NUMBERS, false }, + { UPPER_CASE_LETTERS + SPECIAL_CHARS, false }, + { LOWER_CASE_LETTERS + NUMBERS, false }, + { LOWER_CASE_LETTERS + SPECIAL_CHARS, false }, + { NUMBERS + SPECIAL_CHARS, false }, + // 3 categories + { UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + NUMBERS, true }, + { UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + SPECIAL_CHARS, true }, + { UPPER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS, true }, + { LOWER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS, true }, + // 4 categories + { UPPER_CASE_LETTERS + LOWER_CASE_LETTERS + NUMBERS + SPECIAL_CHARS, true }, + } + ); } @Test public void runPasswordTests() { try { new MSSQLServerContainer<>(MSSQLServerTestImages.MSSQL_SERVER_IMAGE).withPassword(this.password); - if (!valid) + if (!valid) { fail("Password " + this.password + " is not valid. Expected exception"); + } } catch (IllegalArgumentException e) { - if (valid) + if (valid) { fail("Password " + this.password + " should have been validated"); + } } } - - } diff --git a/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomizableMSSQLServerTest.java b/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomizableMSSQLServerTest.java index d3c387e7b4a..21ea5380801 100644 --- a/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomizableMSSQLServerTest.java +++ b/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/CustomizableMSSQLServerTest.java @@ -16,9 +16,12 @@ public class CustomizableMSSQLServerTest extends AbstractContainerDatabaseTest { @Test public void testSqlServerConnection() throws SQLException { - try (MSSQLServerContainer mssqlServerContainer = new MSSQLServerContainer<>(DockerImageName.parse("mcr.microsoft.com/mssql/server:2017-CU12")) - .withPassword(STRONG_PASSWORD)) { - + try ( + MSSQLServerContainer mssqlServerContainer = new MSSQLServerContainer<>( + DockerImageName.parse("mcr.microsoft.com/mssql/server:2017-CU12") + ) + .withPassword(STRONG_PASSWORD) + ) { mssqlServerContainer.start(); ResultSet resultSet = performQuery(mssqlServerContainer, mssqlServerContainer.getTestQueryString()); diff --git a/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/SimpleMSSQLServerTest.java b/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/SimpleMSSQLServerTest.java index 1530760b673..36d215c8757 100644 --- a/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/SimpleMSSQLServerTest.java +++ b/modules/mssqlserver/src/test/java/org/testcontainers/junit/mssqlserver/SimpleMSSQLServerTest.java @@ -1,24 +1,27 @@ package org.testcontainers.junit.mssqlserver; import org.junit.Test; +import org.testcontainers.MSSQLServerTestImages; import org.testcontainers.containers.MSSQLServerContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; -import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import static org.hamcrest.CoreMatchers.containsString; +import javax.sql.DataSource; + import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.MSSQLServerTestImages.MSSQL_SERVER_IMAGE; public class SimpleMSSQLServerTest extends AbstractContainerDatabaseTest { @Test public void testSimple() throws SQLException { - try (MSSQLServerContainer mssqlServer = new MSSQLServerContainer<>(MSSQL_SERVER_IMAGE)) { + try ( + MSSQLServerContainer mssqlServer = new MSSQLServerContainer<>(MSSQLServerTestImages.MSSQL_SERVER_IMAGE) + ) { mssqlServer.start(); ResultSet resultSet = performQuery(mssqlServer, "SELECT 1"); @@ -29,10 +32,11 @@ public void testSimple() throws SQLException { @Test public void testWithAdditionalUrlParamInJdbcUrl() { - try (MSSQLServerContainer mssqlServer = new MSSQLServerContainer<>(MSSQL_SERVER_IMAGE) - .withUrlParam("integratedSecurity", "false") - .withUrlParam("applicationName", "MyApp")) { - + try ( + MSSQLServerContainer mssqlServer = new MSSQLServerContainer<>(MSSQLServerTestImages.MSSQL_SERVER_IMAGE) + .withUrlParam("integratedSecurity", "false") + .withUrlParam("applicationName", "MyApp") + ) { mssqlServer.start(); String jdbcUrl = mssqlServer.getJdbcUrl(); @@ -40,10 +44,11 @@ public void testWithAdditionalUrlParamInJdbcUrl() { } } - @Test public void testSetupDatabase() throws SQLException { - try (MSSQLServerContainer mssqlServer = new MSSQLServerContainer<>(MSSQL_SERVER_IMAGE)) { + try ( + MSSQLServerContainer mssqlServer = new MSSQLServerContainer<>(MSSQLServerTestImages.MSSQL_SERVER_IMAGE) + ) { mssqlServer.start(); DataSource ds = getDataSource(mssqlServer); Statement statement = ds.getConnection().createStatement(); diff --git a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java index 20be08c2aec..14206018954 100644 --- a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java +++ b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainer.java @@ -26,10 +26,15 @@ public class MySQLContainer> extends JdbcDatab static final String DEFAULT_PASSWORD = "test"; private static final String MY_CNF_CONFIG_OVERRIDE_PARAM_NAME = "TC_MY_CNF"; + public static final Integer MYSQL_PORT = 3306; + private String databaseName = "test"; + private String username = DEFAULT_USER; + private String password = DEFAULT_PASSWORD; + private static final String MYSQL_ROOT_USER = "root"; /** @@ -46,13 +51,11 @@ public MySQLContainer(String dockerImageName) { public MySQLContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); addExposedPort(MYSQL_PORT); } - @NotNull @Override protected Set getLivenessCheckPorts() { @@ -61,8 +64,11 @@ protected Set getLivenessCheckPorts() { @Override protected void configure() { - optionallyMapResourceParameterAsVolume(MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, "/etc/mysql/conf.d", - "mysql-default-conf"); + optionallyMapResourceParameterAsVolume( + MY_CNF_CONFIG_OVERRIDE_PARAM_NAME, + "/etc/mysql/conf.d", + "mysql-default-conf" + ); addEnv("MYSQL_DATABASE", databaseName); if (!MYSQL_ROOT_USER.equalsIgnoreCase(username)) { @@ -92,8 +98,7 @@ public String getDriverClassName() { @Override public String getJdbcUrl() { String additionalUrlParams = constructUrlParameters("?", "&"); - return "jdbc:mysql://" + getHost() + ":" + getMappedPort(MYSQL_PORT) + - "/" + databaseName + additionalUrlParams; + return "jdbc:mysql://" + getHost() + ":" + getMappedPort(MYSQL_PORT) + "/" + databaseName + additionalUrlParams; } @Override diff --git a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainerProvider.java b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainerProvider.java index 18d126635b1..621001d7b57 100644 --- a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainerProvider.java +++ b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLContainerProvider.java @@ -35,5 +35,4 @@ public JdbcDatabaseContainer newInstance(String tag) { public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) { return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); } - } diff --git a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainer.java b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainer.java index 274224352a8..4bbb542fec8 100644 --- a/modules/mysql/src/main/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainer.java +++ b/modules/mysql/src/main/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainer.java @@ -13,7 +13,8 @@ public class MySQLR2DBCDatabaseContainer implements R2DBCDatabaseContainer { private final MySQLContainer container; public static ConnectionFactoryOptions getOptions(MySQLContainer container) { - ConnectionFactoryOptions options = ConnectionFactoryOptions.builder() + ConnectionFactoryOptions options = ConnectionFactoryOptions + .builder() .option(ConnectionFactoryOptions.DRIVER, MySQLR2DBCDatabaseContainerProvider.DRIVER) .build(); @@ -22,7 +23,8 @@ public static ConnectionFactoryOptions getOptions(MySQLContainer container) { @Override public ConnectionFactoryOptions configure(ConnectionFactoryOptions options) { - return options.mutate() + return options + .mutate() .option(ConnectionFactoryOptions.HOST, container.getHost()) .option(ConnectionFactoryOptions.PORT, container.getMappedPort(MySQLContainer.MYSQL_PORT)) .option(ConnectionFactoryOptions.DATABASE, container.getDatabaseName()) diff --git a/modules/mysql/src/test/java/org/testcontainers/MySQLTestImages.java b/modules/mysql/src/test/java/org/testcontainers/MySQLTestImages.java index 833dc1448cf..81de83be0b9 100644 --- a/modules/mysql/src/test/java/org/testcontainers/MySQLTestImages.java +++ b/modules/mysql/src/test/java/org/testcontainers/MySQLTestImages.java @@ -3,7 +3,10 @@ import org.testcontainers.utility.DockerImageName; public class MySQLTestImages { + public static final DockerImageName MYSQL_56_IMAGE = DockerImageName.parse("mysql:5.6.51"); + public static final DockerImageName MYSQL_57_IMAGE = DockerImageName.parse("mysql:5.7.34"); + public static final DockerImageName MYSQL_80_IMAGE = DockerImageName.parse("mysql:8.0.24"); } diff --git a/modules/mysql/src/test/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainerTest.java b/modules/mysql/src/test/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainerTest.java index 334fabb0a49..42a852ad1f1 100644 --- a/modules/mysql/src/test/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainerTest.java +++ b/modules/mysql/src/test/java/org/testcontainers/containers/MySQLR2DBCDatabaseContainerTest.java @@ -20,5 +20,4 @@ protected String createR2DBCUrl() { protected MySQLContainer createContainer() { return new MySQLContainer<>(MySQLTestImages.MYSQL_80_IMAGE); } - } diff --git a/modules/mysql/src/test/java/org/testcontainers/containers/MySQLRootAccountTest.java b/modules/mysql/src/test/java/org/testcontainers/containers/MySQLRootAccountTest.java index 86b13a0d1bf..0320eee9255 100644 --- a/modules/mysql/src/test/java/org/testcontainers/containers/MySQLRootAccountTest.java +++ b/modules/mysql/src/test/java/org/testcontainers/containers/MySQLRootAccountTest.java @@ -18,13 +18,10 @@ public class MySQLRootAccountTest { @Parameterized.Parameters(name = "{0}") public static DockerImageName[] params() { - return new DockerImageName[]{ - MySQLTestImages.MYSQL_80_IMAGE, - MySQLTestImages.MYSQL_57_IMAGE - }; + return new DockerImageName[] { MySQLTestImages.MYSQL_80_IMAGE, MySQLTestImages.MYSQL_57_IMAGE }; } - @Parameterized.Parameter() + @Parameterized.Parameter public DockerImageName image; @Test diff --git a/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/JDBCDriverWithPoolTest.java b/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/JDBCDriverWithPoolTest.java index 3b9f9842095..a30f3f59888 100644 --- a/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/JDBCDriverWithPoolTest.java +++ b/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/JDBCDriverWithPoolTest.java @@ -11,15 +11,16 @@ import org.testcontainers.jdbc.ContainerDatabaseDriver; import org.vibur.dbcp.ViburDBCPDataSource; -import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; +import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; -import static java.util.Arrays.asList; +import javax.sql.DataSource; + import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; /** @@ -31,12 +32,14 @@ @RunWith(Parameterized.class) public class JDBCDriverWithPoolTest { - public static final String URL = "jdbc:tc:mysql:5.7.34://hostname/databasename?TC_INITFUNCTION=org.testcontainers.jdbc.mysql.JDBCDriverWithPoolTest::sampleInitFunction"; + public static final String URL = + "jdbc:tc:mysql:5.7.34://hostname/databasename?TC_INITFUNCTION=org.testcontainers.jdbc.mysql.JDBCDriverWithPoolTest::sampleInitFunction"; + private final DataSource dataSource; @Parameterized.Parameters public static Iterable> dataSourceSuppliers() { - return asList( + return Arrays.asList( JDBCDriverWithPoolTest::getTomcatDataSourceWithDriverClassName, JDBCDriverWithPoolTest::getTomcatDataSource, JDBCDriverWithPoolTest::getHikariDataSourceWithDriverClassName, @@ -54,13 +57,12 @@ public JDBCDriverWithPoolTest(Supplier dataSourceSupplier) { @Test public void testMySQLWithConnectionPoolUsingSameContainer() throws SQLException, InterruptedException { - // Populate the database with some data in multiple threads, so that multiple connections from the pool will be used for (int i = 0; i < 100; i++) { executorService.submit(() -> { try { - new QueryRunner(dataSource).insert("INSERT INTO my_counter (n) VALUES (5)", - (ResultSetHandler) rs -> true); + new QueryRunner(dataSource) + .insert("INSERT INTO my_counter (n) VALUES (5)", (ResultSetHandler) rs -> true); } catch (SQLException e) { e.printStackTrace(); } @@ -72,22 +74,28 @@ public void testMySQLWithConnectionPoolUsingSameContainer() throws SQLException, executorService.awaitTermination(5, TimeUnit.MINUTES); // compare to expected results - int count = new QueryRunner(dataSource).query("SELECT COUNT(1) FROM my_counter", rs -> { - rs.next(); - return rs.getInt(1); - }); + int count = new QueryRunner(dataSource) + .query( + "SELECT COUNT(1) FROM my_counter", + rs -> { + rs.next(); + return rs.getInt(1); + } + ); assertEquals("Reuse of a datasource points to the same DB container", 100, count); - - int sum = new QueryRunner(dataSource).query("SELECT SUM(n) FROM my_counter", rs -> { - rs.next(); - return rs.getInt(1); - }); + int sum = new QueryRunner(dataSource) + .query( + "SELECT SUM(n) FROM my_counter", + rs -> { + rs.next(); + return rs.getInt(1); + } + ); // 100 records * 5 = 500 expected assertEquals("Reuse of a datasource points to the same DB container", 500, sum); } - private static DataSource getTomcatDataSourceWithDriverClassName() { PoolProperties poolProperties = new PoolProperties(); poolProperties.setUrl(URL + ";TEST=TOMCAT_WITH_CLASSNAME"); // append a dummy URL element to ensure different DB per test @@ -134,7 +142,7 @@ private static DataSource getViburDataSourceWithDriverClassName() { ViburDBCPDataSource ds = new ViburDBCPDataSource(); ds.setJdbcUrl(URL + ";TEST=VIBUR_WITH_CLASSNAME"); - ds.setUsername("any"); // Recent versions of Vibur require a username, even though it will not be used + ds.setUsername("any"); // Recent versions of Vibur require a username, even though it will not be used ds.setPassword(""); ds.setPoolInitialSize(3); ds.setPoolMaxSize(10); @@ -149,7 +157,7 @@ private static DataSource getViburDataSourceWithDriverClassName() { private static DataSource getViburDataSource() { ViburDBCPDataSource ds = new ViburDBCPDataSource(); ds.setJdbcUrl(URL + ";TEST=VIBUR"); - ds.setUsername("any"); // Recent versions of Vibur require a username, even though it will not be used + ds.setUsername("any"); // Recent versions of Vibur require a username, even though it will not be used ds.setPassword(""); ds.setPoolInitialSize(3); ds.setPoolMaxSize(10); @@ -162,12 +170,8 @@ private static DataSource getViburDataSource() { @SuppressWarnings("SqlNoDataSourceInspection") public static void sampleInitFunction(Connection connection) throws SQLException { - connection.createStatement().execute("CREATE TABLE bar (\n" + - " foo VARCHAR(255)\n" + - ");"); + connection.createStatement().execute("CREATE TABLE bar (\n" + " foo VARCHAR(255)\n" + ");"); connection.createStatement().execute("INSERT INTO bar (foo) VALUES ('hello world');"); - connection.createStatement().execute("CREATE TABLE my_counter (\n" + - " n INT\n" + - ");"); + connection.createStatement().execute("CREATE TABLE my_counter (\n" + " n INT\n" + ");"); } } diff --git a/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/MySQLJDBCDriverTest.java b/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/MySQLJDBCDriverTest.java index 302621879eb..752fbca8e07 100644 --- a/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/MySQLJDBCDriverTest.java +++ b/modules/mysql/src/test/java/org/testcontainers/jdbc/mysql/MySQLJDBCDriverTest.java @@ -4,27 +4,48 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class MySQLJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:mysql://hostname/databasename", EnumSet.noneOf(Options.class)}, - {"jdbc:tc:mysql://hostname/databasename?user=someuser&TC_INITSCRIPT=somepath/init_mysql.sql", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&password=somepwd&TC_INITSCRIPT=somepath/init_mysql.sql", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&password=somepwd&TC_INITSCRIPT=file:sql/init_mysql.sql", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&password=somepwd&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", EnumSet.of(Options.ScriptedSchema, Options.JDBCParams)}, - {"jdbc:tc:mysql:5.7.34://hostname/databasename?TC_INITSCRIPT=somepath/init_unicode_mysql.sql&useUnicode=yes&characterEncoding=utf8", EnumSet.of(Options.CharacterSet)}, - {"jdbc:tc:mysql:5.7.34://hostname/databasename", EnumSet.noneOf(Options.class)}, - {"jdbc:tc:mysql:5.7.34://hostname/databasename?useSSL=false", EnumSet.noneOf(Options.class)}, - {"jdbc:tc:mysql:5.6.51://hostname/databasename?TC_MY_CNF=somepath/mysql_conf_override", EnumSet.of(Options.CustomIniFile)}, - }); + return Arrays.asList( + new Object[][] { + { "jdbc:tc:mysql://hostname/databasename", EnumSet.noneOf(Options.class) }, + { + "jdbc:tc:mysql://hostname/databasename?user=someuser&TC_INITSCRIPT=somepath/init_mysql.sql", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&password=somepwd&TC_INITSCRIPT=somepath/init_mysql.sql", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&password=somepwd&TC_INITSCRIPT=file:sql/init_mysql.sql", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mysql:5.7.34://hostname/databasename?user=someuser&password=somepwd&TC_INITFUNCTION=org.testcontainers.jdbc.AbstractJDBCDriverTest::sampleInitFunction", + EnumSet.of(Options.ScriptedSchema, Options.JDBCParams), + }, + { + "jdbc:tc:mysql:5.7.34://hostname/databasename?TC_INITSCRIPT=somepath/init_unicode_mysql.sql&useUnicode=yes&characterEncoding=utf8", + EnumSet.of(Options.CharacterSet), + }, + { "jdbc:tc:mysql:5.7.34://hostname/databasename", EnumSet.noneOf(Options.class) }, + { "jdbc:tc:mysql:5.7.34://hostname/databasename?useSSL=false", EnumSet.noneOf(Options.class) }, + { + "jdbc:tc:mysql:5.6.51://hostname/databasename?TC_MY_CNF=somepath/mysql_conf_override", + EnumSet.of(Options.CustomIniFile), + }, + } + ); } } diff --git a/modules/mysql/src/test/java/org/testcontainers/junit/mysql/CustomizableMysqlTest.java b/modules/mysql/src/test/java/org/testcontainers/junit/mysql/CustomizableMysqlTest.java index 0b72ce083d2..20b49d19201 100644 --- a/modules/mysql/src/test/java/org/testcontainers/junit/mysql/CustomizableMysqlTest.java +++ b/modules/mysql/src/test/java/org/testcontainers/junit/mysql/CustomizableMysqlTest.java @@ -11,19 +11,23 @@ import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; public class CustomizableMysqlTest extends AbstractContainerDatabaseTest { + private static final String DB_NAME = "foo"; + private static final String USER = "bar"; + private static final String PWD = "baz"; @Test public void testSimple() throws SQLException { // Add MYSQL_ROOT_HOST environment so that we can root login from anywhere for testing purposes - try (MySQLContainer mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) - .withDatabaseName(DB_NAME) - .withUsername(USER) - .withPassword(PWD) - .withEnv("MYSQL_ROOT_HOST", "%")) { - + try ( + MySQLContainer mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) + .withDatabaseName(DB_NAME) + .withUsername(USER) + .withPassword(PWD) + .withEnv("MYSQL_ROOT_HOST", "%") + ) { mysql.start(); ResultSet resultSet = performQuery(mysql, "SELECT 1"); diff --git a/modules/mysql/src/test/java/org/testcontainers/junit/mysql/MultiVersionMySQLTest.java b/modules/mysql/src/test/java/org/testcontainers/junit/mysql/MultiVersionMySQLTest.java index 32dee3cd056..735af251236 100644 --- a/modules/mysql/src/test/java/org/testcontainers/junit/mysql/MultiVersionMySQLTest.java +++ b/modules/mysql/src/test/java/org/testcontainers/junit/mysql/MultiVersionMySQLTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.testcontainers.MySQLTestImages; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; import org.testcontainers.utility.DockerImageName; @@ -11,23 +12,20 @@ import java.sql.SQLException; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.testcontainers.MySQLTestImages.MYSQL_56_IMAGE; -import static org.testcontainers.MySQLTestImages.MYSQL_57_IMAGE; -import static org.testcontainers.MySQLTestImages.MYSQL_80_IMAGE; @RunWith(Parameterized.class) public class MultiVersionMySQLTest extends AbstractContainerDatabaseTest { @Parameterized.Parameters(name = "{0}") public static DockerImageName[] params() { - return new DockerImageName[]{ - MYSQL_56_IMAGE, - MYSQL_57_IMAGE, - MYSQL_80_IMAGE + return new DockerImageName[] { + MySQLTestImages.MYSQL_56_IMAGE, + MySQLTestImages.MYSQL_57_IMAGE, + MySQLTestImages.MYSQL_80_IMAGE, }; } - @Parameterized.Parameter() + @Parameterized.Parameter public DockerImageName dockerImageName; @Test @@ -37,7 +35,11 @@ public void versionCheckTest() throws SQLException { final ResultSet resultSet = performQuery(mysql, "SELECT VERSION()"); final String resultSetString = resultSet.getString(1); - assertEquals("The database version can be set using a container rule parameter", dockerImageName.getVersionPart(), resultSetString); + assertEquals( + "The database version can be set using a container rule parameter", + dockerImageName.getVersionPart(), + resultSetString + ); } } } diff --git a/modules/mysql/src/test/java/org/testcontainers/junit/mysql/SimpleMySQLTest.java b/modules/mysql/src/test/java/org/testcontainers/junit/mysql/SimpleMySQLTest.java index 90973bc4b56..6441724c443 100644 --- a/modules/mysql/src/test/java/org/testcontainers/junit/mysql/SimpleMySQLTest.java +++ b/modules/mysql/src/test/java/org/testcontainers/junit/mysql/SimpleMySQLTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testcontainers.MySQLTestImages; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; @@ -18,15 +19,12 @@ import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; import static org.junit.Assume.assumeFalse; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; import static org.rnorth.visibleassertions.VisibleAssertions.fail; -import static org.testcontainers.MySQLTestImages.MYSQL_56_IMAGE; -import static org.testcontainers.MySQLTestImages.MYSQL_57_IMAGE; - public class SimpleMySQLTest extends AbstractContainerDatabaseTest { @@ -51,10 +49,11 @@ public class SimpleMySQLTest extends AbstractContainerDatabaseTest { @Test public void testSimple() throws SQLException { - try (MySQLContainer mysql = new MySQLContainer<>(MYSQL_57_IMAGE) - .withConfigurationOverride("somepath/mysql_conf_override") - .withLogConsumer(new Slf4jLogConsumer(logger))) { - + try ( + MySQLContainer mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) + .withConfigurationOverride("somepath/mysql_conf_override") + .withLogConsumer(new Slf4jLogConsumer(logger)) + ) { mysql.start(); ResultSet resultSet = performQuery(mysql, "SELECT 1"); @@ -66,16 +65,20 @@ public void testSimple() throws SQLException { @Test public void testSpecificVersion() throws SQLException { - try (MySQLContainer mysqlOldVersion = new MySQLContainer<>(MYSQL_56_IMAGE) - .withConfigurationOverride("somepath/mysql_conf_override") - .withLogConsumer(new Slf4jLogConsumer(logger))) { - + try ( + MySQLContainer mysqlOldVersion = new MySQLContainer<>(MySQLTestImages.MYSQL_56_IMAGE) + .withConfigurationOverride("somepath/mysql_conf_override") + .withLogConsumer(new Slf4jLogConsumer(logger)) + ) { mysqlOldVersion.start(); ResultSet resultSet = performQuery(mysqlOldVersion, "SELECT VERSION()"); String resultSetString = resultSet.getString(1); - assertTrue("The database version can be set using a container rule parameter", resultSetString.startsWith("5.6")); + assertTrue( + "The database version can be set using a container rule parameter", + resultSetString.startsWith("5.6") + ); } } @@ -83,9 +86,10 @@ public void testSpecificVersion() throws SQLException { public void testMySQLWithCustomIniFile() throws SQLException { assumeFalse(SystemUtils.IS_OS_WINDOWS); - try (MySQLContainer mysqlCustomConfig = new MySQLContainer<>(MYSQL_56_IMAGE) - .withConfigurationOverride("somepath/mysql_conf_override")) { - + try ( + MySQLContainer mysqlCustomConfig = new MySQLContainer<>(MySQLTestImages.MYSQL_56_IMAGE) + .withConfigurationOverride("somepath/mysql_conf_override") + ) { mysqlCustomConfig.start(); ResultSet resultSet = performQuery(mysqlCustomConfig, "SELECT @@GLOBAL.innodb_file_format"); @@ -97,9 +101,10 @@ public void testMySQLWithCustomIniFile() throws SQLException { @Test public void testCommandOverride() throws SQLException { - try (MySQLContainer mysqlCustomConfig = new MySQLContainer<>(MYSQL_57_IMAGE) - .withCommand("mysqld --auto_increment_increment=42")) { - + try ( + MySQLContainer mysqlCustomConfig = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) + .withCommand("mysqld --auto_increment_increment=42") + ) { mysqlCustomConfig.start(); ResultSet resultSet = performQuery(mysqlCustomConfig, "show variables like 'auto_increment_increment'"); @@ -111,9 +116,11 @@ public void testCommandOverride() throws SQLException { @Test public void testExplicitInitScript() throws SQLException { - try (MySQLContainer container = new MySQLContainer<>(MYSQL_57_IMAGE) - .withInitScript("somepath/init_mysql.sql") - .withLogConsumer(new Slf4jLogConsumer(logger))) { + try ( + MySQLContainer container = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) + .withInitScript("somepath/init_mysql.sql") + .withLogConsumer(new Slf4jLogConsumer(logger)) + ) { container.start(); ResultSet resultSet = performQuery(container, "SELECT foo FROM bar"); @@ -125,11 +132,13 @@ public void testExplicitInitScript() throws SQLException { @Test(expected = ContainerLaunchException.class) public void testEmptyPasswordWithNonRootUser() { - try (MySQLContainer container = new MySQLContainer<>(MYSQL_56_IMAGE) - .withDatabaseName("TEST") - .withUsername("test") - .withPassword("") - .withEnv("MYSQL_ROOT_HOST", "%")){ + try ( + MySQLContainer container = new MySQLContainer<>(MySQLTestImages.MYSQL_56_IMAGE) + .withDatabaseName("TEST") + .withUsername("test") + .withPassword("") + .withEnv("MYSQL_ROOT_HOST", "%") + ) { container.start(); fail("ContainerLaunchException expected to be thrown"); } @@ -138,12 +147,13 @@ public void testEmptyPasswordWithNonRootUser() { @Test public void testEmptyPasswordWithRootUser() throws SQLException { // Add MYSQL_ROOT_HOST environment so that we can root login from anywhere for testing purposes - try (MySQLContainer mysql = new MySQLContainer<>(MYSQL_56_IMAGE) - .withDatabaseName("foo") - .withUsername("root") - .withPassword("") - .withEnv("MYSQL_ROOT_HOST", "%")) { - + try ( + MySQLContainer mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_56_IMAGE) + .withDatabaseName("foo") + .withUsername("root") + .withPassword("") + .withEnv("MYSQL_ROOT_HOST", "%") + ) { mysql.start(); ResultSet resultSet = performQuery(mysql, "SELECT 1"); @@ -155,13 +165,13 @@ public void testEmptyPasswordWithRootUser() throws SQLException { @Test public void testWithAdditionalUrlParamTimeZone() throws SQLException { - MySQLContainer mysql = new MySQLContainer<>(MYSQL_57_IMAGE) + MySQLContainer mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) .withUrlParam("serverTimezone", "Europe/Zurich") .withEnv("TZ", "Europe/Zurich") .withLogConsumer(new Slf4jLogConsumer(logger)); mysql.start(); - try(Connection connection = mysql.createConnection("")) { + try (Connection connection = mysql.createConnection("")) { Statement statement = connection.createStatement(); statement.execute("SELECT NOW();"); try (ResultSet resultSet = statement.getResultSet()) { @@ -169,13 +179,18 @@ public void testWithAdditionalUrlParamTimeZone() throws SQLException { // checking that the time_zone MySQL is Europe/Zurich LocalDateTime localDateTime = resultSet.getObject(1, LocalDateTime.class); - ZonedDateTime actualDateTime = localDateTime.atZone(ZoneId.of("Europe/Zurich")) + ZonedDateTime actualDateTime = localDateTime + .atZone(ZoneId.of("Europe/Zurich")) .truncatedTo(ChronoUnit.MINUTES); - ZonedDateTime expectedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Zurich")) + ZonedDateTime expectedDateTime = ZonedDateTime + .now(ZoneId.of("Europe/Zurich")) .truncatedTo(ChronoUnit.MINUTES); - String message = String.format("MySQL time zone is not Europe/Zurich. MySQL date:%s, current date:%s", - actualDateTime, expectedDateTime); + String message = String.format( + "MySQL time zone is not Europe/Zurich. MySQL date:%s, current date:%s", + actualDateTime, + expectedDateTime + ); assertTrue(message, actualDateTime.equals(expectedDateTime)); } } finally { @@ -185,19 +200,20 @@ public void testWithAdditionalUrlParamTimeZone() throws SQLException { @Test public void testWithAdditionalUrlParamMultiQueries() throws SQLException { - MySQLContainer mysql = new MySQLContainer<>(MYSQL_57_IMAGE) + MySQLContainer mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) .withUrlParam("allowMultiQueries", "true") .withLogConsumer(new Slf4jLogConsumer(logger)); mysql.start(); - try(Connection connection = mysql.createConnection("")) { + try (Connection connection = mysql.createConnection("")) { Statement statement = connection.createStatement(); - String multiQuery = "DROP TABLE IF EXISTS bar; " + + String multiQuery = + "DROP TABLE IF EXISTS bar; " + "CREATE TABLE bar (foo VARCHAR(20)); " + "INSERT INTO bar (foo) VALUES ('hello world');"; statement.execute(multiQuery); statement.execute("SELECT foo FROM bar;"); - try(ResultSet resultSet = statement.getResultSet()) { + try (ResultSet resultSet = statement.getResultSet()) { resultSet.next(); String firstColumnValue = resultSet.getString(1); assertEquals("Value from bar should equal real value", "hello world", firstColumnValue); @@ -209,7 +225,7 @@ public void testWithAdditionalUrlParamMultiQueries() throws SQLException { @Test public void testWithAdditionalUrlParamInJdbcUrl() { - MySQLContainer mysql = new MySQLContainer<>(MYSQL_57_IMAGE) + MySQLContainer mysql = new MySQLContainer<>(MySQLTestImages.MYSQL_57_IMAGE) .withUrlParam("allowMultiQueries", "true") .withUrlParam("rewriteBatchedStatements", "true") .withLogConsumer(new Slf4jLogConsumer(logger)); diff --git a/modules/neo4j/src/custom-neo4j-plugin/java/ac/simons/neo4j/demos/plugins/HelloWorld.java b/modules/neo4j/src/custom-neo4j-plugin/java/ac/simons/neo4j/demos/plugins/HelloWorld.java index cbfcdc03a55..8948c98d53c 100644 --- a/modules/neo4j/src/custom-neo4j-plugin/java/ac/simons/neo4j/demos/plugins/HelloWorld.java +++ b/modules/neo4j/src/custom-neo4j-plugin/java/ac/simons/neo4j/demos/plugins/HelloWorld.java @@ -9,7 +9,6 @@ public class HelloWorld { @UserFunction("ac.simons.helloWorld") @Description("Simple Hello World") public String helloWorld(@Name("name") String name) { - return "Hello, " + name; } } diff --git a/modules/neo4j/src/main/java/org/testcontainers/containers/Neo4jContainer.java b/modules/neo4j/src/main/java/org/testcontainers/containers/Neo4jContainer.java index 6f0cf10ded7..94b4263fe8c 100644 --- a/modules/neo4j/src/main/java/org/testcontainers/containers/Neo4jContainer.java +++ b/modules/neo4j/src/main/java/org/testcontainers/containers/Neo4jContainer.java @@ -1,15 +1,5 @@ package org.testcontainers.containers; -import static java.net.HttpURLConnection.HTTP_OK; -import static java.util.stream.Collectors.toSet; - -import java.time.Duration; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; @@ -19,6 +9,15 @@ import org.testcontainers.utility.LicenseAcceptance; import org.testcontainers.utility.MountableFile; +import java.net.HttpURLConnection; +import java.time.Duration; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + /** * Testcontainer for Neo4j. * @@ -36,6 +35,7 @@ public class Neo4jContainer> extends GenericContaine * The default tag (version) to use. */ private static final String DEFAULT_TAG = "4.4"; + private static final String ENTERPRISE_TAG = DEFAULT_TAG + "-enterprise"; /** @@ -91,9 +91,7 @@ public Neo4jContainer(String dockerImageName) { */ public Neo4jContainer(final DockerImageName dockerImageName) { super(dockerImageName); - - this.standardImage = dockerImageName.getUnversionedPart() - .equals(DEFAULT_IMAGE_NAME.getUnversionedPart()); + this.standardImage = dockerImageName.getUnversionedPart().equals(DEFAULT_IMAGE_NAME.getUnversionedPart()); dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); @@ -101,39 +99,37 @@ public Neo4jContainer(final DockerImageName dockerImageName) { .withRegEx(String.format(".*Bolt enabled on .*:%d\\.\n", DEFAULT_BOLT_PORT)); WaitStrategy waitForHttp = new HttpWaitStrategy() .forPort(DEFAULT_HTTP_PORT) - .forStatusCodeMatching(response -> response == HTTP_OK); + .forStatusCodeMatching(response -> response == HttpURLConnection.HTTP_OK); - this.waitStrategy = new WaitAllStrategy() - .withStrategy(waitForBolt) - .withStrategy(waitForHttp) - .withStartupTimeout(Duration.ofMinutes(2)); + this.waitStrategy = + new WaitAllStrategy() + .withStrategy(waitForBolt) + .withStrategy(waitForHttp) + .withStartupTimeout(Duration.ofMinutes(2)); addExposedPorts(DEFAULT_BOLT_PORT, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT); } @Override public Set getLivenessCheckPortNumbers() { - - return Stream.of(DEFAULT_BOLT_PORT, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT) + return Stream + .of(DEFAULT_BOLT_PORT, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT) .map(this::getMappedPort) - .collect(toSet()); + .collect(Collectors.toSet()); } @Override protected void configure() { - boolean emptyAdminPassword = this.adminPassword == null || this.adminPassword.isEmpty(); String neo4jAuth = emptyAdminPassword ? "none" : String.format(AUTH_FORMAT, this.adminPassword); addEnv("NEO4J_AUTH", neo4jAuth); if (!this.labsPlugins.isEmpty()) { - String enabledPlugins = this.labsPlugins.stream() - .map(pluginName -> "\"" + pluginName + "\"") - .collect(Collectors.joining(",")); + String enabledPlugins = + this.labsPlugins.stream().map(pluginName -> "\"" + pluginName + "\"").collect(Collectors.joining(",")); addEnv("NEO4JLABS_PLUGINS", "[" + enabledPlugins + "]"); } - } /** @@ -169,8 +165,8 @@ public String getHttpsUrl() { public S withEnterpriseEdition() { if (!standardImage) { throw new IllegalStateException( - String.format("Cannot use enterprise version with alternative image %s.", - getDockerImageName())); + String.format("Cannot use enterprise version with alternative image %s.", getDockerImageName()) + ); } setDockerImageName(DEFAULT_IMAGE_NAME.withTag(ENTERPRISE_TAG).asCanonicalNameString()); @@ -189,7 +185,6 @@ public S withEnterpriseEdition() { * @return This container. */ public S withAdminPassword(final String adminPassword) { - this.adminPassword = adminPassword; return self(); } @@ -226,7 +221,8 @@ public S withoutAuthentication() { public S withDatabase(MountableFile graphDb) { if (!isNeo4jDatabaseVersionSupportingDbCopy()) { throw new IllegalArgumentException( - "Copying database folder is not supported for Neo4j instances with version 4.0 or higher."); + "Copying database folder is not supported for Neo4j instances with version 4.0 or higher." + ); } return withCopyFileToContainer(graphDb, "/data/databases/graph.db"); } @@ -254,7 +250,6 @@ public S withPlugins(MountableFile plugins) { * @return This container. */ public S withNeo4jConfig(String key, String value) { - addEnv(formatConfigurationKey(key), value); return self(); } @@ -273,7 +268,8 @@ public String getAdminPassword() { * @return This container. */ public S withLabsPlugins(Neo4jLabsPlugin... neo4jLabsPlugins) { - List pluginNames = Arrays.stream(neo4jLabsPlugins) + List pluginNames = Arrays + .stream(neo4jLabsPlugins) .map(plugin -> plugin.pluginName) .collect(Collectors.toList()); @@ -295,9 +291,7 @@ public S withLabsPlugins(String... neo4jLabsPlugins) { private static String formatConfigurationKey(String plainConfigKey) { final String prefix = "NEO4J_"; - return String.format("%s%s", prefix, plainConfigKey - .replaceAll("_", "__") - .replaceAll("\\.", "_")); + return String.format("%s%s", prefix, plainConfigKey.replaceAll("_", "__").replaceAll("\\.", "_")); } private boolean isNeo4jDatabaseVersionSupportingDbCopy() { @@ -311,9 +305,12 @@ private boolean isNeo4jDatabaseVersionSupportingDbCopy() { return true; } if (!usedComparableVersion.isSemanticVersion()) { - logger().warn("Version {} is not a semantic version. The function \"withDatabase\" will fail.", usedImageVersion); + logger() + .warn( + "Version {} is not a semantic version. The function \"withDatabase\" will fail.", + usedImageVersion + ); logger().warn("Copying databases is only supported for Neo4j versions 3.5.x"); - } return false; diff --git a/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerJUnitIntegrationTest.java b/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerJUnitIntegrationTest.java index 6832dfff0c7..3a2df1f7d0c 100644 --- a/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerJUnitIntegrationTest.java +++ b/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerJUnitIntegrationTest.java @@ -24,12 +24,11 @@ public class Neo4jContainerJUnitIntegrationTest { @Test public void shouldStart() { - boolean actual = neo4jContainer.isRunning(); assertThat(actual).isTrue(); - try (Driver driver = GraphDatabase - .driver(neo4jContainer.getBoltUrl(), AuthTokens.basic("neo4j", "password")); + try ( + Driver driver = GraphDatabase.driver(neo4jContainer.getBoltUrl(), AuthTokens.basic("neo4j", "password")); Session session = driver.session() ) { long one = session.run("RETURN 1", Collections.emptyMap()).next().get(0).asLong(); diff --git a/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerTest.java b/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerTest.java index 0d3f04ef570..20cd38dc70c 100644 --- a/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerTest.java +++ b/modules/neo4j/src/test/java/org/testcontainers/containers/Neo4jContainerTest.java @@ -29,17 +29,16 @@ public class Neo4jContainerTest { @Test public void shouldDisableAuthentication() { - try ( + // spotless:off // withoutAuthentication { Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4") .withoutAuthentication() // } + // spotless:on ) { neo4jContainer.start(); - try (Driver driver = getDriver(neo4jContainer); - Session session = driver.session() - ) { + try (Driver driver = getDriver(neo4jContainer); Session session = driver.session()) { long one = session.run("RETURN 1", Collections.emptyMap()).next().get(0).asLong(); assertThat(one).isEqualTo(1L); } @@ -55,10 +54,7 @@ public void shouldCopyDatabase() { // } ) { neo4jContainer.start(); - try ( - Driver driver = getDriver(neo4jContainer); - Session session = driver.session() - ) { + try (Driver driver = getDriver(neo4jContainer); Session session = driver.session()) { Result result = session.run("MATCH (t:Thing) RETURN t"); assertThat(result.list().stream().map(r -> r.get("t").get("name").asString())) .containsExactlyInAnyOrder("Thing", "Thing 2", "Thing 3", "A box"); @@ -68,25 +64,29 @@ public void shouldCopyDatabase() { @Test public void shouldFailOnCopyDatabaseForDefaultNeo4j4Image() { - Assertions.assertThatIllegalArgumentException() - .isThrownBy(() -> new Neo4jContainer<>() - .withDatabase(MountableFile.forClasspathResource("/test-graph.db"))) + Assertions + .assertThatIllegalArgumentException() + .isThrownBy(() -> new Neo4jContainer<>().withDatabase(MountableFile.forClasspathResource("/test-graph.db"))) .withMessage("Copying database folder is not supported for Neo4j instances with version 4.0 or higher."); } @Test public void shouldFailOnCopyDatabaseForCustomNeo4j4Image() { - Assertions.assertThatIllegalArgumentException() - .isThrownBy(() -> new Neo4jContainer<>("neo4j:4.4.1") - .withDatabase(MountableFile.forClasspathResource("/test-graph.db"))) + Assertions + .assertThatIllegalArgumentException() + .isThrownBy(() -> { + new Neo4jContainer<>("neo4j:4.4.1").withDatabase(MountableFile.forClasspathResource("/test-graph.db")); + }) .withMessage("Copying database folder is not supported for Neo4j instances with version 4.0 or higher."); } @Test public void shouldFailOnCopyDatabaseForCustomNonSemverNeo4j4Image() { - Assertions.assertThatIllegalArgumentException() - .isThrownBy(() -> new Neo4jContainer<>("neo4j:latest") - .withDatabase(MountableFile.forClasspathResource("/test-graph.db"))) + Assertions + .assertThatIllegalArgumentException() + .isThrownBy(() -> { + new Neo4jContainer<>("neo4j:latest").withDatabase(MountableFile.forClasspathResource("/test-graph.db")); + }) .withMessage("Copying database folder is not supported for Neo4j instances with version 4.0 or higher."); } @@ -99,10 +99,7 @@ public void shouldCopyPlugins() { // } ) { neo4jContainer.start(); - try ( - Driver driver = getDriver(neo4jContainer); - Session session = driver.session() - ) { + try (Driver driver = getDriver(neo4jContainer); Session session = driver.session()) { assertThatCustomPluginWasCopied(session); } } @@ -117,10 +114,7 @@ public void shouldCopyPlugin() { // } ) { neo4jContainer.start(); - try ( - Driver driver = getDriver(neo4jContainer); - Session session = driver.session() - ) { + try (Driver driver = getDriver(neo4jContainer); Session session = driver.session()) { assertThatCustomPluginWasCopied(session); } } @@ -152,17 +146,16 @@ public void shouldRunEnterprise() { // enterpriseEdition { Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4") .withEnterpriseEdition() - // } + // } .withAdminPassword("Picard123") ) { neo4jContainer.start(); - try ( - Driver driver = getDriver(neo4jContainer); - Session session = driver.session() - ) { + try (Driver driver = getDriver(neo4jContainer); Session session = driver.session()) { String edition = session .run("CALL dbms.components() YIELD edition RETURN edition", Collections.emptyMap()) - .next().get(0).asString(); + .next() + .get(0) + .asString(); assertThat(edition).isEqualTo("enterprise"); } } @@ -178,31 +171,28 @@ public void shouldAddConfigToEnvironment() { assertThat(neo4jContainer.getEnvMap()) .containsEntry("NEO4J_dbms_security_procedures_unrestricted", "apoc.*,algo.*"); - assertThat(neo4jContainer.getEnvMap()) - .containsEntry("NEO4J_dbms_tx__log_rotation_size", "42M"); + assertThat(neo4jContainer.getEnvMap()).containsEntry("NEO4J_dbms_tx__log_rotation_size", "42M"); } @Test public void shouldConfigureSingleLabsPlugin() { - try (Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4") - .withLabsPlugins(Neo4jLabsPlugin.APOC)) { - - + try ( + Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4").withLabsPlugins(Neo4jLabsPlugin.APOC) + ) { // needs to get called explicitly for setup neo4jContainer.configure(); - assertThat(neo4jContainer.getEnvMap()) - .containsEntry("NEO4JLABS_PLUGINS", "[\"apoc\"]"); + assertThat(neo4jContainer.getEnvMap()).containsEntry("NEO4JLABS_PLUGINS", "[\"apoc\"]"); } } @Test public void shouldConfigureMultipleLabsPlugins() { - try( - // configureLabsPlugins { - Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4") - .withLabsPlugins(Neo4jLabsPlugin.APOC, Neo4jLabsPlugin.BLOOM); - // } + try ( + // configureLabsPlugins { + Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4") + .withLabsPlugins(Neo4jLabsPlugin.APOC, Neo4jLabsPlugin.BLOOM); + // } ) { // needs to get called explicitly for setup neo4jContainer.configure(); @@ -214,23 +204,19 @@ public void shouldConfigureMultipleLabsPlugins() { @Test public void shouldConfigureSingleLabsPluginWithString() { - try (Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4") - .withLabsPlugins("myApoc")) { - + try (Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4").withLabsPlugins("myApoc")) { // needs to get called explicitly for setup neo4jContainer.configure(); - assertThat(neo4jContainer.getEnvMap()) - .containsEntry("NEO4JLABS_PLUGINS", "[\"myApoc\"]"); + assertThat(neo4jContainer.getEnvMap()).containsEntry("NEO4JLABS_PLUGINS", "[\"myApoc\"]"); } } @Test public void shouldConfigureMultipleLabsPluginsWithString() { - - try (Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4") - .withLabsPlugins("myApoc", "myBloom")) { - + try ( + Neo4jContainer neo4jContainer = new Neo4jContainer<>("neo4j:4.4").withLabsPlugins("myApoc", "myBloom") + ) { // needs to get called explicitly for setup neo4jContainer.configure(); @@ -240,7 +226,6 @@ public void shouldConfigureMultipleLabsPluginsWithString() { } private static Driver getDriver(Neo4jContainer container) { - AuthToken authToken = AuthTokens.none(); if (container.getAdminPassword() != null) { authToken = AuthTokens.basic("neo4j", container.getAdminPassword()); diff --git a/modules/nginx/src/main/java/org/testcontainers/containers/NginxContainer.java b/modules/nginx/src/main/java/org/testcontainers/containers/NginxContainer.java index 296d82b7997..3e7a2062fd0 100644 --- a/modules/nginx/src/main/java/org/testcontainers/containers/NginxContainer.java +++ b/modules/nginx/src/main/java/org/testcontainers/containers/NginxContainer.java @@ -12,10 +12,14 @@ /** * @author richardnorth */ -public class NginxContainer> extends GenericContainer implements LinkableContainer { +public class NginxContainer> + extends GenericContainer + implements LinkableContainer { private static final int NGINX_DEFAULT_PORT = 80; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("nginx"); + private static final String DEFAULT_TAG = "1.9.4"; /** @@ -32,7 +36,6 @@ public NginxContainer(String dockerImageName) { public NginxContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); addExposedPort(NGINX_DEFAULT_PORT); diff --git a/modules/nginx/src/test/java/org/testcontainers/junit/SimpleNginxTest.java b/modules/nginx/src/test/java/org/testcontainers/junit/SimpleNginxTest.java index e322804bf75..c1ba3d30684 100644 --- a/modules/nginx/src/test/java/org/testcontainers/junit/SimpleNginxTest.java +++ b/modules/nginx/src/test/java/org/testcontainers/junit/SimpleNginxTest.java @@ -12,7 +12,7 @@ import java.net.URL; import java.net.URLConnection; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.rnorth.visibleassertions.VisibleAssertions.*; /** @@ -29,9 +29,10 @@ public class SimpleNginxTest { public NginxContainer nginx = new NginxContainer<>(NGINX_IMAGE) .withCustomContent(tmpDirectory) .waitingFor(new HttpWaitStrategy()); + // } - @SuppressWarnings({"Duplicates", "ResultOfMethodCallIgnored"}) + @SuppressWarnings({ "Duplicates", "ResultOfMethodCallIgnored" }) @BeforeClass public static void setupContent() throws Exception { // addCustomContent { @@ -43,7 +44,8 @@ public static void setupContent() throws Exception { // And "hello world" HTTP file File indexFile = new File(contentFolder, "index.html"); indexFile.deleteOnExit(); - @Cleanup PrintStream printStream = new PrintStream(new FileOutputStream(indexFile)); + @Cleanup + PrintStream printStream = new PrintStream(new FileOutputStream(indexFile)); printStream.println("Hello World!"); // } } @@ -53,7 +55,8 @@ public void testSimple() throws Exception { // getFromNginxServer { URL baseUrl = nginx.getBaseUrl("http", 80); - assertThat("An HTTP GET from the Nginx server returns the index.html from the custom content directory", + assertThat( + "An HTTP GET from the Nginx server returns the index.html from the custom content directory", responseFromNginx(baseUrl), containsString("Hello World!") ); @@ -62,7 +65,8 @@ public void testSimple() throws Exception { private static String responseFromNginx(URL baseUrl) throws IOException { URLConnection urlConnection = baseUrl.openConnection(); - @Cleanup BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); + @Cleanup + BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); return reader.readLine(); } } diff --git a/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainer.java b/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainer.java index 689646f0006..bd5d9aeb7ca 100644 --- a/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainer.java +++ b/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainer.java @@ -1,50 +1,59 @@ package org.testcontainers.containers; -import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.utility.DockerImageName; import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.Future; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.util.Collections.singleton; - public class OracleContainer extends JdbcDatabaseContainer { public static final String NAME = "oracle"; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("gvenzl/oracle-xe"); static final String DEFAULT_TAG = "18.4.0-slim"; + static final String IMAGE = DEFAULT_IMAGE_NAME.getUnversionedPart(); private static final int ORACLE_PORT = 1521; + private static final int APEX_HTTP_PORT = 8080; private static final int DEFAULT_STARTUP_TIMEOUT_SECONDS = 240; + private static final int DEFAULT_CONNECT_TIMEOUT_SECONDS = 120; // Container defaults static final String DEFAULT_DATABASE_NAME = "xepdb1"; + static final String DEFAULT_SID = "xe"; + static final String DEFAULT_SYSTEM_USER = "system"; + static final String DEFAULT_SYS_USER = "sys"; // Test container defaults static final String APP_USER = "test"; + static final String APP_USER_PASSWORD = "test"; // Restricted user and database names private static final List ORACLE_SYSTEM_USERS = Arrays.asList(DEFAULT_SYSTEM_USER, DEFAULT_SYS_USER); private String databaseName = DEFAULT_DATABASE_NAME; + private String username = APP_USER; + private String password = APP_USER_PASSWORD; + private boolean usingSid = false; /** @@ -71,10 +80,11 @@ public OracleContainer(Future dockerImageName) { } private void preconfigure() { - this.waitStrategy = new LogMessageWaitStrategy() - .withRegEx(".*DATABASE IS READY TO USE!.*\\s") - .withTimes(1) - .withStartupTimeout(Duration.of(DEFAULT_STARTUP_TIMEOUT_SECONDS, SECONDS)); + this.waitStrategy = + new LogMessageWaitStrategy() + .withRegEx(".*DATABASE IS READY TO USE!.*\\s") + .withTimes(1) + .withStartupTimeout(Duration.of(DEFAULT_STARTUP_TIMEOUT_SECONDS, ChronoUnit.SECONDS)); withConnectTimeoutSeconds(DEFAULT_CONNECT_TIMEOUT_SECONDS); addExposedPorts(ORACLE_PORT, APEX_HTTP_PORT); @@ -88,7 +98,7 @@ protected void waitUntilContainerStarted() { @NotNull @Override public Set getLivenessCheckPortNumbers() { - return singleton(getMappedPort(ORACLE_PORT)); + return Collections.singleton(getMappedPort(ORACLE_PORT)); } @Override @@ -98,9 +108,9 @@ public String getDriverClassName() { @Override public String getJdbcUrl() { - return isUsingSid() ? - "jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + ":" + getSid() : - "jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + "/" + getDatabaseName(); + return isUsingSid() + ? "jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + ":" + getSid() + : "jdbc:oracle:thin:" + "@" + getHost() + ":" + getOraclePort() + "/" + getDatabaseName(); } @Override @@ -192,7 +202,7 @@ protected void configure() { withEnv("ORACLE_PASSWORD", password); // Only set ORACLE_DATABASE if different than the default. - if(databaseName != DEFAULT_DATABASE_NAME) { + if (databaseName != DEFAULT_DATABASE_NAME) { withEnv("ORACLE_DATABASE", databaseName); } diff --git a/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainerProvider.java b/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainerProvider.java index a298ae23359..f92f0ec40be 100644 --- a/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainerProvider.java +++ b/modules/oracle-xe/src/main/java/org/testcontainers/containers/OracleContainerProvider.java @@ -6,6 +6,7 @@ * Factory for Oracle containers. */ public class OracleContainerProvider extends JdbcDatabaseContainerProvider { + @Override public boolean supports(String databaseType) { return databaseType.equals(OracleContainer.NAME); diff --git a/modules/oracle-xe/src/test/java/org/testcontainers/containers/jdbc/OracleJDBCDriverTest.java b/modules/oracle-xe/src/test/java/org/testcontainers/containers/jdbc/OracleJDBCDriverTest.java index 79dc35deb64..003941f4dfc 100644 --- a/modules/oracle-xe/src/test/java/org/testcontainers/containers/jdbc/OracleJDBCDriverTest.java +++ b/modules/oracle-xe/src/test/java/org/testcontainers/containers/jdbc/OracleJDBCDriverTest.java @@ -4,7 +4,6 @@ import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; -import org.junit.Ignore; import org.junit.Test; import java.sql.ResultSet; @@ -19,18 +18,21 @@ public void testOracleWithNoSpecifiedVersion() throws SQLException { performSimpleTest("jdbc:tc:oracle://hostname/databasename"); } - private void performSimpleTest(String jdbcUrl) throws SQLException { HikariDataSource dataSource = getDataSource(jdbcUrl, 1); - new QueryRunner(dataSource).query("SELECT 1 FROM dual", new ResultSetHandler() { - @Override - public Object handle(ResultSet rs) throws SQLException { - rs.next(); - int resultSetInt = rs.getInt(1); - assertEquals("A basic SELECT query succeeds", 1, resultSetInt); - return true; - } - }); + new QueryRunner(dataSource) + .query( + "SELECT 1 FROM dual", + new ResultSetHandler() { + @Override + public Object handle(ResultSet rs) throws SQLException { + rs.next(); + int resultSetInt = rs.getInt(1); + assertEquals("A basic SELECT query succeeds", 1, resultSetInt); + return true; + } + } + ); dataSource.close(); } diff --git a/modules/oracle-xe/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java b/modules/oracle-xe/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java index 2dd82c437a4..2c514062415 100644 --- a/modules/oracle-xe/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java +++ b/modules/oracle-xe/src/test/java/org/testcontainers/junit/oracle/SimpleOracleTest.java @@ -1,8 +1,5 @@ package org.testcontainers.junit.oracle; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - import org.junit.Test; import org.testcontainers.containers.OracleContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; @@ -11,16 +8,22 @@ import java.sql.ResultSet; import java.sql.SQLException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + public class SimpleOracleTest extends AbstractContainerDatabaseTest { - public static final DockerImageName ORACLE_DOCKER_IMAGE_NAME = DockerImageName.parse("gvenzl/oracle-xe:18.4.0-slim"); + public static final DockerImageName ORACLE_DOCKER_IMAGE_NAME = DockerImageName.parse( + "gvenzl/oracle-xe:18.4.0-slim" + ); - private void runTest(OracleContainer container, String databaseName, String username, String password) throws SQLException { + private void runTest(OracleContainer container, String databaseName, String username, String password) + throws SQLException { //Test config was honored assertEquals(databaseName, container.getDatabaseName()); assertEquals(username, container.getUsername()); assertEquals(password, container.getPassword()); - + //Test we can get a connection container.start(); ResultSet resultSet = performQuery(container, "SELECT 1 FROM dual"); @@ -30,9 +33,7 @@ private void runTest(OracleContainer container, String databaseName, String user @Test public void testDefaultSettings() throws SQLException { - try ( - OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME); - ) { + try (OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME);) { runTest(oracle, "xepdb1", "test", "test"); // Match against the last '/' @@ -43,10 +44,7 @@ public void testDefaultSettings() throws SQLException { @Test public void testPluggableDatabase() throws SQLException { - try ( - OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME) - .withDatabaseName("testDB") - ) { + try (OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME).withDatabaseName("testDB")) { runTest(oracle, "testDB", "test", "test"); } } @@ -76,10 +74,7 @@ public void testCustomUser() throws SQLException { @Test public void testSID() throws SQLException { - try ( - OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME) - .usingSid(); - ) { + try (OracleContainer oracle = new OracleContainer(ORACLE_DOCKER_IMAGE_NAME).usingSid();) { runTest(oracle, "xepdb1", "system", "test"); // Match against the last ':' diff --git a/modules/orientdb/src/main/java/org/testcontainers/containers/OrientDBContainer.java b/modules/orientdb/src/main/java/org/testcontainers/containers/OrientDBContainer.java index a68f55b60ef..2f606475dc0 100644 --- a/modules/orientdb/src/main/java/org/testcontainers/containers/OrientDBContainer.java +++ b/modules/orientdb/src/main/java/org/testcontainers/containers/OrientDBContainer.java @@ -21,25 +21,33 @@ * @author robfrank */ public class OrientDBContainer extends GenericContainer { + private static final Logger LOGGER = LoggerFactory.getLogger(OrientDBContainer.class); private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("orientdb"); + private static final String DEFAULT_TAG = "3.0.24-tp3"; private static final String DEFAULT_USERNAME = "admin"; + private static final String DEFAULT_PASSWORD = "admin"; + private static final String DEFAULT_SERVER_PASSWORD = "root"; private static final String DEFAULT_DATABASE_NAME = "testcontainers"; private static final int DEFAULT_BINARY_PORT = 2424; + private static final int DEFAULT_HTTP_PORT = 2480; private String databaseName; + private String serverPassword; + private Optional scriptPath = Optional.empty(); private OrientDB orientDB; + private ODatabaseSession session; /** @@ -56,13 +64,12 @@ public OrientDBContainer(@NonNull String dockerImageName) { public OrientDBContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); serverPassword = DEFAULT_SERVER_PASSWORD; databaseName = DEFAULT_DATABASE_NAME; - waitStrategy = new LogMessageWaitStrategy().withRegEx(".*Gremlin started correctly.*"); + waitStrategy = new LogMessageWaitStrategy().withRegEx(".*Gremlin started correctly.*"); addExposedPorts(DEFAULT_BINARY_PORT, DEFAULT_HTTP_PORT); } @@ -133,7 +140,9 @@ private void loadScript(String path, ODatabaseSession session) { if (resource == null) { LOGGER.warn("Could not load classpath init script: {}", scriptPath); - throw new RuntimeException("Could not load classpath init script: " + scriptPath + ". Resource not found."); + throw new RuntimeException( + "Could not load classpath init script: " + scriptPath + ". Resource not found." + ); } String script = IOUtils.toString(resource, StandardCharsets.UTF_8); @@ -147,5 +156,4 @@ private void loadScript(String path, ODatabaseSession session) { throw new RuntimeException("Error while executing init script: " + scriptPath, e); } } - } diff --git a/modules/orientdb/src/test/java/org/testcontainers/containers/OrientDBContainerTest.java b/modules/orientdb/src/test/java/org/testcontainers/containers/OrientDBContainerTest.java index 60d7b172436..675218637ce 100644 --- a/modules/orientdb/src/test/java/org/testcontainers/containers/OrientDBContainerTest.java +++ b/modules/orientdb/src/test/java/org/testcontainers/containers/OrientDBContainerTest.java @@ -42,7 +42,6 @@ public void shouldInitializeWithCommands() { @Test public void shouldQueryWithGremlin() { - try (OrientDBContainer container = new OrientDBContainer(ORIENTDB_IMAGE)) { container.start(); @@ -52,17 +51,17 @@ public void shouldQueryWithGremlin() { session.command("INSERT INTO Person set name='john'"); session.command("INSERT INTO Person set name='jane'"); - assertThat(session.execute("gremlin", - "g.V().hasLabel('Person')").stream()).hasSize(2); + assertThat(session.execute("gremlin", "g.V().hasLabel('Person')").stream()).hasSize(2); } } @Test public void shouldInitializeDatabaseFromScript() { - try (OrientDBContainer container = new OrientDBContainer(ORIENTDB_IMAGE) - .withScriptPath("initscript.osql") - .withDatabaseName("persons")) { - + try ( + OrientDBContainer container = new OrientDBContainer(ORIENTDB_IMAGE) + .withScriptPath("initscript.osql") + .withDatabaseName("persons") + ) { container.start(); assertThat(container.getDbUrl()) diff --git a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgisContainerProvider.java b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgisContainerProvider.java index e41a349365c..0c30ebbb246 100644 --- a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgisContainerProvider.java +++ b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgisContainerProvider.java @@ -9,11 +9,16 @@ public class PostgisContainerProvider extends JdbcDatabaseContainerProvider { private static final String NAME = "postgis"; - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("postgis/postgis").asCompatibleSubstituteFor("postgres"); + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName + .parse("postgis/postgis") + .asCompatibleSubstituteFor("postgres"); + private static final String DEFAULT_TAG = "12-3.0"; + public static final String USER_PARAM = "user"; - public static final String PASSWORD_PARAM = "password"; + public static final String PASSWORD_PARAM = "password"; @Override public boolean supports(String databaseType) { diff --git a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainer.java b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainer.java index 741a8c4139a..3b36b61ea77 100644 --- a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainer.java +++ b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainer.java @@ -5,19 +5,21 @@ import org.testcontainers.utility.DockerImageName; import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Collections; import java.util.Set; -import static java.time.temporal.ChronoUnit.SECONDS; -import static java.util.Collections.singleton; - /** * @author richardnorth */ public class PostgreSQLContainer> extends JdbcDatabaseContainer { + public static final String NAME = "postgresql"; + public static final String IMAGE = "postgres"; public static final String DEFAULT_TAG = "9.6.12"; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("postgres"); public static final Integer POSTGRESQL_PORT = 5432; @@ -27,7 +29,9 @@ public class PostgreSQLContainer> extends static final String DEFAULT_PASSWORD = "test"; private String databaseName = "test"; + private String username = "test"; + private String password = "test"; private static final String FSYNC_OFF_OPTION = "fsync=off"; @@ -46,13 +50,13 @@ public PostgreSQLContainer(final String dockerImageName) { public PostgreSQLContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - this.waitStrategy = new LogMessageWaitStrategy() + this.waitStrategy = + new LogMessageWaitStrategy() .withRegEx(".*database system is ready to accept connections.*\\s") .withTimes(2) - .withStartupTimeout(Duration.of(60, SECONDS)); + .withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS)); this.setCommand("postgres", "-c", FSYNC_OFF_OPTION); addExposedPort(POSTGRESQL_PORT); @@ -61,7 +65,7 @@ public PostgreSQLContainer(final DockerImageName dockerImageName) { @NotNull @Override protected Set getLivenessCheckPorts() { - return singleton(getMappedPort(POSTGRESQL_PORT)); + return Collections.singleton(getMappedPort(POSTGRESQL_PORT)); } @Override @@ -81,8 +85,15 @@ public String getDriverClassName() { @Override public String getJdbcUrl() { String additionalUrlParams = constructUrlParameters("?", "&"); - return "jdbc:postgresql://" + getHost() + ":" + getMappedPort(POSTGRESQL_PORT) - + "/" + databaseName + additionalUrlParams; + return ( + "jdbc:postgresql://" + + getHost() + + ":" + + getMappedPort(POSTGRESQL_PORT) + + "/" + + databaseName + + additionalUrlParams + ); } @Override diff --git a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainerProvider.java b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainerProvider.java index 5e7580c75eb..de98885510c 100644 --- a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainerProvider.java +++ b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainerProvider.java @@ -9,6 +9,7 @@ public class PostgreSQLContainerProvider extends JdbcDatabaseContainerProvider { public static final String USER_PARAM = "user"; + public static final String PASSWORD_PARAM = "password"; @Override @@ -30,5 +31,4 @@ public JdbcDatabaseContainer newInstance(String tag) { public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) { return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); } - } diff --git a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainer.java b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainer.java index 88b5497f5d3..d2b933694c7 100644 --- a/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainer.java +++ b/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainer.java @@ -13,7 +13,8 @@ public final class PostgreSQLR2DBCDatabaseContainer implements R2DBCDatabaseCont private final PostgreSQLContainer container; public static ConnectionFactoryOptions getOptions(PostgreSQLContainer container) { - ConnectionFactoryOptions options = ConnectionFactoryOptions.builder() + ConnectionFactoryOptions options = ConnectionFactoryOptions + .builder() .option(ConnectionFactoryOptions.DRIVER, PostgreSQLR2DBCDatabaseContainerProvider.DRIVER) .build(); @@ -22,7 +23,8 @@ public static ConnectionFactoryOptions getOptions(PostgreSQLContainer contain @Override public ConnectionFactoryOptions configure(ConnectionFactoryOptions options) { - return options.mutate() + return options + .mutate() .option(ConnectionFactoryOptions.HOST, container.getHost()) .option(ConnectionFactoryOptions.PORT, container.getMappedPort(PostgreSQLContainer.POSTGRESQL_PORT)) .option(ConnectionFactoryOptions.DATABASE, container.getDatabaseName()) diff --git a/modules/postgresql/src/main/java/org/testcontainers/containers/TimescaleDBContainerProvider.java b/modules/postgresql/src/main/java/org/testcontainers/containers/TimescaleDBContainerProvider.java index c9b81fccfe4..86fcca2c039 100644 --- a/modules/postgresql/src/main/java/org/testcontainers/containers/TimescaleDBContainerProvider.java +++ b/modules/postgresql/src/main/java/org/testcontainers/containers/TimescaleDBContainerProvider.java @@ -11,11 +11,16 @@ public class TimescaleDBContainerProvider extends JdbcDatabaseContainerProvider { private static final String NAME = "timescaledb"; + private static final String DEFAULT_TAG = "2.1.0-pg11"; - private static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("timescale/timescaledb").asCompatibleSubstituteFor("postgres"); + + private static final DockerImageName DEFAULT_IMAGE = DockerImageName + .parse("timescale/timescaledb") + .asCompatibleSubstituteFor("postgres"); + public static final String USER_PARAM = "user"; - public static final String PASSWORD_PARAM = "password"; + public static final String PASSWORD_PARAM = "password"; @Override public boolean supports(String databaseType) { diff --git a/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLConnectionURLTest.java b/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLConnectionURLTest.java index c18f19a109e..3be7685ea27 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLConnectionURLTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLConnectionURLTest.java @@ -16,7 +16,10 @@ public void shouldCorrectlyAppendQueryString() { String connectionUrl = postgres.constructUrlForConnection("?stringtype=unspecified&stringtype=unspecified"); String queryString = connectionUrl.substring(connectionUrl.indexOf('?')); - assertTrue("Query String contains expected params", queryString.contains("?stringtype=unspecified&stringtype=unspecified")); + assertTrue( + "Query String contains expected params", + queryString.contains("?stringtype=unspecified&stringtype=unspecified") + ); assertEquals("Query String starts with '?'", 0, queryString.indexOf('?')); assertFalse("Query String does not contain extra '?'", queryString.substring(1).contains("?")); } @@ -27,7 +30,10 @@ public void shouldCorrectlyAppendQueryStringWhenNoBaseParams() { String connectionUrl = postgres.constructUrlForConnection("?stringtype=unspecified&stringtype=unspecified"); String queryString = connectionUrl.substring(connectionUrl.indexOf('?')); - assertTrue("Query String contains expected params", queryString.contains("?stringtype=unspecified&stringtype=unspecified")); + assertTrue( + "Query String contains expected params", + queryString.contains("?stringtype=unspecified&stringtype=unspecified") + ); assertEquals("Query String starts with '?'", 0, queryString.indexOf('?')); assertFalse("Query String does not contain extra '?'", queryString.substring(1).contains("?")); } @@ -42,11 +48,15 @@ public void shouldReturnOriginalURLWhenEmptyQueryString() { @Test public void shouldRejectInvalidQueryString() { - assertThrows("Fails when invalid query string provided", IllegalArgumentException.class, - () -> new NoParamsUrlPostgreSQLContainer().constructUrlForConnection("stringtype=unspecified")); + assertThrows( + "Fails when invalid query string provided", + IllegalArgumentException.class, + () -> new NoParamsUrlPostgreSQLContainer().constructUrlForConnection("stringtype=unspecified") + ); } static class FixedJdbcUrlPostgreSQLContainer extends PostgreSQLContainer { + public FixedJdbcUrlPostgreSQLContainer() { super(PostgreSQLTestImages.POSTGRES_TEST_IMAGE); } @@ -63,6 +73,7 @@ public Integer getMappedPort(int originalPort) { } static class NoParamsUrlPostgreSQLContainer extends PostgreSQLContainer { + public NoParamsUrlPostgreSQLContainer() { super(PostgreSQLTestImages.POSTGRES_TEST_IMAGE); } diff --git a/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainerTest.java b/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainerTest.java index 46e439aaf66..fb503bfd659 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainerTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/containers/PostgreSQLR2DBCDatabaseContainerTest.java @@ -13,11 +13,13 @@ protected PostgreSQLContainer createContainer() { @Override protected ConnectionFactoryOptions getOptions(PostgreSQLContainer container) { + // spotless:off // get_options { ConnectionFactoryOptions options = PostgreSQLR2DBCDatabaseContainer.getOptions( container ); // } + // spotless:on return options; } diff --git a/modules/postgresql/src/test/java/org/testcontainers/containers/TimescaleDBContainerTest.java b/modules/postgresql/src/test/java/org/testcontainers/containers/TimescaleDBContainerTest.java index f3c73a4111b..74d60b2d32d 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/containers/TimescaleDBContainerTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/containers/TimescaleDBContainerTest.java @@ -24,10 +24,17 @@ public void testSimple() throws SQLException { @Test public void testCommandOverride() throws SQLException { - try (GenericContainer postgres = new TimescaleDBContainerProvider().newInstance().withCommand("postgres -c max_connections=42")) { + try ( + GenericContainer postgres = new TimescaleDBContainerProvider() + .newInstance() + .withCommand("postgres -c max_connections=42") + ) { postgres.start(); - ResultSet resultSet = performQuery((JdbcDatabaseContainer) postgres, "SELECT current_setting('max_connections')"); + ResultSet resultSet = performQuery( + (JdbcDatabaseContainer) postgres, + "SELECT current_setting('max_connections')" + ); String result = resultSet.getString(1); assertEquals("max_connections should be overriden", "42", result); } @@ -35,10 +42,18 @@ public void testCommandOverride() throws SQLException { @Test public void testUnsetCommand() throws SQLException { - try (GenericContainer postgres = new TimescaleDBContainerProvider().newInstance().withCommand("postgres -c max_connections=42").withCommand()) { + try ( + GenericContainer postgres = new TimescaleDBContainerProvider() + .newInstance() + .withCommand("postgres -c max_connections=42") + .withCommand() + ) { postgres.start(); - ResultSet resultSet = performQuery((JdbcDatabaseContainer) postgres, "SELECT current_setting('max_connections')"); + ResultSet resultSet = performQuery( + (JdbcDatabaseContainer) postgres, + "SELECT current_setting('max_connections')" + ); String result = resultSet.getString(1); assertNotEquals("max_connections should not be overriden", "42", result); } @@ -46,7 +61,11 @@ public void testUnsetCommand() throws SQLException { @Test public void testExplicitInitScript() throws SQLException { - try (JdbcDatabaseContainer postgres = new TimescaleDBContainerProvider().newInstance().withInitScript("somepath/init_timescaledb.sql")) { + try ( + JdbcDatabaseContainer postgres = new TimescaleDBContainerProvider() + .newInstance() + .withInitScript("somepath/init_timescaledb.sql") + ) { postgres.start(); ResultSet resultSet = performQuery(postgres, "SELECT foo FROM bar"); diff --git a/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverShutdownTest.java b/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverShutdownTest.java index 9e3e0b03413..5acbd875c23 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverShutdownTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverShutdownTest.java @@ -19,6 +19,7 @@ * TODO: Move to the jdbc module and either (a) implement a barebones {@link org.testcontainers.containers.JdbcDatabaseContainerProvider} for testing, or (b) refactor into a unit test. */ public class DatabaseDriverShutdownTest { + @AfterClass public static void testCleanup() { ContainerDatabaseDriver.killContainers(); diff --git a/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverTmpfsTest.java b/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverTmpfsTest.java index a2b1fd5da8b..4c8d6afeef0 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverTmpfsTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/jdbc/DatabaseDriverTmpfsTest.java @@ -22,7 +22,6 @@ public class DatabaseDriverTmpfsTest { public void testDatabaseHasTmpFsViaConnectionString() throws Exception { final String jdbcUrl = "jdbc:tc:postgresql:9.6.8://hostname/databasename?TC_TMPFS=/testtmpfs:rw"; try (Connection ignored = DriverManager.getConnection(jdbcUrl)) { - JdbcDatabaseContainer container = ContainerDatabaseDriver.getContainer(jdbcUrl); // check file doesn't exist String path = "/testtmpfs/test.file"; diff --git a/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgis/PostgisJDBCDriverTest.java b/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgis/PostgisJDBCDriverTest.java index b1d01441016..abc0a3b76bc 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgis/PostgisJDBCDriverTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgis/PostgisJDBCDriverTest.java @@ -4,19 +4,25 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class PostgisJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:postgis://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)}, - {"jdbc:tc:postgis:9.6-2.5://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)}, - }); + return Arrays.asList( + new Object[][] { + { + "jdbc:tc:postgis://hostname/databasename?user=someuser&password=somepwd", + EnumSet.of(Options.JDBCParams), + }, + { + "jdbc:tc:postgis:9.6-2.5://hostname/databasename?user=someuser&password=somepwd", + EnumSet.of(Options.JDBCParams), + }, + } + ); } } diff --git a/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgresql/PostgreSQLJDBCDriverTest.java b/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgresql/PostgreSQLJDBCDriverTest.java index c63eb9ffb9d..d42f17f3ec2 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgresql/PostgreSQLJDBCDriverTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/jdbc/postgresql/PostgreSQLJDBCDriverTest.java @@ -4,18 +4,21 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class PostgreSQLJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:postgresql:9.6.8://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)}, - }); + return Arrays.asList( + new Object[][] { + { + "jdbc:tc:postgresql:9.6.8://hostname/databasename?user=someuser&password=somepwd", + EnumSet.of(Options.JDBCParams), + }, + } + ); } } diff --git a/modules/postgresql/src/test/java/org/testcontainers/jdbc/timescaledb/TimescaleDBJDBCDriverTest.java b/modules/postgresql/src/test/java/org/testcontainers/jdbc/timescaledb/TimescaleDBJDBCDriverTest.java index 8a6eaa3d04b..2a50b46c901 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/jdbc/timescaledb/TimescaleDBJDBCDriverTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/jdbc/timescaledb/TimescaleDBJDBCDriverTest.java @@ -4,19 +4,25 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class TimescaleDBJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:timescaledb://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)}, - {"jdbc:tc:timescaledb:2.1.0-pg13://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)}, - }); + return Arrays.asList( + new Object[][] { + { + "jdbc:tc:timescaledb://hostname/databasename?user=someuser&password=somepwd", + EnumSet.of(Options.JDBCParams), + }, + { + "jdbc:tc:timescaledb:2.1.0-pg13://hostname/databasename?user=someuser&password=somepwd", + EnumSet.of(Options.JDBCParams), + }, + } + ); } } diff --git a/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/CustomizablePostgreSQLTest.java b/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/CustomizablePostgreSQLTest.java index 8fd523434dd..1b256c0fd6b 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/CustomizablePostgreSQLTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/CustomizablePostgreSQLTest.java @@ -14,17 +14,21 @@ * @author richardnorth */ public class CustomizablePostgreSQLTest extends AbstractContainerDatabaseTest { + private static final String DB_NAME = "foo"; + private static final String USER = "bar"; + private static final String PWD = "baz"; @Test public void testSimple() throws SQLException { - try (PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE) + try ( + PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE) .withDatabaseName(DB_NAME) .withUsername(USER) - .withPassword(PWD)) { - + .withPassword(PWD) + ) { postgres.start(); ResultSet resultSet = performQuery(postgres, "SELECT 1"); diff --git a/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/SimplePostgreSQLTest.java b/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/SimplePostgreSQLTest.java index 95e1fdf10fd..2a0dd351ad6 100644 --- a/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/SimplePostgreSQLTest.java +++ b/modules/postgresql/src/test/java/org/testcontainers/junit/postgresql/SimplePostgreSQLTest.java @@ -1,6 +1,7 @@ package org.testcontainers.junit.postgresql; import org.junit.Test; +import org.testcontainers.PostgreSQLTestImages; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.db.AbstractContainerDatabaseTest; @@ -9,14 +10,12 @@ import java.util.logging.Level; import java.util.logging.LogManager; -import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertThat; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertNotEquals; -import static org.testcontainers.PostgreSQLTestImages.POSTGRES_TEST_IMAGE; public class SimplePostgreSQLTest extends AbstractContainerDatabaseTest { - static { // Postgres JDBC driver uses JUL; disable it to avoid annoying, irrelevant, stderr logs during connection testing LogManager.getLogManager().getLogger("").setLevel(Level.OFF); @@ -24,7 +23,7 @@ public class SimplePostgreSQLTest extends AbstractContainerDatabaseTest { @Test public void testSimple() throws SQLException { - try (PostgreSQLContainer postgres = new PostgreSQLContainer<>(POSTGRES_TEST_IMAGE)) { + try (PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE)) { postgres.start(); ResultSet resultSet = performQuery(postgres, "SELECT 1"); @@ -35,7 +34,10 @@ public void testSimple() throws SQLException { @Test public void testCommandOverride() throws SQLException { - try (PostgreSQLContainer postgres = new PostgreSQLContainer<>(POSTGRES_TEST_IMAGE).withCommand("postgres -c max_connections=42")) { + try ( + PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE) + .withCommand("postgres -c max_connections=42") + ) { postgres.start(); ResultSet resultSet = performQuery(postgres, "SELECT current_setting('max_connections')"); @@ -46,7 +48,11 @@ public void testCommandOverride() throws SQLException { @Test public void testUnsetCommand() throws SQLException { - try (PostgreSQLContainer postgres = new PostgreSQLContainer<>(POSTGRES_TEST_IMAGE).withCommand("postgres -c max_connections=42").withCommand()) { + try ( + PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE) + .withCommand("postgres -c max_connections=42") + .withCommand() + ) { postgres.start(); ResultSet resultSet = performQuery(postgres, "SELECT current_setting('max_connections')"); @@ -57,7 +63,10 @@ public void testUnsetCommand() throws SQLException { @Test public void testExplicitInitScript() throws SQLException { - try (PostgreSQLContainer postgres = new PostgreSQLContainer<>(POSTGRES_TEST_IMAGE).withInitScript("somepath/init_postgresql.sql")) { + try ( + PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE) + .withInitScript("somepath/init_postgresql.sql") + ) { postgres.start(); ResultSet resultSet = performQuery(postgres, "SELECT foo FROM bar"); @@ -69,9 +78,10 @@ public void testExplicitInitScript() throws SQLException { @Test public void testWithAdditionalUrlParamInJdbcUrl() { - try (PostgreSQLContainer postgres = new PostgreSQLContainer<>(POSTGRES_TEST_IMAGE) - .withUrlParam("charSet", "UNICODE")) { - + try ( + PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLTestImages.POSTGRES_TEST_IMAGE) + .withUrlParam("charSet", "UNICODE") + ) { postgres.start(); String jdbcUrl = postgres.getJdbcUrl(); assertThat(jdbcUrl, containsString("?")); diff --git a/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java b/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java index 30d77c1a469..e73f6cc0f6b 100644 --- a/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java +++ b/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java @@ -1,5 +1,6 @@ package org.testcontainers.containers; +import com.google.common.base.Strings; import org.jetbrains.annotations.NotNull; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.utility.DockerImageName; @@ -7,26 +8,28 @@ import java.sql.Connection; import java.sql.SQLException; import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.HashSet; import java.util.Set; -import static com.google.common.base.Strings.nullToEmpty; -import static java.lang.String.format; -import static java.time.temporal.ChronoUnit.SECONDS; - /** * @deprecated Use {@code TrinoContainer} instead. */ @Deprecated public class PrestoContainer> extends JdbcDatabaseContainer { + public static final String NAME = "presto"; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("ghcr.io/trinodb/presto"); + public static final String IMAGE = "ghcr.io/trinodb/presto"; + public static final String DEFAULT_TAG = "344"; public static final Integer PRESTO_PORT = 8080; private String username = "test"; + private String catalog = null; /** @@ -43,12 +46,12 @@ public PrestoContainer(final String dockerImageName) { public PrestoContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - this.waitStrategy = new LogMessageWaitStrategy() - .withRegEx(".*======== SERVER STARTED ========.*") - .withStartupTimeout(Duration.of(60, SECONDS)); + this.waitStrategy = + new LogMessageWaitStrategy() + .withRegEx(".*======== SERVER STARTED ========.*") + .withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS)); addExposedPort(PRESTO_PORT); } @@ -66,7 +69,12 @@ public String getDriverClassName() { @Override public String getJdbcUrl() { - return format("jdbc:presto://%s:%s/%s", getHost(), getMappedPort(PRESTO_PORT), nullToEmpty(catalog)); + return String.format( + "jdbc:presto://%s:%s/%s", + getHost(), + getMappedPort(PRESTO_PORT), + Strings.nullToEmpty(catalog) + ); } @Override diff --git a/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainerProvider.java b/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainerProvider.java index 8408aab4517..f37efb9438e 100644 --- a/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainerProvider.java +++ b/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainerProvider.java @@ -9,6 +9,7 @@ public class PrestoContainerProvider extends JdbcDatabaseContainerProvider { public static final String USER_PARAM = "user"; + public static final String PASSWORD_PARAM = "password"; @Override @@ -30,5 +31,4 @@ public JdbcDatabaseContainer newInstance(String tag) { public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) { return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM); } - } diff --git a/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java b/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java index d5a4d9587a6..a54108ea1a2 100644 --- a/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java +++ b/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java @@ -3,7 +3,6 @@ import org.junit.Assert; import org.junit.Test; import org.testcontainers.PrestoTestImages; -import org.testcontainers.utility.DockerImageName; import java.sql.Connection; import java.sql.DriverManager; @@ -14,8 +13,6 @@ import java.util.Arrays; import java.util.List; -import static java.lang.Integer.parseInt; -import static java.lang.String.format; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -29,9 +26,11 @@ public class PrestoContainerTest { public void testSimple() throws Exception { try (PrestoContainer prestoSql = new PrestoContainer<>(PrestoTestImages.PRESTO_TEST_IMAGE)) { prestoSql.start(); - try (Connection connection = prestoSql.createConnection(); - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes")) { + try ( + Connection connection = prestoSql.createConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes") + ) { assertTrue("No result", resultSet.next()); assertEquals("Presto version", PrestoContainer.DEFAULT_TAG, resultSet.getString("node_version")); } @@ -40,13 +39,21 @@ public void testSimple() throws Exception { @Test public void testSpecificVersion() throws Exception { - try (PrestoContainer prestoSql = new PrestoContainer<>(PrestoTestImages.PRESTO_PREVIOUS_VERSION_TEST_IMAGE)) { + try ( + PrestoContainer prestoSql = new PrestoContainer<>(PrestoTestImages.PRESTO_PREVIOUS_VERSION_TEST_IMAGE) + ) { prestoSql.start(); - try (Connection connection = prestoSql.createConnection(); - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes")) { + try ( + Connection connection = prestoSql.createConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes") + ) { assertTrue("No result", resultSet.next()); - assertEquals("Presto version", PrestoTestImages.PRESTO_PREVIOUS_VERSION_TEST_IMAGE.getVersionPart(), resultSet.getString("node_version")); + assertEquals( + "Presto version", + PrestoTestImages.PRESTO_PREVIOUS_VERSION_TEST_IMAGE.getVersionPart(), + resultSet.getString("node_version") + ); } } } @@ -55,18 +62,26 @@ public void testSpecificVersion() throws Exception { public void testQueryMemoryAndTpch() throws SQLException { try (PrestoContainer prestoSql = new PrestoContainer<>(PrestoTestImages.PRESTO_TEST_IMAGE)) { prestoSql.start(); - try (Connection connection = prestoSql.createConnection(); - Statement statement = connection.createStatement()) { + try ( + Connection connection = prestoSql.createConnection(); + Statement statement = connection.createStatement() + ) { // Prepare data - statement.execute("CREATE TABLE memory.default.table_with_array AS SELECT 1 id, ARRAY[1, 42, 2, 42, 4, 42] my_array"); + statement.execute( + "CREATE TABLE memory.default.table_with_array AS SELECT 1 id, ARRAY[1, 42, 2, 42, 4, 42] my_array" + ); // Query Presto using newly created table and a builtin connector - try (ResultSet resultSet = statement.executeQuery("" + - "SELECT nationkey, element " + - "FROM tpch.tiny.nation " + - "JOIN memory.default.table_with_array twa ON nationkey = twa.id " + - "LEFT JOIN UNNEST(my_array) a(element) ON true " + - "ORDER BY element OFFSET 1 FETCH NEXT 3 ROWS WITH TIES ")) { + try ( + ResultSet resultSet = statement.executeQuery( + "" + + "SELECT nationkey, element " + + "FROM tpch.tiny.nation " + + "JOIN memory.default.table_with_array twa ON nationkey = twa.id " + + "LEFT JOIN UNNEST(my_array) a(element) ON true " + + "ORDER BY element OFFSET 1 FETCH NEXT 3 ROWS WITH TIES " + ) + ) { List actualElements = new ArrayList<>(); while (resultSet.next()) { actualElements.add(resultSet.getInt("element")); @@ -82,9 +97,11 @@ public void testInitScript() throws Exception { try (PrestoContainer prestoSql = new PrestoContainer<>(PrestoTestImages.PRESTO_TEST_IMAGE)) { prestoSql.withInitScript("initial.sql"); prestoSql.start(); - try (Connection connection = prestoSql.createConnection(); - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT a FROM memory.default.test_table")) { + try ( + Connection connection = prestoSql.createConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT a FROM memory.default.test_table") + ) { assertTrue("No result", resultSet.next()); assertEquals("Value", 12345678909324L, resultSet.getObject("a")); assertFalse("Too many result", resultSet.next()); @@ -94,19 +111,38 @@ public void testInitScript() throws Exception { @Test public void testTcJdbcUri() throws Exception { - try (Connection connection = DriverManager.getConnection(format("jdbc:tc:presto:%s://hostname/", PrestoContainer.DEFAULT_TAG))) { + try ( + Connection connection = DriverManager.getConnection( + String.format("jdbc:tc:presto:%s://hostname/", PrestoContainer.DEFAULT_TAG) + ) + ) { // Verify metadata with tc: JDBC connection URI - assertEquals(connection.getMetaData().getDatabaseMajorVersion(), parseInt(PrestoContainer.DEFAULT_TAG)); + assertEquals( + connection.getMetaData().getDatabaseMajorVersion(), + Integer.parseInt(PrestoContainer.DEFAULT_TAG) + ); // Verify transactions with tc: JDBC connection URI assertTrue("Is autocommit", connection.getAutoCommit()); connection.setAutoCommit(false); assertFalse("Is autocommit", connection.getAutoCommit()); - assertEquals("Transaction isolation", Connection.TRANSACTION_READ_UNCOMMITTED, connection.getTransactionIsolation()); + assertEquals( + "Transaction isolation", + Connection.TRANSACTION_READ_UNCOMMITTED, + connection.getTransactionIsolation() + ); try (Statement statement = connection.createStatement()) { - assertEquals("Update result", 0, statement.executeUpdate("CREATE TABLE memory.default.test_tc(a bigint)")); - try (ResultSet resultSet = statement.executeQuery("SELECT sum(cast(node_version AS bigint)) AS v FROM system.runtime.nodes")) { + assertEquals( + "Update result", + 0, + statement.executeUpdate("CREATE TABLE memory.default.test_tc(a bigint)") + ); + try ( + ResultSet resultSet = statement.executeQuery( + "SELECT sum(cast(node_version AS bigint)) AS v FROM system.runtime.nodes" + ) + ) { assertTrue(resultSet.next()); assertEquals(PrestoContainer.DEFAULT_TAG, resultSet.getString("v")); assertFalse(resultSet.next()); @@ -117,7 +153,11 @@ public void testTcJdbcUri() throws Exception { } connection.setAutoCommit(true); assertTrue("Is autocommit", connection.getAutoCommit()); - assertEquals("Transaction isolation should be retained", Connection.TRANSACTION_READ_UNCOMMITTED, connection.getTransactionIsolation()); + assertEquals( + "Transaction isolation should be retained", + Connection.TRANSACTION_READ_UNCOMMITTED, + connection.getTransactionIsolation() + ); } } } diff --git a/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java b/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java index d1a64c92aaa..9c5dd712104 100644 --- a/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java +++ b/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java @@ -4,18 +4,18 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class PrestoJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:presto:344://hostname/", EnumSet.of(Options.PmdKnownBroken)}, - }); + return Arrays.asList( + new Object[][] { // + { "jdbc:tc:presto:344://hostname/", EnumSet.of(Options.PmdKnownBroken) }, + } + ); } } diff --git a/modules/pulsar/src/main/java/org/testcontainers/containers/PulsarContainer.java b/modules/pulsar/src/main/java/org/testcontainers/containers/PulsarContainer.java index b3c836b56a5..9b14e90d736 100644 --- a/modules/pulsar/src/main/java/org/testcontainers/containers/PulsarContainer.java +++ b/modules/pulsar/src/main/java/org/testcontainers/containers/PulsarContainer.java @@ -10,10 +10,13 @@ public class PulsarContainer extends GenericContainer { public static final int BROKER_PORT = 6650; + public static final int BROKER_HTTP_PORT = 8080; + public static final String METRICS_ENDPOINT = "/metrics"; private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("apachepulsar/pulsar"); + @Deprecated private static final String DEFAULT_TAG = "2.2.0"; @@ -37,7 +40,6 @@ public PulsarContainer(String pulsarVersion) { public PulsarContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DockerImageName.parse("apachepulsar/pulsar")); withExposedPorts(BROKER_PORT, BROKER_HTTP_PORT); diff --git a/modules/pulsar/src/test/java/org/testcontainers/containers/PulsarContainerTest.java b/modules/pulsar/src/test/java/org/testcontainers/containers/PulsarContainerTest.java index f2354d98ef7..6d739dfbf98 100644 --- a/modules/pulsar/src/test/java/org/testcontainers/containers/PulsarContainerTest.java +++ b/modules/pulsar/src/test/java/org/testcontainers/containers/PulsarContainerTest.java @@ -18,6 +18,7 @@ public class PulsarContainerTest { public static final String TEST_TOPIC = "test_topic"; + private static final DockerImageName PULSAR_IMAGE = DockerImageName.parse("apachepulsar/pulsar:2.2.0"); @Test @@ -33,9 +34,7 @@ public void shouldNotEnableFunctionsWorkerByDefault() throws Exception { try (PulsarContainer pulsar = new PulsarContainer("2.5.1")) { pulsar.start(); - PulsarAdmin pulsarAdmin = PulsarAdmin.builder() - .serviceHttpUrl(pulsar.getHttpServiceUrl()) - .build(); + PulsarAdmin pulsarAdmin = PulsarAdmin.builder().serviceHttpUrl(pulsar.getHttpServiceUrl()).build(); assertThatThrownBy(() -> pulsarAdmin.functions().getFunctions("public", "default")) .isInstanceOf(PulsarAdminException.class); @@ -47,36 +46,23 @@ public void shouldWaitForFunctionsWorkerStarted() throws Exception { try (PulsarContainer pulsar = new PulsarContainer("2.5.1").withFunctionsWorker()) { pulsar.start(); - PulsarAdmin pulsarAdmin = PulsarAdmin.builder() - .serviceHttpUrl(pulsar.getHttpServiceUrl()) - .build(); + PulsarAdmin pulsarAdmin = PulsarAdmin.builder().serviceHttpUrl(pulsar.getHttpServiceUrl()).build(); assertThat(pulsarAdmin.functions().getFunctions("public", "default")).hasSize(0); } } protected void testPulsarFunctionality(String pulsarBrokerUrl) throws Exception { - try ( - PulsarClient client = PulsarClient.builder() - .serviceUrl(pulsarBrokerUrl) - .build(); - Consumer consumer = client.newConsumer() - .topic(TEST_TOPIC) - .subscriptionName("test-subs") - .subscribe(); - Producer producer = client.newProducer() - .topic(TEST_TOPIC) - .create() + PulsarClient client = PulsarClient.builder().serviceUrl(pulsarBrokerUrl).build(); + Consumer consumer = client.newConsumer().topic(TEST_TOPIC).subscriptionName("test-subs").subscribe(); + Producer producer = client.newProducer().topic(TEST_TOPIC).create() ) { - producer.send("test containers".getBytes()); CompletableFuture future = consumer.receiveAsync(); Message message = future.get(5, TimeUnit.SECONDS); - assertThat(new String(message.getData())) - .isEqualTo("test containers"); + assertThat(new String(message.getData())).isEqualTo("test containers"); } } - } diff --git a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/CancellableSubscription.java b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/CancellableSubscription.java index e64d19a9f49..3f4fd7e4b1e 100644 --- a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/CancellableSubscription.java +++ b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/CancellableSubscription.java @@ -9,8 +9,7 @@ class CancellableSubscription implements Subscription { private final AtomicBoolean cancelled = new AtomicBoolean(); @Override - public void request(long n) { - } + public void request(long n) {} @Override public void cancel() { diff --git a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/ConnectionPublisher.java b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/ConnectionPublisher.java index 489d545429d..d1b1c0e43f3 100644 --- a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/ConnectionPublisher.java +++ b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/ConnectionPublisher.java @@ -56,8 +56,8 @@ synchronized void transitionTo(SubscriptionState newState) { } abstract class SubscriptionState implements Subscription { - void enter() { - } + + void enter() {} } class WaitRequestSubscriptionState extends SubscriptionState { @@ -68,8 +68,7 @@ public void request(long n) { } @Override - public void cancel() { - } + public void cancel() {} } class WaitFutureCompletionSubscriptionState extends SubscriptionState { @@ -93,8 +92,7 @@ void enter() { } @Override - public void request(long n) { - } + public void request(long n) {} @Override public void cancel() { diff --git a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/EmptySubscription.java b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/EmptySubscription.java index 7828d121c6f..5cd2ffbd894 100644 --- a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/EmptySubscription.java +++ b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/EmptySubscription.java @@ -6,12 +6,8 @@ enum EmptySubscription implements Subscription { INSTANCE; @Override - public void request(long n) { - - } + public void request(long n) {} @Override - public void cancel() { - - } + public void cancel() {} } diff --git a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/Hidden.java b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/Hidden.java index f642a60d67c..1eecb22a2c7 100644 --- a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/Hidden.java +++ b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/Hidden.java @@ -52,7 +52,8 @@ private ConnectionFactoryOptions removeProxying(ConnectionFactoryOptions options // when protocol does NOT contain COLON, the length becomes 1 String protocolDelegate = protocols.length == 2 ? protocols[1] : ""; - return ConnectionFactoryOptions.builder() + return ConnectionFactoryOptions + .builder() .from(options) .option(ConnectionFactoryOptions.DRIVER, driverDelegate) .option(ConnectionFactoryOptions.PROTOCOL, protocolDelegate) @@ -68,6 +69,5 @@ public boolean supports(ConnectionFactoryOptions options) { public String getDriver() { return DRIVER; } - } } diff --git a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainer.java b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainer.java index a303cbafff8..8bf0401fe69 100644 --- a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainer.java +++ b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainer.java @@ -4,6 +4,5 @@ import org.testcontainers.lifecycle.Startable; public interface R2DBCDatabaseContainer extends Startable { - ConnectionFactoryOptions configure(ConnectionFactoryOptions options); } diff --git a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainerProvider.java b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainerProvider.java index 287407dc15e..9d3efc17ac7 100644 --- a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainerProvider.java +++ b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/R2DBCDatabaseContainerProvider.java @@ -9,7 +9,6 @@ import javax.annotation.Nullable; public interface R2DBCDatabaseContainerProvider { - Option REUSABLE_OPTION = Option.valueOf("TC_REUSABLE"); Option IMAGE_TAG_OPTION = Option.valueOf("TC_IMAGE_TAG"); diff --git a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactory.java b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactory.java index 691775a94f8..bada076eec9 100644 --- a/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactory.java +++ b/modules/r2dbc/src/main/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactory.java @@ -36,34 +36,36 @@ class TestcontainersR2DBCConnectionFactory implements ConnectionFactory, Closeab TestcontainersR2DBCConnectionFactory(ConnectionFactoryOptions options) { this.options = options; - containerProvider = StreamSupport.stream(ServiceLoader.load(R2DBCDatabaseContainerProvider.class).spliterator(), false) - .filter(it -> it.supports(options)) - .findAny() - .orElseThrow(() -> new IllegalArgumentException("Missing provider for " + options)); + containerProvider = + StreamSupport + .stream(ServiceLoader.load(R2DBCDatabaseContainerProvider.class).spliterator(), false) + .filter(it -> it.supports(options)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException("Missing provider for " + options)); } @Override public Publisher create() { - return new ConnectionPublisher( - () -> { - if (future == null) { - synchronized (this) { - if (future == null) { - future = CompletableFuture.supplyAsync(() -> { - R2DBCDatabaseContainer container = containerProvider.createContainer(options); - container.start(); - return container; - }, EXECUTOR); - } + return new ConnectionPublisher(() -> { + if (future == null) { + synchronized (this) { + if (future == null) { + future = + CompletableFuture.supplyAsync( + () -> { + R2DBCDatabaseContainer container = containerProvider.createContainer(options); + container.start(); + return container; + }, + EXECUTOR + ); } } - return future.thenApply(it -> { - return ConnectionFactories.find( - it.configure(options) - ); - }); } - ); + return future.thenApply(it -> { + return ConnectionFactories.find(it.configure(options)); + }); + }); } @Override @@ -99,5 +101,4 @@ public Publisher close() { } }; } - } diff --git a/modules/r2dbc/src/test/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactoryTest.java b/modules/r2dbc/src/test/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactoryTest.java index 6fad93f0e2a..3772e6d49a6 100644 --- a/modules/r2dbc/src/test/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactoryTest.java +++ b/modules/r2dbc/src/test/java/org/testcontainers/r2dbc/TestcontainersR2DBCConnectionFactoryTest.java @@ -48,16 +48,15 @@ public void reusesUntilConnectionFactoryIsClosed() { assertThat(updated).isEqualTo(1); - Flux select = Flux - .usingWhen( - Flux.defer(connectionFactory::create), - connection -> { - return Flux - .from(connection.createStatement("SELECT COUNT(*) FROM test").execute()) - .flatMap(it -> it.map((row, meta) -> (Long) row.get(0))); - }, - Connection::close - ); + Flux select = Flux.usingWhen( + Flux.defer(connectionFactory::create), + connection -> { + return Flux + .from(connection.createStatement("SELECT COUNT(*) FROM test").execute()) + .flatMap(it -> it.map((row, meta) -> (Long) row.get(0))); + }, + Connection::close + ); Long rows = select.blockFirst(); diff --git a/modules/r2dbc/src/testFixtures/java/org/testcontainers/r2dbc/AbstractR2DBCDatabaseContainerTest.java b/modules/r2dbc/src/testFixtures/java/org/testcontainers/r2dbc/AbstractR2DBCDatabaseContainerTest.java index c21c7078410..63603379e40 100644 --- a/modules/r2dbc/src/testFixtures/java/org/testcontainers/r2dbc/AbstractR2DBCDatabaseContainerTest.java +++ b/modules/r2dbc/src/testFixtures/java/org/testcontainers/r2dbc/AbstractR2DBCDatabaseContainerTest.java @@ -60,9 +60,7 @@ protected void runTestQuery(ConnectionFactory connectionFactory) { .flatMap(it -> it.map((row, meta) -> (Number) row.get(0))) .blockFirst(); - assertThat(result) - .isNotNull() - .returns(expected, Number::intValue); + assertThat(result).isNotNull().returns(expected, Number::intValue); } finally { if (connectionFactory instanceof Closeable) { Mono.from(((Closeable) connectionFactory).close()).block(); diff --git a/modules/rabbitmq/src/main/java/org/testcontainers/containers/RabbitMQContainer.java b/modules/rabbitmq/src/main/java/org/testcontainers/containers/RabbitMQContainer.java index f5c63a267a9..c13dfdf1a24 100644 --- a/modules/rabbitmq/src/main/java/org/testcontainers/containers/RabbitMQContainer.java +++ b/modules/rabbitmq/src/main/java/org/testcontainers/containers/RabbitMQContainer.java @@ -11,13 +11,11 @@ import java.io.IOException; import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; -import static java.lang.String.join; -import static java.util.Arrays.asList; - /** * Testcontainer for RabbitMQ. * @@ -29,15 +27,21 @@ public class RabbitMQContainer extends GenericContainer { * The image defaults to the official RabbitmQ image: RabbitMQ. */ private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("rabbitmq"); + private static final String DEFAULT_TAG = "3.7.25-management-alpine"; private static final int DEFAULT_AMQP_PORT = 5672; + private static final int DEFAULT_AMQPS_PORT = 5671; + private static final int DEFAULT_HTTPS_PORT = 15671; + private static final int DEFAULT_HTTP_PORT = 15672; private String adminPassword = "guest"; + private String adminUsername = "guest"; + private final List> values = new ArrayList<>(); /** @@ -60,14 +64,12 @@ public RabbitMQContainer(String dockerImageName) { public RabbitMQContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); addExposedPorts(DEFAULT_AMQP_PORT, DEFAULT_AMQPS_PORT, DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT); - this.waitStrategy = Wait. - forLogMessage(".*Server startup complete.*", 1) - .withStartupTimeout(Duration.ofSeconds(60)); + this.waitStrategy = + Wait.forLogMessage(".*Server startup complete.*", 1).withStartupTimeout(Duration.ofSeconds(60)); } @Override @@ -79,7 +81,6 @@ protected void configure() { @Override protected void containerIsStarted(InspectContainerResponse containerInfo) { - values.forEach(command -> { try { ExecResult execResult = execInContainer(command.toArray(new String[0])); @@ -159,257 +160,394 @@ public RabbitMQContainer withAdminPassword(final String adminPassword) { } public enum SslVerification { - VERIFY_NONE("verify_none"), VERIFY_PEER("verify_peer"); + VERIFY_NONE("verify_none"), + VERIFY_PEER("verify_peer"); SslVerification(String value) { this.value = value; } - private final String value; + private final String value; } public RabbitMQContainer withSSL( - final MountableFile keyFile, - final MountableFile certFile, - final MountableFile caFile, - final SslVerification verify, - boolean failIfNoCert, - int verificationDepth) { - + final MountableFile keyFile, + final MountableFile certFile, + final MountableFile caFile, + final SslVerification verify, + boolean failIfNoCert, + int verificationDepth + ) { return withSSL(keyFile, certFile, caFile, verify, failIfNoCert) - .withEnv("RABBITMQ_SSL_DEPTH", String.valueOf(verificationDepth)); + .withEnv("RABBITMQ_SSL_DEPTH", String.valueOf(verificationDepth)); } public RabbitMQContainer withSSL( - final MountableFile keyFile, - final MountableFile certFile, - final MountableFile caFile, - final SslVerification verify, - boolean failIfNoCert) { - + final MountableFile keyFile, + final MountableFile certFile, + final MountableFile caFile, + final SslVerification verify, + boolean failIfNoCert + ) { return withSSL(keyFile, certFile, caFile, verify) - .withEnv("RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT", String.valueOf(failIfNoCert)); + .withEnv("RABBITMQ_SSL_FAIL_IF_NO_PEER_CERT", String.valueOf(failIfNoCert)); } public RabbitMQContainer withSSL( - final MountableFile keyFile, - final MountableFile certFile, - final MountableFile caFile, - final SslVerification verify) { - + final MountableFile keyFile, + final MountableFile certFile, + final MountableFile caFile, + final SslVerification verify + ) { return withEnv("RABBITMQ_SSL_CACERTFILE", "/etc/rabbitmq/ca_cert.pem") - .withEnv("RABBITMQ_SSL_CERTFILE", "/etc/rabbitmq/rabbitmq_cert.pem") - .withEnv("RABBITMQ_SSL_KEYFILE", "/etc/rabbitmq/rabbitmq_key.pem") - .withEnv("RABBITMQ_SSL_VERIFY", verify.value) - .withCopyFileToContainer(certFile, "/etc/rabbitmq/rabbitmq_cert.pem") - .withCopyFileToContainer(caFile, "/etc/rabbitmq/ca_cert.pem") - .withCopyFileToContainer(keyFile, "/etc/rabbitmq/rabbitmq_key.pem"); + .withEnv("RABBITMQ_SSL_CERTFILE", "/etc/rabbitmq/rabbitmq_cert.pem") + .withEnv("RABBITMQ_SSL_KEYFILE", "/etc/rabbitmq/rabbitmq_key.pem") + .withEnv("RABBITMQ_SSL_VERIFY", verify.value) + .withCopyFileToContainer(certFile, "/etc/rabbitmq/rabbitmq_cert.pem") + .withCopyFileToContainer(caFile, "/etc/rabbitmq/ca_cert.pem") + .withCopyFileToContainer(keyFile, "/etc/rabbitmq/rabbitmq_key.pem"); } public RabbitMQContainer withPluginsEnabled(String... pluginNames) { - List command = new ArrayList<>(asList("rabbitmq-plugins", "enable")); - command.addAll(asList(pluginNames)); + List command = new ArrayList<>(Arrays.asList("rabbitmq-plugins", "enable")); + command.addAll(Arrays.asList(pluginNames)); values.add(command); return self(); } public RabbitMQContainer withBinding(String source, String destination) { - values.add(asList("rabbitmqadmin", "declare", "binding", - "source=" + source, - "destination=" + destination)); + values.add( + Arrays.asList("rabbitmqadmin", "declare", "binding", "source=" + source, "destination=" + destination) + ); return self(); } public RabbitMQContainer withBinding(String vhost, String source, String destination) { - values.add(asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "binding", - "source=" + source, - "destination=" + destination)); + values.add( + Arrays.asList( + "rabbitmqadmin", + "--vhost=" + vhost, + "declare", + "binding", + "source=" + source, + "destination=" + destination + ) + ); return self(); } - public RabbitMQContainer withBinding(String source, String destination, Map arguments, String routingKey, String destinationType) { - values.add(asList("rabbitmqadmin", "declare", "binding", - "source=" + source, - "destination=" + destination, - "routing_key=" + routingKey, - "destination_type=" + destinationType, - "arguments=" + toJson(arguments))); + public RabbitMQContainer withBinding( + String source, + String destination, + Map arguments, + String routingKey, + String destinationType + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "binding", + "source=" + source, + "destination=" + destination, + "routing_key=" + routingKey, + "destination_type=" + destinationType, + "arguments=" + toJson(arguments) + ) + ); return self(); } - public RabbitMQContainer withBinding(String vhost, String source, String destination, Map arguments, String routingKey, String destinationType) { - values.add(asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "binding", + public RabbitMQContainer withBinding( + String vhost, + String source, + String destination, + Map arguments, + String routingKey, + String destinationType + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "--vhost=" + vhost, + "declare", + "binding", "source=" + source, "destination=" + destination, "routing_key=" + routingKey, "destination_type=" + destinationType, - "arguments=" + toJson(arguments))); + "arguments=" + toJson(arguments) + ) + ); return self(); } public RabbitMQContainer withParameter(String component, String name, String value) { - values.add(asList("rabbitmqadmin", "declare", "parameter", + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "parameter", "component=" + component, "name=" + name, - "value=" + value)); + "value=" + value + ) + ); return self(); } public RabbitMQContainer withPermission(String vhost, String user, String configure, String write, String read) { - values.add(asList("rabbitmqadmin", "declare", "permission", + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "permission", "vhost=" + vhost, "user=" + user, "configure=" + configure, "write=" + write, - "read=" + read)); + "read=" + read + ) + ); return self(); } public RabbitMQContainer withUser(String name, String password) { - values.add(asList("rabbitmqadmin", "declare", "user", - "name=" + name, - "password=" + password, - "tags=")); + values.add(Arrays.asList("rabbitmqadmin", "declare", "user", "name=" + name, "password=" + password, "tags=")); return self(); } public RabbitMQContainer withUser(String name, String password, Set tags) { - values.add(asList("rabbitmqadmin", "declare", "user", + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "user", "name=" + name, "password=" + password, - "tags=" + join(",", tags))); + "tags=" + String.join(",", tags) + ) + ); return self(); } public RabbitMQContainer withPolicy(String name, String pattern, Map definition) { - values.add(asList("rabbitmqadmin", "declare", "policy", + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "policy", "name=" + name, "pattern=" + pattern, - "definition=" + toJson(definition))); + "definition=" + toJson(definition) + ) + ); return self(); } public RabbitMQContainer withPolicy(String vhost, String name, String pattern, Map definition) { - values.add(asList("rabbitmqadmin", "declare", "policy", + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "policy", "--vhost=" + vhost, "name=" + name, "pattern=" + pattern, - "definition=" + toJson(definition))); + "definition=" + toJson(definition) + ) + ); return self(); } - public RabbitMQContainer withPolicy(String name, String pattern, Map definition, int priority, String applyTo) { - values.add(asList("rabbitmqadmin", "declare", "policy", + public RabbitMQContainer withPolicy( + String name, + String pattern, + Map definition, + int priority, + String applyTo + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "policy", "name=" + name, "pattern=" + pattern, "priority=" + priority, "apply-to=" + applyTo, - "definition=" + toJson(definition))); + "definition=" + toJson(definition) + ) + ); return self(); } public RabbitMQContainer withOperatorPolicy(String name, String pattern, Map definition) { - values.add(new ArrayList<>(asList("rabbitmqadmin", "declare", "operator_policy", - "name=" + name, - "pattern=" + pattern, - "definition=" + toJson(definition)))); + values.add( + new ArrayList<>( + Arrays.asList( + "rabbitmqadmin", + "declare", + "operator_policy", + "name=" + name, + "pattern=" + pattern, + "definition=" + toJson(definition) + ) + ) + ); return self(); } - public RabbitMQContainer withOperatorPolicy(String name, String pattern, Map definition, int priority, String applyTo) { - values.add(asList("rabbitmqadmin", "declare", "operator_policy", + public RabbitMQContainer withOperatorPolicy( + String name, + String pattern, + Map definition, + int priority, + String applyTo + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "operator_policy", "name=" + name, "pattern=" + pattern, "priority=" + priority, "apply-to=" + applyTo, - "definition=" + toJson(definition))); + "definition=" + toJson(definition) + ) + ); return self(); } public RabbitMQContainer withVhost(String name) { - values.add(asList("rabbitmqadmin", "declare", "vhost", - "name=" + name)); + values.add(Arrays.asList("rabbitmqadmin", "declare", "vhost", "name=" + name)); return self(); } public RabbitMQContainer withVhost(String name, boolean tracing) { - values.add(asList("rabbitmqadmin", "declare", "vhost", - "name=" + name, - "tracing=" + tracing)); + values.add(Arrays.asList("rabbitmqadmin", "declare", "vhost", "name=" + name, "tracing=" + tracing)); return self(); } public RabbitMQContainer withVhostLimit(String vhost, String name, int value) { - values.add(asList("rabbitmqadmin", "declare", "vhost_limit", - "vhost=" + vhost, - "name=" + name, - "value=" + value)); + values.add( + Arrays.asList("rabbitmqadmin", "declare", "vhost_limit", "vhost=" + vhost, "name=" + name, "value=" + value) + ); return self(); } public RabbitMQContainer withQueue(String name) { - values.add(asList("rabbitmqadmin", "declare", "queue", - "name=" + name)); + values.add(Arrays.asList("rabbitmqadmin", "declare", "queue", "name=" + name)); return self(); } public RabbitMQContainer withQueue(String vhost, String name) { - values.add(asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "queue", - "name=" + name)); + values.add(Arrays.asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "queue", "name=" + name)); return self(); } - public RabbitMQContainer withQueue(String name, boolean autoDelete, boolean durable, Map arguments) { - values.add(asList("rabbitmqadmin", "declare", "queue", + public RabbitMQContainer withQueue( + String name, + boolean autoDelete, + boolean durable, + Map arguments + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "queue", "name=" + name, "auto_delete=" + autoDelete, "durable=" + durable, - "arguments=" + toJson(arguments))); + "arguments=" + toJson(arguments) + ) + ); return self(); } - public RabbitMQContainer withQueue(String vhost, String name, boolean autoDelete, boolean durable, Map arguments) { - values.add(asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "queue", - "name=" + name, - "auto_delete=" + autoDelete, - "durable=" + durable, - "arguments=" + toJson(arguments))); + public RabbitMQContainer withQueue( + String vhost, + String name, + boolean autoDelete, + boolean durable, + Map arguments + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "--vhost=" + vhost, + "declare", + "queue", + "name=" + name, + "auto_delete=" + autoDelete, + "durable=" + durable, + "arguments=" + toJson(arguments) + ) + ); return self(); } public RabbitMQContainer withExchange(String name, String type) { - values.add(asList("rabbitmqadmin", "declare", "exchange", - "name=" + name, - "type=" + type)); + values.add(Arrays.asList("rabbitmqadmin", "declare", "exchange", "name=" + name, "type=" + type)); return self(); } public RabbitMQContainer withExchange(String vhost, String name, String type) { - values.add(asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "exchange", - "name=" + name, - "type=" + type)); + values.add( + Arrays.asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "exchange", "name=" + name, "type=" + type) + ); return self(); } - public RabbitMQContainer withExchange(String name, String type, boolean autoDelete, boolean internal, boolean durable, Map arguments) { - values.add(asList("rabbitmqadmin", "declare", "exchange", - "name=" + name, - "type=" + type, - "auto_delete=" + autoDelete, - "internal=" + internal, - "durable=" + durable, - "arguments=" + toJson(arguments))); + public RabbitMQContainer withExchange( + String name, + String type, + boolean autoDelete, + boolean internal, + boolean durable, + Map arguments + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "declare", + "exchange", + "name=" + name, + "type=" + type, + "auto_delete=" + autoDelete, + "internal=" + internal, + "durable=" + durable, + "arguments=" + toJson(arguments) + ) + ); return self(); } - public RabbitMQContainer withExchange(String vhost, String name, String type, boolean autoDelete, boolean internal, boolean durable, Map arguments) { - values.add(asList("rabbitmqadmin", "--vhost=" + vhost, "declare", "exchange", + public RabbitMQContainer withExchange( + String vhost, + String name, + String type, + boolean autoDelete, + boolean internal, + boolean durable, + Map arguments + ) { + values.add( + Arrays.asList( + "rabbitmqadmin", + "--vhost=" + vhost, + "declare", + "exchange", "name=" + name, "type=" + type, "auto_delete=" + autoDelete, "internal=" + internal, "durable=" + durable, - "arguments=" + toJson(arguments))); + "arguments=" + toJson(arguments) + ) + ); return self(); } @@ -420,7 +558,6 @@ public RabbitMQContainer withExchange(String vhost, String name, String type, bo * @return This container. */ public RabbitMQContainer withRabbitMQConfig(MountableFile rabbitMQConf) { - return withRabbitMQConfigSysctl(rabbitMQConf); } diff --git a/modules/rabbitmq/src/test/java/org/testcontainers/containers/RabbitMQContainerTest.java b/modules/rabbitmq/src/test/java/org/testcontainers/containers/RabbitMQContainerTest.java index d82051a94db..6bc935b4e6c 100644 --- a/modules/rabbitmq/src/test/java/org/testcontainers/containers/RabbitMQContainerTest.java +++ b/modules/rabbitmq/src/test/java/org/testcontainers/containers/RabbitMQContainerTest.java @@ -6,11 +6,9 @@ import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import org.junit.Test; +import org.testcontainers.containers.RabbitMQContainer.SslVerification; import org.testcontainers.utility.MountableFile; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -22,10 +20,12 @@ import java.security.cert.CertificateException; import java.util.Collections; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; -import static org.testcontainers.containers.RabbitMQContainer.SslVerification.VERIFY_PEER; -import static org.testcontainers.utility.MountableFile.forClasspathResource; /** * @author Martin Greber @@ -33,46 +33,55 @@ public class RabbitMQContainerTest { public static final int DEFAULT_AMQPS_PORT = 5671; + public static final int DEFAULT_AMQP_PORT = 5672; + public static final int DEFAULT_HTTPS_PORT = 15671; + public static final int DEFAULT_HTTP_PORT = 15672; @Test - public void shouldCreateRabbitMQContainer() - { + public void shouldCreateRabbitMQContainer() { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { - assertThat(container.getAdminPassword()).isEqualTo("guest"); assertThat(container.getAdminUsername()).isEqualTo("guest"); container.start(); - assertThat(container.getAmqpsUrl()).isEqualTo( - String.format("amqps://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_AMQPS_PORT))); - assertThat(container.getAmqpUrl()).isEqualTo( - String.format("amqp://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_AMQP_PORT))); - assertThat(container.getHttpsUrl()).isEqualTo( - String.format("https://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_HTTPS_PORT))); - assertThat(container.getHttpUrl()).isEqualTo( - String.format("http://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_HTTP_PORT))); + assertThat(container.getAmqpsUrl()) + .isEqualTo( + String.format("amqps://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_AMQPS_PORT)) + ); + assertThat(container.getAmqpUrl()) + .isEqualTo( + String.format("amqp://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_AMQP_PORT)) + ); + assertThat(container.getHttpsUrl()) + .isEqualTo( + String.format("https://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_HTTPS_PORT)) + ); + assertThat(container.getHttpUrl()) + .isEqualTo( + String.format("http://%s:%d", container.getHost(), container.getMappedPort(DEFAULT_HTTP_PORT)) + ); assertThat(container.getHttpsPort()).isEqualTo(container.getMappedPort(DEFAULT_HTTPS_PORT)); assertThat(container.getHttpPort()).isEqualTo(container.getMappedPort(DEFAULT_HTTP_PORT)); assertThat(container.getAmqpsPort()).isEqualTo(container.getMappedPort(DEFAULT_AMQPS_PORT)); assertThat(container.getAmqpPort()).isEqualTo(container.getMappedPort(DEFAULT_AMQP_PORT)); - assertThat(container.getLivenessCheckPortNumbers()).containsExactlyInAnyOrder( - container.getMappedPort(DEFAULT_AMQP_PORT), - container.getMappedPort(DEFAULT_AMQPS_PORT), - container.getMappedPort(DEFAULT_HTTP_PORT), - container.getMappedPort(DEFAULT_HTTPS_PORT) - ); + assertThat(container.getLivenessCheckPortNumbers()) + .containsExactlyInAnyOrder( + container.getMappedPort(DEFAULT_AMQP_PORT), + container.getMappedPort(DEFAULT_AMQPS_PORT), + container.getMappedPort(DEFAULT_HTTP_PORT), + container.getMappedPort(DEFAULT_HTTPS_PORT) + ); } } @Test - public void shouldCreateRabbitMQContainerWithExchange() throws IOException, InterruptedException - { + public void shouldCreateRabbitMQContainerWithExchange() throws IOException, InterruptedException { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { container.withExchange("test-exchange", "direct"); @@ -84,11 +93,18 @@ public void shouldCreateRabbitMQContainerWithExchange() throws IOException, Inte } @Test - public void shouldCreateRabbitMQContainerWithExchangeInVhost() throws IOException, InterruptedException - { + public void shouldCreateRabbitMQContainerWithExchangeInVhost() throws IOException, InterruptedException { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { container.withVhost("test-vhost"); - container.withExchange("test-vhost", "test-exchange", "direct", false, false, false, Collections.emptyMap()); + container.withExchange( + "test-vhost", + "test-exchange", + "direct", + false, + false, + false, + Collections.emptyMap() + ); container.start(); @@ -98,11 +114,10 @@ public void shouldCreateRabbitMQContainerWithExchangeInVhost() throws IOExceptio } @Test - public void shouldCreateRabbitMQContainerWithQueues() throws IOException, InterruptedException - { + public void shouldCreateRabbitMQContainerWithQueues() throws IOException, InterruptedException { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { - - container.withQueue("queue-one") + container + .withQueue("queue-one") .withQueue("queue-two", false, true, ImmutableMap.of("x-message-ttl", 1000)); container.start(); @@ -124,7 +139,6 @@ public void shouldMountConfigurationFile() { } } - @Test public void shouldMountConfigurationFileErlang() { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { @@ -135,7 +149,6 @@ public void shouldMountConfigurationFileErlang() { } } - @Test public void shouldMountConfigurationFileSysctl() { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { @@ -147,132 +160,143 @@ public void shouldMountConfigurationFileSysctl() { } @Test - public void shouldStartTheWholeEnchilada() throws IOException, InterruptedException - { + public void shouldStartTheWholeEnchilada() throws IOException, InterruptedException { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { container - .withVhost("vhost1") - .withVhostLimit("vhost1", "max-connections", 1) - .withVhost("vhost2", true) - .withExchange("direct-exchange", "direct") - .withExchange("topic-exchange", "topic") - .withExchange("vhost1", "topic-exchange-2", "topic", false, false, true, Collections.emptyMap()) - .withExchange("vhost2", "topic-exchange-3", "topic") - .withExchange("topic-exchange-4", "topic", false, false, true, Collections.emptyMap()) - .withQueue("queue1") - .withQueue("queue2", true, false, ImmutableMap.of("x-message-ttl", 1000)) - .withQueue("vhost1", "queue3", true, false, ImmutableMap.of("x-message-ttl", 1000)) - .withQueue("vhost2", "queue4") - .withBinding("direct-exchange", "queue1") - .withBinding("vhost1", "topic-exchange-2", "queue3") - .withBinding("vhost2", "topic-exchange-3", "queue4", Collections.emptyMap(), "ss7", "queue") - .withUser("user1", "password1") - .withUser("user2", "password2", ImmutableSet.of("administrator")) - .withPermission("vhost1", "user1", ".*", ".*", ".*") - .withPolicy("max length policy", "^dog", ImmutableMap.of("max-length", 1), 1, "queues") - .withPolicy("alternate exchange policy", "^direct-exchange", ImmutableMap.of("alternate-exchange", "amq.direct")) - .withPolicy("vhost2", "ha-all", ".*", ImmutableMap.of("ha-mode", "all", "ha-sync-mode", "automatic")) - .withOperatorPolicy("operator policy 1", "^queue1", ImmutableMap.of("message-ttl", 1000), 1, "queues") - .withPluginsEnabled("rabbitmq_shovel", "rabbitmq_random_exchange"); + .withVhost("vhost1") + .withVhostLimit("vhost1", "max-connections", 1) + .withVhost("vhost2", true) + .withExchange("direct-exchange", "direct") + .withExchange("topic-exchange", "topic") + .withExchange("vhost1", "topic-exchange-2", "topic", false, false, true, Collections.emptyMap()) + .withExchange("vhost2", "topic-exchange-3", "topic") + .withExchange("topic-exchange-4", "topic", false, false, true, Collections.emptyMap()) + .withQueue("queue1") + .withQueue("queue2", true, false, ImmutableMap.of("x-message-ttl", 1000)) + .withQueue("vhost1", "queue3", true, false, ImmutableMap.of("x-message-ttl", 1000)) + .withQueue("vhost2", "queue4") + .withBinding("direct-exchange", "queue1") + .withBinding("vhost1", "topic-exchange-2", "queue3") + .withBinding("vhost2", "topic-exchange-3", "queue4", Collections.emptyMap(), "ss7", "queue") + .withUser("user1", "password1") + .withUser("user2", "password2", ImmutableSet.of("administrator")) + .withPermission("vhost1", "user1", ".*", ".*", ".*") + .withPolicy("max length policy", "^dog", ImmutableMap.of("max-length", 1), 1, "queues") + .withPolicy( + "alternate exchange policy", + "^direct-exchange", + ImmutableMap.of("alternate-exchange", "amq.direct") + ) + .withPolicy("vhost2", "ha-all", ".*", ImmutableMap.of("ha-mode", "all", "ha-sync-mode", "automatic")) + .withOperatorPolicy("operator policy 1", "^queue1", ImmutableMap.of("message-ttl", 1000), 1, "queues") + .withPluginsEnabled("rabbitmq_shovel", "rabbitmq_random_exchange"); container.start(); - assertThat(container.execInContainer("rabbitmqadmin", "list", "queues") - .getStdout()) + assertThat(container.execInContainer("rabbitmqadmin", "list", "queues").getStdout()) .contains("queue1", "queue2", "queue3", "queue4"); - assertThat(container.execInContainer("rabbitmqadmin", "list", "exchanges") - .getStdout()) - .contains("direct-exchange", "topic-exchange", "topic-exchange-2", "topic-exchange-3", "topic-exchange-4"); + assertThat(container.execInContainer("rabbitmqadmin", "list", "exchanges").getStdout()) + .contains( + "direct-exchange", + "topic-exchange", + "topic-exchange-2", + "topic-exchange-3", + "topic-exchange-4" + ); - assertThat(container.execInContainer("rabbitmqadmin", "list", "bindings") - .getStdout()) + assertThat(container.execInContainer("rabbitmqadmin", "list", "bindings").getStdout()) .contains("direct-exchange", "topic-exchange-2", "topic-exchange-3"); - assertThat(container.execInContainer("rabbitmqadmin", "list", "users") - .getStdout()) + assertThat(container.execInContainer("rabbitmqadmin", "list", "users").getStdout()) .contains("user1", "user2"); - assertThat(container.execInContainer("rabbitmqadmin", "list", "policies") - .getStdout()) + assertThat(container.execInContainer("rabbitmqadmin", "list", "policies").getStdout()) .contains("max length policy", "alternate exchange policy"); - assertThat(container.execInContainer("rabbitmqadmin", "list", "policies", "--vhost=vhost2") - .getStdout()) - .contains("ha-all", "ha-sync-mode"); + assertThat(container.execInContainer("rabbitmqadmin", "list", "policies", "--vhost=vhost2").getStdout()) + .contains("ha-all", "ha-sync-mode"); - assertThat(container.execInContainer("rabbitmqadmin", "list", "operator_policies") - .getStdout()) + assertThat(container.execInContainer("rabbitmqadmin", "list", "operator_policies").getStdout()) .contains("operator policy 1"); - assertThat(container.execInContainer("rabbitmq-plugins", "is_enabled", "rabbitmq_shovel", "--quiet") - .getStdout()) + assertThat( + container.execInContainer("rabbitmq-plugins", "is_enabled", "rabbitmq_shovel", "--quiet").getStdout() + ) .contains("rabbitmq_shovel is enabled"); - assertThat(container.execInContainer("rabbitmq-plugins", "is_enabled", "rabbitmq_random_exchange", "--quiet") - .getStdout()) + assertThat( + container + .execInContainer("rabbitmq-plugins", "is_enabled", "rabbitmq_random_exchange", "--quiet") + .getStdout() + ) .contains("rabbitmq_random_exchange is enabled"); } } @Test - public void shouldThrowExceptionForDodgyJson() - { + public void shouldThrowExceptionForDodgyJson() { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { - - assertThatCode(() -> - container.withQueue( - "queue2", - true, - false, - ImmutableMap.of("x-message-ttl", container)) - ).hasMessageStartingWith("Failed to convert arguments into json"); - + assertThatCode(() -> container.withQueue("queue2", true, false, ImmutableMap.of("x-message-ttl", container)) + ) + .hasMessageStartingWith("Failed to convert arguments into json"); } } @Test - public void shouldWorkWithSSL() - { + public void shouldWorkWithSSL() { try (RabbitMQContainer container = new RabbitMQContainer(RabbitMQTestImages.RABBITMQ_IMAGE)) { container.withSSL( - forClasspathResource("/certs/server_key.pem", 0644), - forClasspathResource("/certs/server_certificate.pem", 0644), - forClasspathResource("/certs/ca_certificate.pem", 0644), - VERIFY_PEER, + MountableFile.forClasspathResource("/certs/server_key.pem", 0644), + MountableFile.forClasspathResource("/certs/server_certificate.pem", 0644), + MountableFile.forClasspathResource("/certs/ca_certificate.pem", 0644), + SslVerification.VERIFY_PEER, true ); container.start(); assertThatCode(() -> { - ConnectionFactory connectionFactory = new ConnectionFactory(); - connectionFactory.useSslProtocol(createSslContext( - "certs/client_key.p12", "password", - "certs/truststore.jks", "password")); - connectionFactory.enableHostnameVerification(); - connectionFactory.setUri(container.getAmqpsUrl()); - connectionFactory.setPassword(container.getAdminPassword()); - Connection connection = connectionFactory.newConnection(); - Channel channel = connection.openChannel().orElseThrow(() -> new RuntimeException("Failed to Open channel")); - channel.close(); - connection.close(); - }).doesNotThrowAnyException(); + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.useSslProtocol( + createSslContext("certs/client_key.p12", "password", "certs/truststore.jks", "password") + ); + connectionFactory.enableHostnameVerification(); + connectionFactory.setUri(container.getAmqpsUrl()); + connectionFactory.setPassword(container.getAdminPassword()); + Connection connection = connectionFactory.newConnection(); + Channel channel = connection + .openChannel() + .orElseThrow(() -> new RuntimeException("Failed to Open channel")); + channel.close(); + connection.close(); + }) + .doesNotThrowAnyException(); } } - private SSLContext createSslContext(String keystoreFile, String keystorePassword, String truststoreFile, String truststorePassword) - throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException - { + private SSLContext createSslContext( + String keystoreFile, + String keystorePassword, + String truststoreFile, + String truststorePassword + ) + throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException { ClassLoader classLoader = getClass().getClassLoader(); KeyStore ks = KeyStore.getInstance("PKCS12"); - ks.load(new FileInputStream(new File(classLoader.getResource(keystoreFile).getFile())), keystorePassword.toCharArray()); + ks.load( + new FileInputStream(new File(classLoader.getResource(keystoreFile).getFile())), + keystorePassword.toCharArray() + ); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, "password".toCharArray()); KeyStore trustStore = KeyStore.getInstance("PKCS12"); - trustStore.load(new FileInputStream(new File(classLoader.getResource(truststoreFile).getFile())), truststorePassword.toCharArray()); + trustStore.load( + new FileInputStream(new File(classLoader.getResource(truststoreFile).getFile())), + truststorePassword.toCharArray() + ); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(trustStore); diff --git a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java index fc3778385cd..08d7ab053c6 100644 --- a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java +++ b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java @@ -1,22 +1,10 @@ package org.testcontainers.containers; -import static java.time.temporal.ChronoUnit.SECONDS; - import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.model.AccessMode; import com.github.dockerjava.api.model.Bind; import com.github.dockerjava.api.model.Volume; import com.google.common.collect.ImmutableSet; -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.file.Files; -import java.time.Duration; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.TimeUnit; - import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.SystemUtils; import org.jetbrains.annotations.NotNull; @@ -41,40 +29,67 @@ import org.testcontainers.utility.ComparableVersion; import org.testcontainers.utility.DockerImageName; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; + /** * A chrome/firefox/custom container based on SeleniumHQ's standalone container sets. *

* The container should expose Selenium remote control protocol and VNC. */ -public class BrowserWebDriverContainer> extends GenericContainer implements LinkableContainer, TestLifecycleAware { +public class BrowserWebDriverContainer> + extends GenericContainer + implements LinkableContainer, TestLifecycleAware { private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome"); + private static final DockerImageName FIREFOX_IMAGE = DockerImageName.parse("selenium/standalone-firefox"); + private static final DockerImageName CHROME_DEBUG_IMAGE = DockerImageName.parse("selenium/standalone-chrome-debug"); - private static final DockerImageName FIREFOX_DEBUG_IMAGE = DockerImageName.parse("selenium/standalone-firefox-debug"); + + private static final DockerImageName FIREFOX_DEBUG_IMAGE = DockerImageName.parse( + "selenium/standalone-firefox-debug" + ); + private static final DockerImageName[] COMPATIBLE_IMAGES = new DockerImageName[] { CHROME_IMAGE, FIREFOX_IMAGE, CHROME_DEBUG_IMAGE, - FIREFOX_DEBUG_IMAGE + FIREFOX_DEBUG_IMAGE, }; private static final String DEFAULT_PASSWORD = "secret"; + private static final int SELENIUM_PORT = 4444; + private static final int VNC_PORT = 5900; private static final String NO_PROXY_KEY = "no_proxy"; + private static final String TC_TEMP_DIR_PREFIX = "tc"; @Nullable private Capabilities capabilities; + private DockerImageName customImageName = null; @Nullable private RemoteWebDriver driver; + private VncRecordingMode recordingMode = VncRecordingMode.RECORD_FAILING; + private VncRecordingFormat recordingFormat; + private RecordingFileFactory recordingFileFactory; + private File vncRecordingDirectory; private VncRecordingContainer vncRecordingContainer = null; @@ -84,13 +99,16 @@ public class BrowserWebDriverContainer getLivenessCheckPorts() { @Override protected void configure() { - String seleniumVersion = SeleniumUtils.determineClasspathSeleniumVersion(); if (recordingMode != VncRecordingMode.SKIP) { - if (vncRecordingDirectory == null) { try { vncRecordingDirectory = Files.createTempDirectory(TC_TEMP_DIR_PREFIX).toFile(); @@ -178,7 +196,8 @@ protected void configure() { withNetwork(Network.SHARED); } - vncRecordingContainer = new VncRecordingContainer(this) + vncRecordingContainer = + new VncRecordingContainer(this) .withVncPassword(DEFAULT_PASSWORD) .withVncPort(VNC_PORT) .withVideoFormat(recordingFormat); @@ -188,7 +207,10 @@ protected void configure() { customImageName.assertCompatibleWith(COMPATIBLE_IMAGES); super.setDockerImageName(customImageName.asCanonicalNameString()); } else { - DockerImageName standardImageForCapabilities = getStandardImageForCapabilities(capabilities, seleniumVersion); + DockerImageName standardImageForCapabilities = getStandardImageForCapabilities( + capabilities, + seleniumVersion + ); super.setDockerImageName(standardImageForCapabilities.asCanonicalNameString()); } @@ -246,7 +268,9 @@ private static DockerImageName getStandardImageForCapabilities(Capabilities capa case BrowserType.FIREFOX: return (supportsVncWithoutDebugImage ? FIREFOX_IMAGE : FIREFOX_DEBUG_IMAGE).withTag(seleniumVersion); default: - throw new UnsupportedOperationException("Browser name must be 'chrome' or 'firefox'; provided '" + browserName + "' is not supported"); + throw new UnsupportedOperationException( + "Browser name must be 'chrome' or 'firefox'; provided '" + browserName + "' is not supported" + ); } } @@ -254,7 +278,7 @@ public URL getSeleniumAddress() { try { return new URL("http", getHost(), getMappedPort(SELENIUM_PORT), "/wd/hub"); } catch (MalformedURLException e) { - e.printStackTrace();// TODO + e.printStackTrace(); // TODO return null; } } @@ -292,15 +316,27 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) { public synchronized RemoteWebDriver getWebDriver() { if (driver == null) { if (capabilities == null) { - logger().warn("No capabilities provided - this will cause an exception in future versions. Falling back to ChromeOptions"); + logger() + .warn( + "No capabilities provided - this will cause an exception in future versions. Falling back to ChromeOptions" + ); capabilities = new ChromeOptions(); } - driver = Unreliables.retryUntilSuccess(30, TimeUnit.SECONDS, () -> { - return Timeouts.getWithTimeout(10, TimeUnit.SECONDS, () -> { - return new RemoteWebDriver(getSeleniumAddress(), capabilities); - }); - }); + driver = + Unreliables.retryUntilSuccess( + 30, + TimeUnit.SECONDS, + () -> { + return Timeouts.getWithTimeout( + 10, + TimeUnit.SECONDS, + () -> { + return new RemoteWebDriver(getSeleniumAddress(), capabilities); + } + ); + } + ); } return driver; } @@ -348,7 +384,12 @@ private void retainRecordingIfNeeded(String prefix, boolean succeeded) { } if (shouldRecord) { - File recordingFile = recordingFileFactory.recordingFileForTest(vncRecordingDirectory, prefix, succeeded, vncRecordingContainer.getVideoFormat()); + File recordingFile = recordingFileFactory.recordingFileForTest( + vncRecordingDirectory, + prefix, + succeeded, + vncRecordingContainer.getVideoFormat() + ); LOGGER.info("Screen recordings for test {} will be stored at: {}", prefix, recordingFile); vncRecordingContainer.saveRecordingToFile(recordingFile); @@ -375,7 +416,11 @@ public SELF withRecordingMode(VncRecordingMode recordingMode, File vncRecordingD return withRecordingMode(recordingMode, vncRecordingDirectory, null); } - public SELF withRecordingMode(VncRecordingMode recordingMode, File vncRecordingDirectory, VncRecordingFormat recordingFormat) { + public SELF withRecordingMode( + VncRecordingMode recordingMode, + File vncRecordingDirectory, + VncRecordingFormat recordingFormat + ) { this.recordingMode = recordingMode; this.vncRecordingDirectory = vncRecordingDirectory; this.recordingFormat = recordingFormat; @@ -388,6 +433,8 @@ public SELF withRecordingFileFactory(RecordingFileFactory recordingFileFactory) } public enum VncRecordingMode { - SKIP, RECORD_ALL, RECORD_FAILING + SKIP, + RECORD_ALL, + RECORD_FAILING, } } diff --git a/modules/selenium/src/main/java/org/testcontainers/containers/DefaultRecordingFileFactory.java b/modules/selenium/src/main/java/org/testcontainers/containers/DefaultRecordingFileFactory.java index 62a1abd38db..3815f5de3e1 100644 --- a/modules/selenium/src/main/java/org/testcontainers/containers/DefaultRecordingFileFactory.java +++ b/modules/selenium/src/main/java/org/testcontainers/containers/DefaultRecordingFileFactory.java @@ -4,25 +4,36 @@ import java.text.SimpleDateFormat; import java.util.Date; -import static org.testcontainers.containers.VncRecordingContainer.VncRecordingFormat; - public class DefaultRecordingFileFactory implements RecordingFileFactory { private static final SimpleDateFormat filenameDateFormat = new SimpleDateFormat("YYYYMMdd-HHmmss"); + private static final String PASSED = "PASSED"; + private static final String FAILED = "FAILED"; - private static final String FILENAME_FORMAT = "%s-%s-%s.%s"; + private static final String FILENAME_FORMAT = "%s-%s-%s.%s"; @Override public File recordingFileForTest(File vncRecordingDirectory, String prefix, boolean succeeded) { - return recordingFileForTest(vncRecordingDirectory, prefix, succeeded, VncRecordingContainer.DEFAULT_RECORDING_FORMAT); + return recordingFileForTest( + vncRecordingDirectory, + prefix, + succeeded, + VncRecordingContainer.DEFAULT_RECORDING_FORMAT + ); } @Override - public File recordingFileForTest(File vncRecordingDirectory, String prefix, boolean succeeded, VncRecordingFormat recordingFormat) { + public File recordingFileForTest( + File vncRecordingDirectory, + String prefix, + boolean succeeded, + VncRecordingContainer.VncRecordingFormat recordingFormat + ) { final String resultMarker = succeeded ? PASSED : FAILED; - final String fileName = String.format(FILENAME_FORMAT, + final String fileName = String.format( + FILENAME_FORMAT, resultMarker, prefix, filenameDateFormat.format(new Date()), diff --git a/modules/selenium/src/main/java/org/testcontainers/containers/RecordingFileFactory.java b/modules/selenium/src/main/java/org/testcontainers/containers/RecordingFileFactory.java index aff607cf23d..31946dac59e 100644 --- a/modules/selenium/src/main/java/org/testcontainers/containers/RecordingFileFactory.java +++ b/modules/selenium/src/main/java/org/testcontainers/containers/RecordingFileFactory.java @@ -6,16 +6,23 @@ import java.io.File; public interface RecordingFileFactory { - @Deprecated default File recordingFileForTest(File vncRecordingDirectory, Description description, boolean succeeded) { - return recordingFileForTest(vncRecordingDirectory, description.getTestClass().getSimpleName() + "-" + description.getMethodName(), succeeded); + return recordingFileForTest( + vncRecordingDirectory, + description.getTestClass().getSimpleName() + "-" + description.getMethodName(), + succeeded + ); } - default File recordingFileForTest(File vncRecordingDirectory, String prefix, boolean succeeded, VncRecordingFormat recordingFormat) { + default File recordingFileForTest( + File vncRecordingDirectory, + String prefix, + boolean succeeded, + VncRecordingFormat recordingFormat + ) { return recordingFileForTest(vncRecordingDirectory, prefix, succeeded); } File recordingFileForTest(File vncRecordingDirectory, String prefix, boolean succeeded); - } diff --git a/modules/selenium/src/main/java/org/testcontainers/containers/SeleniumUtils.java b/modules/selenium/src/main/java/org/testcontainers/containers/SeleniumUtils.java index 131f5a953ea..4fc0765cc86 100644 --- a/modules/selenium/src/main/java/org/testcontainers/containers/SeleniumUtils.java +++ b/modules/selenium/src/main/java/org/testcontainers/containers/SeleniumUtils.java @@ -45,19 +45,24 @@ public static String determineClasspathSeleniumVersion() { } } } - } catch (Exception e) { LOGGER.debug("Failed to determine Selenium-Version from selenium-api JAR Manifest", e); } if (seleniumVersions.size() == 0) { - LOGGER.warn("Failed to determine Selenium version from classpath - will use default version of {}", DEFAULT_SELENIUM_VERSION); + LOGGER.warn( + "Failed to determine Selenium version from classpath - will use default version of {}", + DEFAULT_SELENIUM_VERSION + ); return DEFAULT_SELENIUM_VERSION; } String foundVersion = seleniumVersions.iterator().next(); if (seleniumVersions.size() > 1) { - LOGGER.warn("Multiple versions of Selenium API found on classpath - will select {}, but this may not be reliable", foundVersion); + LOGGER.warn( + "Multiple versions of Selenium API found on classpath - will select {}, but this may not be reliable", + foundVersion + ); } return foundVersion; @@ -76,7 +81,7 @@ public static String getSeleniumVersionFromManifest(Manifest manifest) { } // Compatibility Selenium > 3.X - if(seleniumVersion == null) { + if (seleniumVersion == null) { Attributes seleniumInfo = manifest.getAttributes("Selenium"); if (seleniumInfo != null) { seleniumVersion = seleniumInfo.getValue("Selenium-Version"); diff --git a/modules/selenium/src/test/java/org/testcontainers/containers/DefaultRecordingFileFactoryTest.java b/modules/selenium/src/test/java/org/testcontainers/containers/DefaultRecordingFileFactoryTest.java index 9abea56c5f2..0d8daaad219 100644 --- a/modules/selenium/src/test/java/org/testcontainers/containers/DefaultRecordingFileFactoryTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/containers/DefaultRecordingFileFactoryTest.java @@ -8,19 +8,15 @@ import java.io.File; import java.nio.file.Files; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; -import static java.lang.Boolean.FALSE; -import static java.lang.Boolean.TRUE; -import static java.lang.String.format; -import static java.time.LocalDateTime.now; -import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.hamcrest.Matchers.hasItem; import static org.junit.Assert.assertThat; -import static org.junit.runner.Description.createTestDescription; @RunWith(Parameterized.class) @Value @@ -29,30 +25,47 @@ public class DefaultRecordingFileFactoryTest { private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("YYYYMMdd-HHmmss"); private final DefaultRecordingFileFactory factory = new DefaultRecordingFileFactory(); + private final String methodName; + private final String prefix; + private final boolean success; @Parameterized.Parameters public static Collection data() { Collection args = new ArrayList<>(); - args.add(new Object[]{"testMethod1", "FAILED", FALSE}); - args.add(new Object[]{"testMethod2", "PASSED", TRUE}); + args.add(new Object[] { "testMethod1", "FAILED", Boolean.FALSE }); + args.add(new Object[] { "testMethod2", "PASSED", Boolean.TRUE }); return args; } @Test public void recordingFileThatShouldDescribeTheTestResultAtThePresentTime() throws Exception { File vncRecordingDirectory = Files.createTempDirectory("recording").toFile(); - Description description = createTestDescription(getClass().getCanonicalName(), methodName, Test.class); + Description description = Description.createTestDescription( + getClass().getCanonicalName(), + methodName, + Test.class + ); File recordingFile = factory.recordingFileForTest(vncRecordingDirectory, description, success); - String expectedFilePrefix = format("%s-%s-%s", prefix, getClass().getSimpleName(), methodName); + String expectedFilePrefix = String.format("%s-%s-%s", prefix, getClass().getSimpleName(), methodName); List expectedPossibleFileNames = Arrays.asList( - new File(vncRecordingDirectory, format("%s-%s.flv", expectedFilePrefix, now().format(DATETIME_FORMATTER))), - new File(vncRecordingDirectory, format("%s-%s.flv", expectedFilePrefix, now().minusSeconds(1L).format(DATETIME_FORMATTER))) + new File( + vncRecordingDirectory, + String.format("%s-%s.flv", expectedFilePrefix, LocalDateTime.now().format(DATETIME_FORMATTER)) + ), + new File( + vncRecordingDirectory, + String.format( + "%s-%s.flv", + expectedFilePrefix, + LocalDateTime.now().minusSeconds(1L).format(DATETIME_FORMATTER) + ) + ) ); assertThat(expectedPossibleFileNames, hasItem(recordingFile)); diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/BaseWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/BaseWebDriverContainerTest.java index db369824442..d0865a06b09 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/BaseWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/BaseWebDriverContainerTest.java @@ -1,10 +1,5 @@ package org.testcontainers.junit; -import static java.lang.String.format; -import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; - -import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.NotNull; import org.junit.ClassRule; import org.openqa.selenium.By; @@ -16,6 +11,11 @@ import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import org.testcontainers.utility.DockerImageName; +import java.util.concurrent.TimeUnit; + +import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; +import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; + /** * */ @@ -25,7 +25,9 @@ public class BaseWebDriverContainerTest { public static Network NETWORK = Network.newNetwork(); @ClassRule - public static GenericContainer HELLO_WORLD = new GenericContainer<>(DockerImageName.parse("testcontainers/helloworld:1.1.0")) + public static GenericContainer HELLO_WORLD = new GenericContainer<>( + DockerImageName.parse("testcontainers/helloworld:1.1.0") + ) .withNetwork(NETWORK) .withNetworkAliases("helloworld") .withExposedPorts(8080, 8081) @@ -39,17 +41,13 @@ protected static void doSimpleExplore(BrowserWebDriverContainer rule) { driver.get("http://helloworld:8080"); WebElement title = driver.findElement(By.tagName("h1")); - assertEquals("the index page contains the title 'Hello world'", - "Hello world", - title.getText().trim() - ); + assertEquals("the index page contains the title 'Hello world'", "Hello world", title.getText().trim()); } protected void assertBrowserNameIs(BrowserWebDriverContainer rule, String expectedName) { RemoteWebDriver driver = setupDriverFromRule(rule); String actual = driver.getCapabilities().getBrowserName(); - assertTrue(format("actual browser name is %s", actual), - actual.equals(expectedName)); + assertTrue(String.format("actual browser name is %s", actual), actual.equals(expectedName)); } @NotNull diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/BrowserWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/BrowserWebDriverContainerTest.java index a53fa532f99..60d113dc290 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/BrowserWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/BrowserWebDriverContainerTest.java @@ -9,10 +9,10 @@ import org.openqa.selenium.firefox.FirefoxOptions; import org.testcontainers.containers.BrowserWebDriverContainer; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toList; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; public class BrowserWebDriverContainerTest { @@ -40,7 +40,6 @@ public void provideDefaultNoProxyEnvironmentIfNotSet() { try ( BrowserWebDriverContainer chromeWithoutNoProxySet = new BrowserWebDriverContainer() .withCapabilities(new ChromeOptions()) - ) { chromeWithoutNoProxySet.start(); @@ -49,7 +48,6 @@ public void provideDefaultNoProxyEnvironmentIfNotSet() { } } - @Test public void createContainerWithShmVolume() { Assume.assumeFalse("SHM isn't mounted on Windows", SystemUtils.IS_OS_WINDOWS); @@ -76,19 +74,19 @@ public void createContainerWithoutShmVolume() { ) { webDriverContainer.start(); - assertEquals("Shared memory size is configured", - 512 * FileUtils.ONE_MB, - webDriverContainer.getShmSize()); + assertEquals("Shared memory size is configured", 512 * FileUtils.ONE_MB, webDriverContainer.getShmSize()); - assertEquals("No shm mounts present", emptyList(), shmVolumes(webDriverContainer)); + assertEquals("No shm mounts present", Collections.emptyList(), shmVolumes(webDriverContainer)); } } private List shmVolumes(final BrowserWebDriverContainer container) { - return container.getContainerInfo().getMounts() + return container + .getContainerInfo() + .getMounts() .stream() // destination path is always /dev/shm .filter(m -> m.getDestination().getPath().equals("/dev/shm")) - .collect(toList()); + .collect(Collectors.toList()); } } diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/ChromeRecordingWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/ChromeRecordingWebDriverContainerTest.java index fdf56aa0134..b2b7d8d6b1c 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/ChromeRecordingWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/ChromeRecordingWebDriverContainerTest.java @@ -1,6 +1,5 @@ package org.testcontainers.junit; - import com.google.common.io.PatternFilenameFilter; import org.junit.Rule; import org.junit.Test; @@ -9,6 +8,7 @@ import org.junit.runner.RunWith; import org.openqa.selenium.chrome.ChromeOptions; import org.testcontainers.containers.BrowserWebDriverContainer; +import org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode; import org.testcontainers.containers.DefaultRecordingFileFactory; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.VncRecordingContainer; @@ -21,14 +21,12 @@ import java.io.File; import java.io.IOException; import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.Optional; import java.util.concurrent.TimeUnit; -import static java.time.temporal.ChronoUnit.SECONDS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode.RECORD_ALL; -import static org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode.RECORD_FAILING; @RunWith(Enclosed.class) public class ChromeRecordingWebDriverContainerTest extends BaseWebDriverContainerTest { @@ -52,7 +50,7 @@ public void recordingTestThatShouldBeRecordedAndRetainedInFlvFormatAsDefault() t // To do this, simply add extra parameters to the rule constructor, so video will default to FLV format: BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() .withCapabilities(new ChromeOptions()) - .withRecordingMode(RECORD_ALL, target) + .withRecordingMode(VncRecordingMode.RECORD_ALL, target) // } .withRecordingFileFactory(new DefaultRecordingFileFactory()) .withNetwork(NETWORK) @@ -62,22 +60,26 @@ public void recordingTestThatShouldBeRecordedAndRetainedInFlvFormatAsDefault() t } } - private File[] runSimpleExploreInContainer(BrowserWebDriverContainer container, String fileNamePattern) throws InterruptedException { + private File[] runSimpleExploreInContainer(BrowserWebDriverContainer container, String fileNamePattern) + throws InterruptedException { container.start(); TimeUnit.MILLISECONDS.sleep(MINIMUM_VIDEO_DURATION_MILLISECONDS); doSimpleExplore(container); - container.afterTest(new TestDescription() { - @Override - public String getTestId() { - return getFilesystemFriendlyName(); - } - - @Override - public String getFilesystemFriendlyName() { - return "ChromeThatRecordsAllTests-recordingTestThatShouldBeRecordedAndRetained"; - } - }, Optional.empty()); + container.afterTest( + new TestDescription() { + @Override + public String getTestId() { + return getFilesystemFriendlyName(); + } + + @Override + public String getFilesystemFriendlyName() { + return "ChromeThatRecordsAllTests-recordingTestThatShouldBeRecordedAndRetained"; + } + }, + Optional.empty() + ); return vncRecordingDirectory.getRoot().listFiles(new PatternFilenameFilter(fileNamePattern)); } @@ -90,7 +92,7 @@ public void recordingTestShouldHaveFlvExtension() throws InterruptedException { // Set (explicitly) FLV format for recorded video: BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() .withCapabilities(new ChromeOptions()) - .withRecordingMode(RECORD_ALL, target, VncRecordingFormat.FLV) + .withRecordingMode(VncRecordingMode.RECORD_ALL, target, VncRecordingFormat.FLV) // } .withRecordingFileFactory(new DefaultRecordingFileFactory()) .withNetwork(NETWORK) @@ -108,7 +110,7 @@ public void recordingTestShouldHaveMp4Extension() throws InterruptedException { // Set MP4 format for recorded video: BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() .withCapabilities(new ChromeOptions()) - .withRecordingMode(RECORD_ALL, target, VncRecordingFormat.MP4) + .withRecordingMode(VncRecordingMode.RECORD_ALL, target, VncRecordingFormat.MP4) // } .withRecordingFileFactory(new DefaultRecordingFileFactory()) .withNetwork(NETWORK) @@ -124,7 +126,7 @@ public void recordingTestThatShouldHaveCorrectDuration() throws IOException, Int try ( BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() .withCapabilities(new ChromeOptions()) - .withRecordingMode(RECORD_ALL, vncRecordingDirectory.getRoot()) + .withRecordingMode(VncRecordingMode.RECORD_ALL, vncRecordingDirectory.getRoot()) .withRecordingFileFactory(new DefaultRecordingFileFactory()) .withNetwork(NETWORK) ) { @@ -132,19 +134,28 @@ public void recordingTestThatShouldHaveCorrectDuration() throws IOException, Int mountableFile = MountableFile.forHostPath(recordedFiles[0].getCanonicalPath()); } - try (GenericContainer container = new GenericContainer<>(DockerImageName.parse("testcontainers/vnc-recorder:1.2.0"))) { + try ( + GenericContainer container = new GenericContainer<>( + DockerImageName.parse("testcontainers/vnc-recorder:1.2.0") + ) + ) { String recordFileContainerPath = "/tmp/chromeTestRecord.flv"; - container.withCopyFileToContainer(mountableFile, recordFileContainerPath) - .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withEntrypoint("ffmpeg")) - .withCommand("-i", recordFileContainerPath, "-f", "null", "-") - .waitingFor(new LogMessageWaitStrategy() - .withRegEx(".*Duration.*") - .withStartupTimeout(Duration.of(60, SECONDS))) - .start(); + container + .withCopyFileToContainer(mountableFile, recordFileContainerPath) + .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withEntrypoint("ffmpeg")) + .withCommand("-i", recordFileContainerPath, "-f", "null", "-") + .waitingFor( + new LogMessageWaitStrategy() + .withRegEx(".*Duration.*") + .withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS)) + ) + .start(); String ffmpegOutput = container.getLogs(); - assertTrue("Duration is incorrect in:\n " + ffmpegOutput, - ffmpegOutput.contains("Duration: 00:") && !(ffmpegOutput.contains("Duration: 00:00:00.00"))); + assertTrue( + "Duration is incorrect in:\n " + ffmpegOutput, + ffmpegOutput.contains("Duration: 00:") && !(ffmpegOutput.contains("Duration: 00:00:00.00")) + ); } } } @@ -180,7 +191,7 @@ public void recordingTestThatShouldBeRecordedAndRetained() throws InterruptedExc // or if you only want videos for test failures: BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() .withCapabilities(new ChromeOptions()) - .withRecordingMode(RECORD_FAILING, target) + .withRecordingMode(VncRecordingMode.RECORD_FAILING, target) // } .withRecordingFileFactory(new DefaultRecordingFileFactory()) .withNetwork(NETWORK) @@ -189,25 +200,26 @@ public void recordingTestThatShouldBeRecordedAndRetained() throws InterruptedExc TimeUnit.MILLISECONDS.sleep(MINIMUM_VIDEO_DURATION_MILLISECONDS); doSimpleExplore(chrome); - chrome.afterTest(new TestDescription() { - @Override - public String getTestId() { - return getFilesystemFriendlyName(); - } - - @Override - public String getFilesystemFriendlyName() { - return "ChromeThatRecordsFailingTests-recordingTestThatShouldBeRecordedAndRetained"; - } - }, Optional.of(new RuntimeException("Force writing of video file."))); + chrome.afterTest( + new TestDescription() { + @Override + public String getTestId() { + return getFilesystemFriendlyName(); + } + + @Override + public String getFilesystemFriendlyName() { + return "ChromeThatRecordsFailingTests-recordingTestThatShouldBeRecordedAndRetained"; + } + }, + Optional.of(new RuntimeException("Force writing of video file.")) + ); String[] files = vncRecordingDirectory.getRoot().list(new PatternFilenameFilter("FAILED-.*\\.flv")); assertEquals("Recorded file not found", 1, files.length); } - } - private static class CustomRecordingFileFactory extends DefaultRecordingFileFactory { - } + private static class CustomRecordingFileFactory extends DefaultRecordingFileFactory {} } } diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/ChromeWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/ChromeWebDriverContainerTest.java index bea1909a145..eb9872b06e9 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/ChromeWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/ChromeWebDriverContainerTest.java @@ -15,7 +15,7 @@ public class ChromeWebDriverContainerTest extends BaseWebDriverContainerTest { @Rule public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() .withCapabilities(new ChromeOptions()) - // } + // } .withNetwork(NETWORK); @Before diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/ContainerWithoutCapabilitiesTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/ContainerWithoutCapabilitiesTest.java index b1214d18b60..d20f8c3aad8 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/ContainerWithoutCapabilitiesTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/ContainerWithoutCapabilitiesTest.java @@ -4,11 +4,10 @@ import org.junit.Test; import org.testcontainers.containers.BrowserWebDriverContainer; -public class ContainerWithoutCapabilitiesTest extends BaseWebDriverContainerTest{ +public class ContainerWithoutCapabilitiesTest extends BaseWebDriverContainerTest { @Rule - public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() - .withNetwork(NETWORK); + public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>().withNetwork(NETWORK); @Test public void chromeIsStartedIfNoCapabilitiesProvided() { @@ -16,7 +15,7 @@ public void chromeIsStartedIfNoCapabilitiesProvided() { } @Test - public void simpleExploreTestWhenNoCapabilitiesProvided(){ + public void simpleExploreTestWhenNoCapabilitiesProvided() { doSimpleExplore(chrome); } } diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java index 8448dc40d53..362be6550e4 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java @@ -6,8 +6,7 @@ import org.testcontainers.containers.BrowserWebDriverContainer; import java.time.Duration; - -import static java.time.temporal.ChronoUnit.SECONDS; +import java.time.temporal.ChronoUnit; /** * @@ -17,7 +16,7 @@ public class CustomWaitTimeoutWebDriverContainerTest extends BaseWebDriverContai @Rule public BrowserWebDriverContainer chromeWithCustomTimeout = new BrowserWebDriverContainer<>() .withCapabilities(new ChromeOptions()) - .withStartupTimeout(Duration.of(30, SECONDS)) + .withStartupTimeout(Duration.of(30, ChronoUnit.SECONDS)) .withNetwork(NETWORK); @Test diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/FirefoxWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/FirefoxWebDriverContainerTest.java index 1cffec16bc6..e56b33a1704 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/FirefoxWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/FirefoxWebDriverContainerTest.java @@ -14,8 +14,8 @@ public class FirefoxWebDriverContainerTest extends BaseWebDriverContainerTest { // junitRule { @Rule public BrowserWebDriverContainer firefox = new BrowserWebDriverContainer<>() - .withCapabilities(new FirefoxOptions()) - // } + .withCapabilities(new FirefoxOptions()) + // } .withNetwork(NETWORK); @Before diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/LocalServerWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/LocalServerWebDriverContainerTest.java index 3c071984dfb..2d2feb6aaff 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/LocalServerWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/LocalServerWebDriverContainerTest.java @@ -22,11 +22,11 @@ public class LocalServerWebDriverContainerTest { public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>() .withAccessToHost(true) .withCapabilities(new ChromeOptions()); + private int localPort; @Before public void setupLocalServer() throws Exception { - // Set up a local Jetty HTTP server Server server = new Server(); server.addConnector(new SocketConnector()); @@ -53,6 +53,10 @@ public void testConnection() { String headingText = driver.findElement(By.cssSelector("h1")).getText().trim(); - assertEquals("The hardcoded success message was found on a page fetched from a local server", "It worked", headingText); + assertEquals( + "The hardcoded success message was found on a page fetched from a local server", + "It worked", + headingText + ); } } diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumStartTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumStartTest.java index a236a9696c1..04a31662099 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumStartTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumStartTest.java @@ -15,19 +15,19 @@ public class SeleniumStartTest { @Parameterized.Parameters(name = "tag: {0}") public static String[] data() { - return new String[]{"4.0.0", "3.4.0", "2.53.0", "2.45.0"}; + return new String[] { "4.0.0", "3.4.0", "2.53.0", "2.45.0" }; } - @Parameterized.Parameter() + @Parameterized.Parameter public String tag; @Test public void testAdditionalStartupString() { - final DockerImageName imageName = DockerImageName - .parse("selenium/standalone-chrome") - .withTag(tag); - try (BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>(imageName) - .withCapabilities(new ChromeOptions())) { + final DockerImageName imageName = DockerImageName.parse("selenium/standalone-chrome").withTag(tag); + try ( + BrowserWebDriverContainer chrome = new BrowserWebDriverContainer<>(imageName) + .withCapabilities(new ChromeOptions()) + ) { chrome.start(); } } diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumUtilsTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumUtilsTest.java index d706d0fc390..4cbfca77d21 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumUtilsTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/SeleniumUtilsTest.java @@ -8,7 +8,6 @@ import static org.rnorth.visibleassertions.VisibleAssertions.*; - /** * Created by Julien LAMY */ @@ -35,5 +34,4 @@ private void checkSeleniumVersionDetected(String urlManifest, String expectedVer String seleniumVersion = SeleniumUtils.getSeleniumVersionFromManifest(manifest); assertEquals("Check if Selenium Version detected is the correct one.", expectedVersion, seleniumVersion); } - } diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/SpecificImageNameWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/SpecificImageNameWebDriverContainerTest.java index 9a15c6b466d..e3db8ad5887 100644 --- a/modules/selenium/src/test/java/org/testcontainers/junit/SpecificImageNameWebDriverContainerTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/junit/SpecificImageNameWebDriverContainerTest.java @@ -8,8 +8,9 @@ public class SpecificImageNameWebDriverContainerTest extends BaseWebDriverContainerTest { - private static final DockerImageName FIREFOX_IMAGE = DockerImageName - .parse("selenium/standalone-firefox:2.53.1-beryllium"); + private static final DockerImageName FIREFOX_IMAGE = DockerImageName.parse( + "selenium/standalone-firefox:2.53.1-beryllium" + ); @Rule public BrowserWebDriverContainer firefox = new BrowserWebDriverContainer<>(FIREFOX_IMAGE) diff --git a/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtils.java b/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtils.java index 4492ca0befe..f831cdd82e9 100644 --- a/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtils.java +++ b/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtils.java @@ -1,5 +1,13 @@ package org.testcontainers.containers; +import okhttp3.HttpUrl; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.apache.commons.io.IOUtils; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URISyntaxException; @@ -11,15 +19,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import org.apache.commons.io.IOUtils; - -import okhttp3.HttpUrl; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - /** * Utils class which can create collections and configurations. * @@ -38,7 +37,13 @@ public class SolrClientUtils { * @param solrConfig the url under which the solrconfig.xml can be found * @param solrSchema the url under which the schema.xml can be found or null if the default schema should be used */ - public static void uploadConfiguration(String hostname, int port, String configurationName, URL solrConfig, URL solrSchema) throws URISyntaxException, IOException { + public static void uploadConfiguration( + String hostname, + int port, + String configurationName, + URL solrConfig, + URL solrSchema + ) throws URISyntaxException, IOException { Map parameters = new HashMap<>(); parameters.put("action", "UPLOAD"); parameters.put("name", configurationName); @@ -46,7 +51,6 @@ public static void uploadConfiguration(String hostname, int port, String configu byte[] configurationZipFile = generateConfigZipFile(solrConfig, solrSchema); executePost(url, configurationZipFile); - } /** @@ -58,7 +62,8 @@ public static void uploadConfiguration(String hostname, int port, String configu * @param configurationName the name of the configuration which should used to create the collection * or null if the default configuration should be used */ - public static void createCollection(String hostname, int port, String collectionName, String configurationName) throws URISyntaxException, IOException { + public static void createCollection(String hostname, int port, String collectionName, String configurationName) + throws URISyntaxException, IOException { Map parameters = new HashMap<>(); parameters.put("action", "CREATE"); parameters.put("name", collectionName); @@ -73,16 +78,11 @@ public static void createCollection(String hostname, int port, String collection } private static void executePost(HttpUrl url, byte[] data) throws IOException { + RequestBody requestBody = data == null + ? RequestBody.create(MediaType.parse("text/plain"), "") + : RequestBody.create(MediaType.parse("application/octet-stream"), data); + Request request = new Request.Builder().url(url).post(requestBody).build(); - RequestBody requestBody = data == null ? - RequestBody.create(MediaType.parse("text/plain"), "") : - RequestBody.create(MediaType.parse("application/octet-stream"), data); - ; - - Request request = new Request.Builder() - .url(url) - .post(requestBody) - .build(); Response response = httpClient.newCall(request).execute(); if (!response.isSuccessful()) { String responseBody = ""; @@ -97,7 +97,12 @@ private static void executePost(HttpUrl url, byte[] data) throws IOException { } } - private static HttpUrl generateSolrURL(String hostname, int port, List pathSegments, Map parameters) throws URISyntaxException { + private static HttpUrl generateSolrURL( + String hostname, + int port, + List pathSegments, + Map parameters + ) throws URISyntaxException { HttpUrl.Builder builder = new HttpUrl.Builder(); builder.scheme("http"); builder.host(hostname); diff --git a/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtilsException.java b/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtilsException.java index 5ba0865502c..a3b2cfd77c6 100644 --- a/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtilsException.java +++ b/modules/solr/src/main/java/org/testcontainers/containers/SolrClientUtilsException.java @@ -1,6 +1,7 @@ package org.testcontainers.containers; public class SolrClientUtilsException extends RuntimeException { + public SolrClientUtilsException(int statusCode, String msg) { super("Http Call Status: " + statusCode + "\n" + msg); } diff --git a/modules/solr/src/main/java/org/testcontainers/containers/SolrContainer.java b/modules/solr/src/main/java/org/testcontainers/containers/SolrContainer.java index e583c1f54ee..5161bce2738 100644 --- a/modules/solr/src/main/java/org/testcontainers/containers/SolrContainer.java +++ b/modules/solr/src/main/java/org/testcontainers/containers/SolrContainer.java @@ -8,11 +8,10 @@ import java.net.URL; import java.time.Duration; +import java.time.temporal.ChronoUnit; import java.util.HashSet; import java.util.Set; -import static java.time.temporal.ChronoUnit.SECONDS; - /** * SolrContainer allows a solr container to be launched and controlled. */ @@ -27,6 +26,7 @@ public class SolrContainer extends GenericContainer { public static final String DEFAULT_TAG = "8.3.0"; public static final Integer ZOOKEEPER_PORT = 9983; + public static final Integer SOLR_PORT = 8983; private SolrContainerConfiguration configuration; @@ -48,12 +48,12 @@ public SolrContainer(final String dockerImageName) { public SolrContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - this.waitStrategy = new LogMessageWaitStrategy() - .withRegEx(".*o\\.e\\.j\\.s\\.Server Started.*") - .withStartupTimeout(Duration.of(60, SECONDS)); + this.waitStrategy = + new LogMessageWaitStrategy() + .withRegEx(".*o\\.e\\.j\\.s\\.Server Started.*") + .withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS)); this.configuration = new SolrContainerConfiguration(); } @@ -129,7 +129,9 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) { if (!configuration.isZookeeper()) { ExecResult result = execInContainer("solr", "create_core", "-c", configuration.getCollectionName()); if (result.getExitCode() != 0) { - throw new IllegalStateException("Unable to create solr core:\nStdout: " + result.getStdout() + "\nStderr:" + result.getStderr()); + throw new IllegalStateException( + "Unable to create solr core:\nStdout: " + result.getStdout() + "\nStderr:" + result.getStderr() + ); } return; } @@ -140,14 +142,15 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) { getSolrPort(), configuration.getConfigurationName(), configuration.getSolrConfiguration(), - configuration.getSolrSchema()); + configuration.getSolrSchema() + ); } SolrClientUtils.createCollection( getHost(), getSolrPort(), configuration.getCollectionName(), - configuration.getConfigurationName()); + configuration.getConfigurationName() + ); } } - diff --git a/modules/solr/src/main/java/org/testcontainers/containers/SolrContainerConfiguration.java b/modules/solr/src/main/java/org/testcontainers/containers/SolrContainerConfiguration.java index 1f35ce2a810..698e956c8fe 100644 --- a/modules/solr/src/main/java/org/testcontainers/containers/SolrContainerConfiguration.java +++ b/modules/solr/src/main/java/org/testcontainers/containers/SolrContainerConfiguration.java @@ -1,9 +1,9 @@ package org.testcontainers.containers; -import java.net.URL; - import lombok.Data; +import java.net.URL; + /** * @author Simon Schneider */ @@ -11,8 +11,12 @@ public class SolrContainerConfiguration { private boolean zookeeper = true; + private String collectionName = "dummy"; + private String configurationName; + private URL solrConfiguration; + private URL solrSchema; } diff --git a/modules/solr/src/test/java/org/testcontainers/containers/SolrContainerTest.java b/modules/solr/src/test/java/org/testcontainers/containers/SolrContainerTest.java index 9f82e2c3af9..9b561e5cda9 100644 --- a/modules/solr/src/test/java/org/testcontainers/containers/SolrContainerTest.java +++ b/modules/solr/src/test/java/org/testcontainers/containers/SolrContainerTest.java @@ -10,9 +10,9 @@ import java.io.IOException; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; /** * @author Simon Schneider @@ -20,6 +20,7 @@ public class SolrContainerTest { private static final DockerImageName SOLR_IMAGE = DockerImageName.parse("solr:8.3.0"); + private SolrClient client = null; @After @@ -60,7 +61,10 @@ public void solrCloudPingTest() throws IOException, SolrServerException { container.start(); // Do whatever you want with the client ... - SolrClient client = new Http2SolrClient.Builder("http://" + container.getHost() + ":" + container.getSolrPort() + "/solr").build(); + SolrClient client = new Http2SolrClient.Builder( + "http://" + container.getHost() + ":" + container.getSolrPort() + "/solr" + ) + .build(); SolrPingResponse response = client.ping("dummy"); // Stop the container. @@ -70,9 +74,10 @@ public void solrCloudPingTest() throws IOException, SolrServerException { private SolrClient getClient(SolrContainer container) { if (client == null) { - client = new Http2SolrClient.Builder("http://" + container.getHost() + ":" + container.getSolrPort() + "/solr").build(); + client = + new Http2SolrClient.Builder("http://" + container.getHost() + ":" + container.getSolrPort() + "/solr") + .build(); } return client; } - } diff --git a/modules/spock/src/main/groovy/org/testcontainers/spock/SpockTestDescription.groovy b/modules/spock/src/main/groovy/org/testcontainers/spock/SpockTestDescription.groovy index 85b58724000..6c71ac421c6 100644 --- a/modules/spock/src/main/groovy/org/testcontainers/spock/SpockTestDescription.groovy +++ b/modules/spock/src/main/groovy/org/testcontainers/spock/SpockTestDescription.groovy @@ -12,25 +12,25 @@ import org.testcontainers.lifecycle.TestDescription @PackageScope class SpockTestDescription implements TestDescription { - String specName - String featureName + String specName + String featureName - static SpockTestDescription fromTestDescription(IMethodInvocation invocation) { - return new SpockTestDescription([ - specName: invocation.spec.name, - featureName: invocation.feature.name - ]) - } + static SpockTestDescription fromTestDescription(IMethodInvocation invocation) { + return new SpockTestDescription([ + specName: invocation.spec.name, + featureName: invocation.feature.name + ]) + } - @Override - String getTestId() { - return getFilesystemFriendlyName() - } + @Override + String getTestId() { + return getFilesystemFriendlyName() + } - @Override - String getFilesystemFriendlyName() { - return [specName, featureName].collect { - URLEncoder.encode(it, 'UTF-8') - }.join('-') - } + @Override + String getFilesystemFriendlyName() { + return [specName, featureName].collect { + URLEncoder.encode(it, 'UTF-8') + }.join('-') + } } diff --git a/modules/spock/src/main/groovy/org/testcontainers/spock/Testcontainers.groovy b/modules/spock/src/main/groovy/org/testcontainers/spock/Testcontainers.groovy index 675ed68c4a6..2e70b6d589f 100644 --- a/modules/spock/src/main/groovy/org/testcontainers/spock/Testcontainers.groovy +++ b/modules/spock/src/main/groovy/org/testcontainers/spock/Testcontainers.groovy @@ -13,5 +13,4 @@ import java.lang.annotation.Target @Target([ElementType.TYPE, ElementType.METHOD]) @ExtensionAnnotation(TestcontainersExtension) @interface Testcontainers { - } diff --git a/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersExtension.groovy b/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersExtension.groovy index 1f66fd8f596..40392210f3a 100644 --- a/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersExtension.groovy +++ b/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersExtension.groovy @@ -7,26 +7,24 @@ import org.spockframework.runtime.model.SpecInfo class TestcontainersExtension extends AbstractAnnotationDrivenExtension { - @Override - void visitSpecAnnotation(Testcontainers annotation, SpecInfo spec) { - def listener = new ErrorListener() - def interceptor = new TestcontainersMethodInterceptor(spec, listener) - spec.addSetupSpecInterceptor(interceptor) - spec.addCleanupSpecInterceptor(interceptor) - spec.addSetupInterceptor(interceptor) - spec.addCleanupInterceptor(interceptor) - - spec.addListener(listener) - - } - - private class ErrorListener extends AbstractRunListener { - List errors = [] - - @Override - void error(ErrorInfo error) { - errors.add(error) - } - } - + @Override + void visitSpecAnnotation(Testcontainers annotation, SpecInfo spec) { + def listener = new ErrorListener() + def interceptor = new TestcontainersMethodInterceptor(spec, listener) + spec.addSetupSpecInterceptor(interceptor) + spec.addCleanupSpecInterceptor(interceptor) + spec.addSetupInterceptor(interceptor) + spec.addCleanupInterceptor(interceptor) + + spec.addListener(listener) + } + + private class ErrorListener extends AbstractRunListener { + List errors = [] + + @Override + void error(ErrorInfo error) { + errors.add(error) + } + } } diff --git a/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersMethodInterceptor.groovy b/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersMethodInterceptor.groovy index 16be002aeb1..2399a0a6e32 100644 --- a/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersMethodInterceptor.groovy +++ b/modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersMethodInterceptor.groovy @@ -11,116 +11,116 @@ import org.testcontainers.spock.TestcontainersExtension.ErrorListener class TestcontainersMethodInterceptor extends AbstractMethodInterceptor { - private final SpecInfo spec - private final ErrorListener errorListener - - TestcontainersMethodInterceptor(SpecInfo spec, ErrorListener errorListener) { - this.spec = spec - this.errorListener = errorListener - } - - @Override - void interceptSetupSpecMethod(IMethodInvocation invocation) throws Throwable { - def containers = findAllContainers(true) - startContainers(containers, invocation) - - def compose = findAllComposeContainers(true) - startComposeContainers(compose, invocation) - - invocation.proceed() - } - - @Override - void interceptCleanupSpecMethod(IMethodInvocation invocation) throws Throwable { - def containers = findAllContainers(true) - stopContainers(containers, invocation) - - def compose = findAllComposeContainers(true) - stopComposeContainers(compose, invocation) - - invocation.proceed() - } - - @Override - void interceptSetupMethod(IMethodInvocation invocation) throws Throwable { - def containers = findAllContainers(false) - startContainers(containers, invocation) - - def compose = findAllComposeContainers(false) - startComposeContainers(compose, invocation) - - invocation.proceed() - } - - - @Override - void interceptCleanupMethod(IMethodInvocation invocation) throws Throwable { - def containers = findAllContainers(false) - stopContainers(containers, invocation) - - def compose = findAllComposeContainers(false) - stopComposeContainers(compose, invocation) - - invocation.proceed() - } - - private List findAllContainers(boolean shared) { - spec.allFields.findAll { FieldInfo f -> - GenericContainer.isAssignableFrom(f.type) && f.shared == shared - } - } - - private List findAllComposeContainers(boolean shared) { - spec.allFields.findAll { FieldInfo f -> - DockerComposeContainer.isAssignableFrom(f.type) && f.shared == shared - } - } - - private static void startContainers(List containers, IMethodInvocation invocation) { - containers.each { FieldInfo f -> - GenericContainer container = readContainerFromField(f, invocation) - if(!container.isRunning()){ - container.start() - } - - if (container instanceof TestLifecycleAware) { - def testDescription = SpockTestDescription.fromTestDescription(invocation) - (container as TestLifecycleAware).beforeTest(testDescription) - } - } - } - - private void stopContainers(List containers, IMethodInvocation invocation) { - containers.each { FieldInfo f -> - GenericContainer container = readContainerFromField(f, invocation) - - if (container instanceof TestLifecycleAware) { - // we assume first error is the one we want - def maybeException = Optional.ofNullable(errorListener.errors[0]?.exception) - def testDescription = SpockTestDescription.fromTestDescription(invocation) - (container as TestLifecycleAware).afterTest(testDescription, maybeException) - } - - container.stop() - } - } - - private static void startComposeContainers(List compose, IMethodInvocation invocation) { - compose.each { FieldInfo f -> - DockerComposeContainer c = f.readValue(invocation.instance) as DockerComposeContainer - c.start() - } - } - - private static void stopComposeContainers(List compose, IMethodInvocation invocation) { - compose.each { FieldInfo f -> - DockerComposeContainer c = f.readValue(invocation.instance) as DockerComposeContainer - c.stop() - } - } - - - private static GenericContainer readContainerFromField(FieldInfo f, IMethodInvocation invocation) { - f.readValue(invocation.instance) as GenericContainer - } + private final SpecInfo spec + private final ErrorListener errorListener + + TestcontainersMethodInterceptor(SpecInfo spec, ErrorListener errorListener) { + this.spec = spec + this.errorListener = errorListener + } + + @Override + void interceptSetupSpecMethod(IMethodInvocation invocation) throws Throwable { + def containers = findAllContainers(true) + startContainers(containers, invocation) + + def compose = findAllComposeContainers(true) + startComposeContainers(compose, invocation) + + invocation.proceed() + } + + @Override + void interceptCleanupSpecMethod(IMethodInvocation invocation) throws Throwable { + def containers = findAllContainers(true) + stopContainers(containers, invocation) + + def compose = findAllComposeContainers(true) + stopComposeContainers(compose, invocation) + + invocation.proceed() + } + + @Override + void interceptSetupMethod(IMethodInvocation invocation) throws Throwable { + def containers = findAllContainers(false) + startContainers(containers, invocation) + + def compose = findAllComposeContainers(false) + startComposeContainers(compose, invocation) + + invocation.proceed() + } + + + @Override + void interceptCleanupMethod(IMethodInvocation invocation) throws Throwable { + def containers = findAllContainers(false) + stopContainers(containers, invocation) + + def compose = findAllComposeContainers(false) + stopComposeContainers(compose, invocation) + + invocation.proceed() + } + + private List findAllContainers(boolean shared) { + spec.allFields.findAll { FieldInfo f -> + GenericContainer.isAssignableFrom(f.type) && f.shared == shared + } + } + + private List findAllComposeContainers(boolean shared) { + spec.allFields.findAll { FieldInfo f -> + DockerComposeContainer.isAssignableFrom(f.type) && f.shared == shared + } + } + + private static void startContainers(List containers, IMethodInvocation invocation) { + containers.each { FieldInfo f -> + GenericContainer container = readContainerFromField(f, invocation) + if(!container.isRunning()){ + container.start() + } + + if (container instanceof TestLifecycleAware) { + def testDescription = SpockTestDescription.fromTestDescription(invocation) + (container as TestLifecycleAware).beforeTest(testDescription) + } + } + } + + private void stopContainers(List containers, IMethodInvocation invocation) { + containers.each { FieldInfo f -> + GenericContainer container = readContainerFromField(f, invocation) + + if (container instanceof TestLifecycleAware) { + // we assume first error is the one we want + def maybeException = Optional.ofNullable(errorListener.errors[0]?.exception) + def testDescription = SpockTestDescription.fromTestDescription(invocation) + (container as TestLifecycleAware).afterTest(testDescription, maybeException) + } + + container.stop() + } + } + + private static void startComposeContainers(List compose, IMethodInvocation invocation) { + compose.each { FieldInfo f -> + DockerComposeContainer c = f.readValue(invocation.instance) as DockerComposeContainer + c.start() + } + } + + private static void stopComposeContainers(List compose, IMethodInvocation invocation) { + compose.each { FieldInfo f -> + DockerComposeContainer c = f.readValue(invocation.instance) as DockerComposeContainer + c.stop() + } + } + + + private static GenericContainer readContainerFromField(FieldInfo f, IMethodInvocation invocation) { + f.readValue(invocation.instance) as GenericContainer + } } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/ComposeContainerIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/ComposeContainerIT.groovy index b952dd1c5dc..7294d534275 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/ComposeContainerIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/ComposeContainerIT.groovy @@ -9,27 +9,27 @@ import spock.lang.Specification @Testcontainers class ComposeContainerIT extends Specification { - DockerComposeContainer composeContainer = new DockerComposeContainer( - new File("src/test/resources/docker-compose.yml")) - .withExposedService("whoami_1", 80, Wait.forHttp("/")) + DockerComposeContainer composeContainer = new DockerComposeContainer( + new File("src/test/resources/docker-compose.yml")) + .withExposedService("whoami_1", 80, Wait.forHttp("/")) - String host + String host - int port + int port - def setup() { - host = composeContainer.getServiceHost("whoami_1", 80) - port = composeContainer.getServicePort("whoami_1", 80) - } + def setup() { + host = composeContainer.getServiceHost("whoami_1", 80) + port = composeContainer.getServicePort("whoami_1", 80) + } - def "running compose defined container is accessible on configured port"() { - given: "a http client" - def client = HttpClientBuilder.create().build() + def "running compose defined container is accessible on configured port"() { + given: "a http client" + def client = HttpClientBuilder.create().build() - when: "accessing web server" - def response = client.execute(new HttpGet("http://$host:$port")) + when: "accessing web server" + def response = client.execute(new HttpGet("http://$host:$port")) - then: "docker container is running and returns http status code 200" - response.statusLine.statusCode == 200 - } + then: "docker container is running and returns http status code 200" + response.statusLine.statusCode == 200 + } } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/MySqlContainerIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/MySqlContainerIT.groovy index 639b46f5886..2f44408fed6 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/MySqlContainerIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/MySqlContainerIT.groovy @@ -14,13 +14,11 @@ import spock.lang.Specification @Testcontainers class MySqlContainerIT extends Specification { - @Shared - MySQLContainer mySQLContainer = new MySQLContainer(SpockTestImages.MYSQL_IMAGE) - - def "dummy test"() { - expect: - mySQLContainer.isRunning() - } - + @Shared + MySQLContainer mySQLContainer = new MySQLContainer(SpockTestImages.MYSQL_IMAGE) + def "dummy test"() { + expect: + mySQLContainer.isRunning() + } } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/PostgresContainerIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/PostgresContainerIT.groovy index a886d552732..19edca4b459 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/PostgresContainerIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/PostgresContainerIT.groovy @@ -13,34 +13,34 @@ import java.sql.Statement @Testcontainers class PostgresContainerIT extends Specification { - @Shared - PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer(SpockTestImages.POSTGRES_TEST_IMAGE) - .withDatabaseName("foo") - .withUsername("foo") - .withPassword("secret") - - def "waits until postgres accepts jdbc connections"() { - - given: "a jdbc connection" - HikariConfig hikariConfig = new HikariConfig() - hikariConfig.setJdbcUrl(postgreSQLContainer.jdbcUrl) - hikariConfig.setUsername("foo") - hikariConfig.setPassword("secret") - HikariDataSource ds = new HikariDataSource(hikariConfig) - - when: "querying the database" - Statement statement = ds.getConnection().createStatement() - statement.execute("SELECT 1") - ResultSet resultSet = statement.getResultSet() - resultSet.next() - - then: "result is returned" - int resultSetInt = resultSet.getInt(1) - resultSetInt == 1 - - cleanup: - ds.close() - } + @Shared + PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer(SpockTestImages.POSTGRES_TEST_IMAGE) + .withDatabaseName("foo") + .withUsername("foo") + .withPassword("secret") + + def "waits until postgres accepts jdbc connections"() { + + given: "a jdbc connection" + HikariConfig hikariConfig = new HikariConfig() + hikariConfig.setJdbcUrl(postgreSQLContainer.jdbcUrl) + hikariConfig.setUsername("foo") + hikariConfig.setPassword("secret") + HikariDataSource ds = new HikariDataSource(hikariConfig) + + when: "querying the database" + Statement statement = ds.getConnection().createStatement() + statement.execute("SELECT 1") + ResultSet resultSet = statement.getResultSet() + resultSet.next() + + then: "result is returned" + int resultSetInt = resultSet.getInt(1) + resultSetInt == 1 + + cleanup: + ds.close() + } } // } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/SharedComposeContainerIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/SharedComposeContainerIT.groovy index dd2ce9f5b3c..f728212278f 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/SharedComposeContainerIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/SharedComposeContainerIT.groovy @@ -10,28 +10,28 @@ import spock.lang.Specification @Testcontainers class SharedComposeContainerIT extends Specification { - @Shared - DockerComposeContainer composeContainer = new DockerComposeContainer( - new File("src/test/resources/docker-compose.yml")) - .withExposedService("whoami_1", 80, Wait.forHttp("/")) + @Shared + DockerComposeContainer composeContainer = new DockerComposeContainer( + new File("src/test/resources/docker-compose.yml")) + .withExposedService("whoami_1", 80, Wait.forHttp("/")) - String host + String host - int port + int port - def setup() { - host = composeContainer.getServiceHost("whoami_1", 80) - port = composeContainer.getServicePort("whoami_1", 80) - } + def setup() { + host = composeContainer.getServiceHost("whoami_1", 80) + port = composeContainer.getServicePort("whoami_1", 80) + } - def "running compose defined container is accessible on configured port"() { - given: "a http client" - def client = HttpClientBuilder.create().build() + def "running compose defined container is accessible on configured port"() { + given: "a http client" + def client = HttpClientBuilder.create().build() - when: "accessing web server" - def response = client.execute(new HttpGet("http://$host:$port")) + when: "accessing web server" + def response = client.execute(new HttpGet("http://$host:$port")) - then: "docker container is running and returns http status code 200" - response.statusLine.statusCode == 200 - } + then: "docker container is running and returns http status code 200" + response.statusLine.statusCode == 200 + } } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/SpockTestImages.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/SpockTestImages.groovy index b9ef64fe475..41432e5e514 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/SpockTestImages.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/SpockTestImages.groovy @@ -3,8 +3,8 @@ package org.testcontainers.spock import org.testcontainers.utility.DockerImageName interface SpockTestImages { - DockerImageName MYSQL_IMAGE = DockerImageName.parse("mysql:5.7.34") - DockerImageName POSTGRES_TEST_IMAGE = DockerImageName.parse("postgres:9.6.12") - DockerImageName HTTPD_IMAGE = DockerImageName.parse("httpd:2.4-alpine") - DockerImageName TINY_IMAGE = DockerImageName.parse("alpine:3.14") + DockerImageName MYSQL_IMAGE = DockerImageName.parse("mysql:5.7.34") + DockerImageName POSTGRES_TEST_IMAGE = DockerImageName.parse("postgres:9.6.12") + DockerImageName HTTPD_IMAGE = DockerImageName.parse("httpd:2.4-alpine") + DockerImageName TINY_IMAGE = DockerImageName.parse("alpine:3.14") } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/TestHierarchyIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/TestHierarchyIT.groovy index c28643910a4..567998281a7 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/TestHierarchyIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/TestHierarchyIT.groovy @@ -9,17 +9,15 @@ import spock.lang.Shared */ class TestHierarchyIT extends MySqlContainerIT { - @Shared - PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer(SpockTestImages.POSTGRES_TEST_IMAGE) - .withDatabaseName("foo") - .withUsername("foo") - .withPassword("secret") - - def "both containers are running"() { - expect: - postgreSQLContainer.isRunning() - mySQLContainer.isRunning() - - } + @Shared + PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer(SpockTestImages.POSTGRES_TEST_IMAGE) + .withDatabaseName("foo") + .withUsername("foo") + .withPassword("secret") + def "both containers are running"() { + expect: + postgreSQLContainer.isRunning() + mySQLContainer.isRunning() + } } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareContainerMock.java b/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareContainerMock.java index eb628fd2f33..7502d097008 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareContainerMock.java +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareContainerMock.java @@ -8,20 +8,22 @@ import java.util.List; import java.util.Optional; -import static org.testcontainers.spock.SpockTestImages.TINY_IMAGE; - -public class TestLifecycleAwareContainerMock extends GenericContainer implements TestLifecycleAware { +public class TestLifecycleAwareContainerMock + extends GenericContainer + implements TestLifecycleAware { static final String BEFORE_TEST = "beforeTest"; + static final String AFTER_TEST = "afterTest"; final List lifecycleMethodCalls = new ArrayList<>(); + final List lifecycleFilesystemFriendlyNames = new ArrayList<>(); Throwable capturedThrowable; public TestLifecycleAwareContainerMock() { - super(TINY_IMAGE); + super(SpockTestImages.TINY_IMAGE); } @Override diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareIT.groovy index 18f7517ea3f..fae834ea422 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/TestLifecycleAwareIT.groovy @@ -7,12 +7,12 @@ import spock.util.EmbeddedSpecRunner class TestLifecycleAwareIT extends Specification { - @Unroll("When failing test is #fails, afterTest receives '#filesystemFriendlyNames' and throwable starting with message '#errorMessageStartsWith'") - def "lifecycle awareness"() { - given: + @Unroll("When failing test is #fails, afterTest receives '#filesystemFriendlyNames' and throwable starting with message '#errorMessageStartsWith'") + def "lifecycle awareness"() { + given: - @Language("groovy") - String myTest = """ + @Language("groovy") + String myTest = """ import org.testcontainers.spock.Testcontainers import org.testcontainers.containers.GenericContainer import spock.lang.Specification @@ -28,28 +28,27 @@ class TestLifecycleAwareIT extends Specification { } } """ - and: - def container = new TestLifecycleAwareContainerMock() - System.properties["org.testcontainers.container"] = container - System.properties["org.testcontainers.shouldFail"] = fails - - when: "executing the test" - def runner = new EmbeddedSpecRunner(throwFailure: false) - runner.run(myTest) - - then: "mock container received lifecycle calls as expected" - container.lifecycleMethodCalls == ["beforeTest", "afterTest"] - container.lifecycleFilesystemFriendlyNames.join(",") == filesystemFriendlyNames - if (errorMessageStartsWith) { - assert container.capturedThrowable.message.startsWith(errorMessageStartsWith) - } else { - assert container.capturedThrowable == null - } - - where: - fails | filesystemFriendlyNames | errorMessageStartsWith - false | 'TestLifecycleAwareIT-perform+test' | null - true | 'TestLifecycleAwareIT-perform+test' | "Condition not satisfied:" - } - + and: + def container = new TestLifecycleAwareContainerMock() + System.properties["org.testcontainers.container"] = container + System.properties["org.testcontainers.shouldFail"] = fails + + when: "executing the test" + def runner = new EmbeddedSpecRunner(throwFailure: false) + runner.run(myTest) + + then: "mock container received lifecycle calls as expected" + container.lifecycleMethodCalls == ["beforeTest", "afterTest"] + container.lifecycleFilesystemFriendlyNames.join(",") == filesystemFriendlyNames + if (errorMessageStartsWith) { + assert container.capturedThrowable.message.startsWith(errorMessageStartsWith) + } else { + assert container.capturedThrowable == null + } + + where: + fails | filesystemFriendlyNames | errorMessageStartsWith + false | 'TestLifecycleAwareIT-perform+test' | null + true | 'TestLifecycleAwareIT-perform+test' | "Condition not satisfied:" + } } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersRestartBetweenTestsIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersRestartBetweenTestsIT.groovy index 81ed0eea724..ebbb1de2474 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersRestartBetweenTestsIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersRestartBetweenTestsIT.groovy @@ -9,23 +9,22 @@ import spock.lang.Stepwise @Testcontainers class TestcontainersRestartBetweenTestsIT extends Specification { - GenericContainer genericContainer = new GenericContainer(SpockTestImages.HTTPD_IMAGE) - .withExposedPorts(80) + GenericContainer genericContainer = new GenericContainer(SpockTestImages.HTTPD_IMAGE) + .withExposedPorts(80) - @Shared - String lastContainerId + @Shared + String lastContainerId - def "retrieving first id"() { - when: - lastContainerId = genericContainer.containerId + def "retrieving first id"() { + when: + lastContainerId = genericContainer.containerId - then: - true - } - - def "containers is recreated between tests"() { - expect: - genericContainer.containerId != lastContainerId - } + then: + true + } + def "containers is recreated between tests"() { + expect: + genericContainer.containerId != lastContainerId + } } diff --git a/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersSharedContainerIT.groovy b/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersSharedContainerIT.groovy index 23b761fcc38..dd2f8443772 100644 --- a/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersSharedContainerIT.groovy +++ b/modules/spock/src/test/groovy/org/testcontainers/spock/TestcontainersSharedContainerIT.groovy @@ -13,35 +13,34 @@ import spock.lang.Stepwise @Testcontainers class TestcontainersSharedContainerIT extends Specification { - @Shared - GenericContainer genericContainer = new GenericContainer(SpockTestImages.HTTPD_IMAGE) - .withExposedPorts(80) - - @Shared - String lastContainerId - - def "starts accessible docker container"() { - given: "a http client" - def client = HttpClientBuilder.create().build() - lastContainerId = genericContainer.containerId - - when: "accessing web server" - CloseableHttpResponse response = performHttpRequest(client) - - then: "docker container is running and returns http status code 200" - response.statusLine.statusCode == 200 - } - - def "containers keeps on running between features"() { - expect: - genericContainer.containerId == lastContainerId - } - - private CloseableHttpResponse performHttpRequest(CloseableHttpClient client) { - String ip = genericContainer.host - String port = genericContainer.getMappedPort(80) - def response = client.execute(new HttpGet("http://$ip:$port")) - response - } - + @Shared + GenericContainer genericContainer = new GenericContainer(SpockTestImages.HTTPD_IMAGE) + .withExposedPorts(80) + + @Shared + String lastContainerId + + def "starts accessible docker container"() { + given: "a http client" + def client = HttpClientBuilder.create().build() + lastContainerId = genericContainer.containerId + + when: "accessing web server" + CloseableHttpResponse response = performHttpRequest(client) + + then: "docker container is running and returns http status code 200" + response.statusLine.statusCode == 200 + } + + def "containers keeps on running between features"() { + expect: + genericContainer.containerId == lastContainerId + } + + private CloseableHttpResponse performHttpRequest(CloseableHttpClient client) { + String ip = genericContainer.host + String port = genericContainer.getMappedPort(80) + def response = client.execute(new HttpGet("http://$ip:$port")) + response + } } diff --git a/modules/toxiproxy/src/main/java/org/testcontainers/containers/ToxiproxyContainer.java b/modules/toxiproxy/src/main/java/org/testcontainers/containers/ToxiproxyContainer.java index e22cc1fdd55..ed8413a2a31 100644 --- a/modules/toxiproxy/src/main/java/org/testcontainers/containers/ToxiproxyContainer.java +++ b/modules/toxiproxy/src/main/java/org/testcontainers/containers/ToxiproxyContainer.java @@ -22,13 +22,19 @@ public class ToxiproxyContainer extends GenericContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("shopify/toxiproxy"); + private static final String DEFAULT_TAG = "2.1.0"; + private static final int TOXIPROXY_CONTROL_PORT = 8474; + private static final int FIRST_PROXIED_PORT = 8666; + private static final int LAST_PROXIED_PORT = 8666 + 31; private ToxiproxyClient client; + private final Map proxies = new HashMap<>(); + private final AtomicInteger nextPort = new AtomicInteger(FIRST_PROXIED_PORT); /** @@ -45,7 +51,6 @@ public ToxiproxyContainer(String dockerImageName) { public ToxiproxyContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); addExposedPorts(TOXIPROXY_CONTROL_PORT); @@ -99,42 +104,55 @@ public ContainerProxy getProxy(GenericContainer container, int port) { public ContainerProxy getProxy(String hostname, int port) { String upstream = hostname + ":" + port; - return proxies.computeIfAbsent(upstream, __ -> { - try { - final int toxiPort = nextPort.getAndIncrement(); - if (toxiPort > LAST_PROXIED_PORT) { - throw new IllegalStateException("Maximum number of proxies exceeded"); + return proxies.computeIfAbsent( + upstream, + __ -> { + try { + final int toxiPort = nextPort.getAndIncrement(); + if (toxiPort > LAST_PROXIED_PORT) { + throw new IllegalStateException("Maximum number of proxies exceeded"); + } + + final Proxy proxy = client.createProxy(upstream, "0.0.0.0:" + toxiPort, upstream); + final int mappedPort = getMappedPort(toxiPort); + return new ContainerProxy(proxy, getHost(), mappedPort, toxiPort); + } catch (IOException e) { + throw new RuntimeException("Proxy could not be created", e); } - - final Proxy proxy = client.createProxy(upstream, "0.0.0.0:" + toxiPort, upstream); - final int mappedPort = getMappedPort(toxiPort); - return new ContainerProxy(proxy, getHost(), mappedPort, toxiPort); - } catch (IOException e) { - throw new RuntimeException("Proxy could not be created", e); } - }); + ); } @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public static class ContainerProxy { + private static final String CUT_CONNECTION_DOWNSTREAM = "CUT_CONNECTION_DOWNSTREAM"; + private static final String CUT_CONNECTION_UPSTREAM = "CUT_CONNECTION_UPSTREAM"; + private final Proxy toxi; + /** * The IP address that this proxy container may be reached on from the host machine. */ - @Getter private final String containerIpAddress; + @Getter + private final String containerIpAddress; + /** * The mapped port of this proxy. This is a port of the host machine. It can be used to * access the Toxiproxy container from the host machine. */ - @Getter private final int proxyPort; + @Getter + private final int proxyPort; + /** * The original (exposed) port of this proxy. This is a port of the Toxiproxy Docker * container. It can be used to access this container from a different Docker container * on the same network. */ - @Getter private final int originalProxyPort; + @Getter + private final int originalProxyPort; + private boolean isCurrentlyCut; public String getName() { diff --git a/modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java b/modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java index 3177fb2e8e8..c5982bc45c1 100644 --- a/modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java +++ b/modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.time.Duration; -import static java.lang.String.format; import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; import static org.rnorth.visibleassertions.VisibleAssertions.assertThrows; import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; @@ -19,6 +18,7 @@ public class ToxiproxyTest { private static final Duration JEDIS_TIMEOUT = Duration.ofSeconds(10); + // spotless:off // creatingProxy { // An alias that can be used to resolve the Toxiproxy container by name in the network it is connected to. // It can be used as a hostname of the Toxiproxy container by other containers in the same network. @@ -29,6 +29,7 @@ public class ToxiproxyTest { public Network network = Network.newNetwork(); private static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis:5.0.4"); + // The target container - this could be anything @Rule public GenericContainer redis = new GenericContainer<>(REDIS_IMAGE) @@ -36,12 +37,15 @@ public class ToxiproxyTest { .withNetwork(network); private static final DockerImageName TOXIPROXY_IMAGE = DockerImageName.parse("shopify/toxiproxy:2.1.0"); + // Toxiproxy container, which will be used as a TCP proxy @Rule public ToxiproxyContainer toxiproxy = new ToxiproxyContainer(TOXIPROXY_IMAGE) .withNetwork(network) .withNetworkAliases(TOXIPROXY_NETWORK_ALIAS); + // } + // spotless:on @Test public void testDirect() { @@ -68,12 +72,14 @@ public void testLatencyViaProxy() throws IOException { checkCallWithLatency(jedis, "without interference", 0, 250); + // spotless:off // addingLatency { proxy.toxics() .latency("latency", ToxicDirection.DOWNSTREAM, 1_100) .setJitter(100); // from now on the connection latency should be from 1000-1200 ms. // } + // spotless:on checkCallWithLatency(jedis, "with interference", 1_000, 1_500); } @@ -84,30 +90,42 @@ public void testConnectionCut() { final Jedis jedis = createJedis(proxy.getContainerIpAddress(), proxy.getProxyPort()); jedis.set("somekey", "somevalue"); - assertEquals("access to the container works OK before cutting the connection", "somevalue", jedis.get("somekey")); + assertEquals( + "access to the container works OK before cutting the connection", + "somevalue", + jedis.get("somekey") + ); // disableProxy { proxy.setConnectionCut(true); // for example, expect failure when the connection is cut - assertThrows("calls fail when the connection is cut", - JedisConnectionException.class, () -> { + assertThrows( + "calls fail when the connection is cut", + JedisConnectionException.class, + () -> { jedis.get("somekey"); - }); + } + ); proxy.setConnectionCut(false); // and with the connection re-established, expect success - assertEquals("access to the container works OK after re-establishing the connection", "somevalue", jedis.get("somekey")); + assertEquals( + "access to the container works OK after re-establishing the connection", + "somevalue", + jedis.get("somekey") + ); // } } @Test public void testMultipleProxiesCanBeCreated() { - try (GenericContainer secondRedis = new GenericContainer<>(REDIS_IMAGE) - .withExposedPorts(6379) - .withNetwork(network)) { - + try ( + GenericContainer secondRedis = new GenericContainer<>(REDIS_IMAGE) + .withExposedPorts(6379) + .withNetwork(network) + ) { secondRedis.start(); final ToxiproxyContainer.ContainerProxy firstProxy = toxiproxy.getProxy(redis, 6379); @@ -121,10 +139,13 @@ public void testMultipleProxiesCanBeCreated() { firstProxy.setConnectionCut(true); - assertThrows("calls fail when the connection is cut, for only the relevant proxy", - JedisConnectionException.class, () -> { + assertThrows( + "calls fail when the connection is cut, for only the relevant proxy", + JedisConnectionException.class, + () -> { firstJedis.get("somekey"); - }); + } + ); assertEquals("access via a different proxy is OK", "somevalue", secondJedis.get("somekey")); } @@ -142,11 +163,19 @@ public void testOriginalAndMappedPorts() { final ToxiproxyContainer.ContainerProxy proxy1 = toxiproxy.getProxy("hostname1", 8080); assertEquals("original port is correct", 8667, proxy1.getOriginalProxyPort()); - assertEquals("mapped port is correct", toxiproxy.getMappedPort(proxy1.getOriginalProxyPort()), proxy1.getProxyPort()); + assertEquals( + "mapped port is correct", + toxiproxy.getMappedPort(proxy1.getOriginalProxyPort()), + proxy1.getProxyPort() + ); final ToxiproxyContainer.ContainerProxy proxy2 = toxiproxy.getProxy("hostname2", 9090); assertEquals("original port is correct", 8668, proxy2.getOriginalProxyPort()); - assertEquals("mapped port is correct", toxiproxy.getMappedPort(proxy2.getOriginalProxyPort()), proxy2.getProxyPort()); + assertEquals( + "mapped port is correct", + toxiproxy.getMappedPort(proxy2.getOriginalProxyPort()), + proxy2.getProxyPort() + ); } @Test @@ -163,15 +192,26 @@ public void testControlPort() { assertEquals("control port is mapped from port 8474", toxiproxy.getMappedPort(8474), controlPort); } - private void checkCallWithLatency(Jedis jedis, final String description, int expectedMinLatency, long expectedMaxLatency) { + private void checkCallWithLatency( + Jedis jedis, + final String description, + int expectedMinLatency, + long expectedMaxLatency + ) { final long start = System.currentTimeMillis(); String s = jedis.get("somekey"); final long end = System.currentTimeMillis(); final long duration = end - start; - assertEquals(format("access to the container %s works OK", description), "somevalue", s); - assertTrue(format("%s there is at least %dms latency", description, expectedMinLatency), duration >= expectedMinLatency); - assertTrue(format("%s there is no more than %dms latency", description, expectedMaxLatency), duration < expectedMaxLatency); + assertEquals(String.format("access to the container %s works OK", description), "somevalue", s); + assertTrue( + String.format("%s there is at least %dms latency", description, expectedMinLatency), + duration >= expectedMinLatency + ); + assertTrue( + String.format("%s there is no more than %dms latency", description, expectedMaxLatency), + duration < expectedMaxLatency + ); } private static Jedis createJedis(String host, int port) { diff --git a/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainer.java b/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainer.java index 825340459f3..9ed18e96d28 100644 --- a/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainer.java +++ b/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainer.java @@ -1,5 +1,6 @@ package org.testcontainers.containers; +import com.google.common.base.Strings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.VisibleForTesting; import org.testcontainers.utility.DockerImageName; @@ -9,19 +10,21 @@ import java.util.HashSet; import java.util.Set; -import static com.google.common.base.Strings.nullToEmpty; -import static java.lang.String.format; - public class TrinoContainer extends JdbcDatabaseContainer { + static final String NAME = "trino"; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("trinodb/trino"); + static final String IMAGE = "trinodb/trino"; + @VisibleForTesting static final String DEFAULT_TAG = "352"; private static final int TRINO_PORT = 8080; private String username = "test"; + private String catalog = null; public TrinoContainer(final String dockerImageName) { @@ -30,7 +33,6 @@ public TrinoContainer(final String dockerImageName) { public TrinoContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); addExposedPort(TRINO_PORT); } @@ -48,7 +50,12 @@ public String getDriverClassName() { @Override public String getJdbcUrl() { - return format("jdbc:trino://%s:%s/%s", getHost(), getMappedPort(TRINO_PORT), nullToEmpty(catalog)); + return String.format( + "jdbc:trino://%s:%s/%s", + getHost(), + getMappedPort(TRINO_PORT), + Strings.nullToEmpty(catalog) + ); } @Override diff --git a/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainerProvider.java b/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainerProvider.java index 233fc1b9b07..30d877c9e4a 100644 --- a/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainerProvider.java +++ b/modules/trino/src/main/java/org/testcontainers/containers/TrinoContainerProvider.java @@ -6,6 +6,7 @@ * Factory for Trino containers. */ public class TrinoContainerProvider extends JdbcDatabaseContainerProvider { + @Override public boolean supports(String databaseType) { return databaseType.equals(TrinoContainer.NAME); diff --git a/modules/trino/src/test/java/org/testcontainers/containers/TrinoContainerTest.java b/modules/trino/src/test/java/org/testcontainers/containers/TrinoContainerTest.java index d7f8014ca9a..97bbdf6dedd 100644 --- a/modules/trino/src/test/java/org/testcontainers/containers/TrinoContainerTest.java +++ b/modules/trino/src/test/java/org/testcontainers/containers/TrinoContainerTest.java @@ -1,20 +1,12 @@ package org.testcontainers.containers; -import org.junit.Assert; import org.junit.Test; import org.testcontainers.TrinoTestImages; import java.sql.Connection; -import java.sql.DriverManager; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import static java.lang.Integer.parseInt; -import static java.lang.String.format; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -25,9 +17,11 @@ public class TrinoContainerTest { public void testSimple() throws Exception { try (TrinoContainer trino = new TrinoContainer(TrinoTestImages.TRINO_TEST_IMAGE)) { trino.start(); - try (Connection connection = trino.createConnection(); - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes")) { + try ( + Connection connection = trino.createConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes") + ) { assertTrue("No result", resultSet.next()); assertEquals("Trino version", TrinoContainer.DEFAULT_TAG, resultSet.getString("node_version")); } @@ -38,11 +32,17 @@ public void testSimple() throws Exception { public void testSpecificVersion() throws Exception { try (TrinoContainer trino = new TrinoContainer(TrinoTestImages.TRINO_PREVIOUS_VERSION_TEST_IMAGE)) { trino.start(); - try (Connection connection = trino.createConnection(); - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes")) { + try ( + Connection connection = trino.createConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT DISTINCT node_version FROM system.runtime.nodes") + ) { assertTrue("No result", resultSet.next()); - assertEquals("Trino version", TrinoTestImages.TRINO_PREVIOUS_VERSION_TEST_IMAGE.getVersionPart(), resultSet.getString("node_version")); + assertEquals( + "Trino version", + TrinoTestImages.TRINO_PREVIOUS_VERSION_TEST_IMAGE.getVersionPart(), + resultSet.getString("node_version") + ); } } } @@ -52,9 +52,11 @@ public void testInitScript() throws Exception { try (TrinoContainer trino = new TrinoContainer(TrinoTestImages.TRINO_TEST_IMAGE)) { trino.withInitScript("initial.sql"); trino.start(); - try (Connection connection = trino.createConnection(); - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("SELECT a FROM memory.default.test_table")) { + try ( + Connection connection = trino.createConnection(); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT a FROM memory.default.test_table") + ) { assertTrue("No result", resultSet.next()); assertEquals("Value", 12345678909324L, resultSet.getObject("a")); assertFalse("Too many result", resultSet.next()); diff --git a/modules/trino/src/test/java/org/testcontainers/jdbc/trino/TrinoJDBCDriverTest.java b/modules/trino/src/test/java/org/testcontainers/jdbc/trino/TrinoJDBCDriverTest.java index 8f06aef7278..9ec98c2e6d7 100644 --- a/modules/trino/src/test/java/org/testcontainers/jdbc/trino/TrinoJDBCDriverTest.java +++ b/modules/trino/src/test/java/org/testcontainers/jdbc/trino/TrinoJDBCDriverTest.java @@ -4,18 +4,18 @@ import org.junit.runners.Parameterized; import org.testcontainers.jdbc.AbstractJDBCDriverTest; +import java.util.Arrays; import java.util.EnumSet; -import static java.util.Arrays.asList; - @RunWith(Parameterized.class) public class TrinoJDBCDriverTest extends AbstractJDBCDriverTest { @Parameterized.Parameters(name = "{index} - {0}") public static Iterable data() { - return asList( - new Object[][]{ - {"jdbc:tc:trino:352://hostname/", EnumSet.of(Options.PmdKnownBroken)}, - }); + return Arrays.asList( + new Object[][] { // + { "jdbc:tc:trino:352://hostname/", EnumSet.of(Options.PmdKnownBroken) }, + } + ); } } diff --git a/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java b/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java index 37e78a14f95..31bb1f31d9f 100644 --- a/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java +++ b/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java @@ -1,6 +1,7 @@ package org.testcontainers.vault; import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.Capability; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.DockerImageName; @@ -14,9 +15,6 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import static com.github.dockerjava.api.model.Capability.IPC_LOCK; - - /** * GenericContainer subclass for Vault specific configuration and features. The main feature is the * withSecretInVault method, where users can specify which secrets to be pre-loaded into Vault for @@ -27,11 +25,13 @@ public class VaultContainer> extends GenericContainer { private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("vault"); + private static final String DEFAULT_TAG = "1.1.3"; private static final int VAULT_PORT = 8200; private Map> secretsMap = new HashMap<>(); + private List initCommands = new ArrayList<>(); private int port = VAULT_PORT; @@ -50,13 +50,12 @@ public VaultContainer(String dockerImageName) { public VaultContainer(final DockerImageName dockerImageName) { super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); // Use the vault healthcheck endpoint to check for readiness, per https://www.vaultproject.io/api/system/health.html setWaitStrategy(Wait.forHttp("/v1/sys/health").forStatusCode(200)); - withCreateContainerCmdModifier(cmd -> cmd.withCapAdd(IPC_LOCK)); + withCreateContainerCmdModifier(cmd -> cmd.withCapAdd(Capability.IPC_LOCK)); withEnv("VAULT_ADDR", "http://0.0.0.0:" + port); withExposedPorts(port); } @@ -72,7 +71,12 @@ private void addSecrets() { try { this.execInContainer(buildExecCommand(secretsMap)).getStdout().contains("Success"); } catch (IOException | InterruptedException e) { - logger().error("Failed to add these secrets {} into Vault via exec command. Exception message: {}", secretsMap, e.getMessage()); + logger() + .error( + "Failed to add these secrets {} into Vault via exec command. Exception message: {}", + secretsMap, + e.getMessage() + ); } } } @@ -83,22 +87,34 @@ private String[] buildExecCommand(Map> map) { stringBuilder.append(" && vault kv put " + path); secrets.forEach(item -> stringBuilder.append(" " + item)); }); - return new String[]{"/bin/sh", "-c", stringBuilder.toString().substring(4)}; + return new String[] { "/bin/sh", "-c", stringBuilder.toString().substring(4) }; } private void runInitCommands() { if (!initCommands.isEmpty()) { - String commands = initCommands.stream() - .map(command -> "vault " + command) - .collect(Collectors.joining(" && ")); + String commands = initCommands + .stream() + .map(command -> "vault " + command) + .collect(Collectors.joining(" && ")); try { - ExecResult execResult = this.execInContainer(new String[]{"/bin/sh", "-c", commands}); + ExecResult execResult = this.execInContainer(new String[] { "/bin/sh", "-c", commands }); if (execResult.getExitCode() != 0) { - logger().error("Failed to execute these init commands {}. Exit code {}. Stdout {}. Stderr {}", - initCommands, execResult.getExitCode(), execResult.getStdout(), execResult.getStderr()); + logger() + .error( + "Failed to execute these init commands {}. Exit code {}. Stdout {}. Stderr {}", + initCommands, + execResult.getExitCode(), + execResult.getStdout(), + execResult.getStderr() + ); } } catch (IOException | InterruptedException e) { - logger().error("Failed to execute these init commands {}. Exception message: {}", initCommands, e.getMessage()); + logger() + .error( + "Failed to execute these init commands {}. Exception message: {}", + initCommands, + e.getMessage() + ); } } } @@ -166,7 +182,7 @@ public SELF withSecretInVault(String path, String firstSecret, String... remaini /** * Run initialization commands using the vault cli. - * + * * Useful for enableing more secret engines like: *

      *     .withInitCommand("secrets enable pki")
diff --git a/modules/vault/src/main/java/org/testcontainers/vault/VaultLogLevel.java b/modules/vault/src/main/java/org/testcontainers/vault/VaultLogLevel.java
index 58b22f975ff..e5f0db784a8 100644
--- a/modules/vault/src/main/java/org/testcontainers/vault/VaultLogLevel.java
+++ b/modules/vault/src/main/java/org/testcontainers/vault/VaultLogLevel.java
@@ -4,7 +4,11 @@
  * Vault preset of logging levels.
  */
 public enum VaultLogLevel {
-    Trace("trace"), Debug("debug"), Info("info"), Warn("warn"), Error("err");
+    Trace("trace"),
+    Debug("debug"),
+    Info("info"),
+    Warn("warn"),
+    Error("err");
 
     public final String config;
 
diff --git a/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java b/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java
index 4a1a800da17..cd1f1a8acea 100644
--- a/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java
+++ b/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java
@@ -10,7 +10,6 @@
 import java.util.Map;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.testcontainers.vault.VaultTestImages.VAULT_IMAGE;
 
 public class VaultClientTest {
 
@@ -19,10 +18,9 @@ public class VaultClientTest {
     @Test
     public void writeAndReadMultipleValues() throws VaultException {
         try (
-            VaultContainer vaultContainer = new VaultContainer<>(VAULT_IMAGE)
-                    .withVaultToken(VAULT_TOKEN)
+            VaultContainer vaultContainer = new VaultContainer<>(VaultTestImages.VAULT_IMAGE)
+                .withVaultToken(VAULT_TOKEN)
         ) {
-
             vaultContainer.start();
 
             final VaultConfig config = new VaultConfig()
@@ -37,22 +35,14 @@ public void writeAndReadMultipleValues() throws VaultException {
             secrets.put("other_value", "another world");
 
             // Write operation
-            final LogicalResponse writeResponse = vault.logical()
-                .write("secret/hello", secrets);
+            final LogicalResponse writeResponse = vault.logical().write("secret/hello", secrets);
 
             assertThat(writeResponse.getRestResponse().getStatus()).isEqualTo(200);
 
             // Read operation
-            final Map value = vault.logical()
-                .read("secret/hello")
-                .getData();
-
-
-            assertThat(value)
-                .containsEntry("value", "world")
-                .containsEntry("other_value", "another world");
+            final Map value = vault.logical().read("secret/hello").getData();
 
+            assertThat(value).containsEntry("value", "world").containsEntry("other_value", "another world");
         }
-
     }
 }
diff --git a/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java b/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java
index 9dee4c21416..22310bf7a23 100644
--- a/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java
+++ b/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java
@@ -7,7 +7,7 @@
 import java.io.IOException;
 
 import static io.restassured.RestAssured.given;
-import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.assertThat;
 
 /**
@@ -22,24 +22,38 @@ public class VaultContainerTest {
     public static VaultContainer vaultContainer = new VaultContainer<>(VaultTestImages.VAULT_IMAGE)
         .withVaultToken(VAULT_TOKEN)
         .withSecretInVault("secret/testing1", "top_secret=password123")
-        .withSecretInVault("secret/testing2",
+        .withSecretInVault(
+            "secret/testing2",
             "secret_one=password1",
             "secret_two=password2",
             "secret_three=password3",
             "secret_three=password3",
-            "secret_four=password4")
+            "secret_four=password4"
+        )
         .withInitCommand("secrets enable transit", "write -f transit/keys/my-key");
 
     @Test
     public void readFirstSecretPathWithCli() throws IOException, InterruptedException {
-        GenericContainer.ExecResult result = vaultContainer.execInContainer("vault", "kv", "get", "-format=json", "secret/testing1");
+        GenericContainer.ExecResult result = vaultContainer.execInContainer(
+            "vault",
+            "kv",
+            "get",
+            "-format=json",
+            "secret/testing1"
+        );
         final String output = result.getStdout().replaceAll("\\r?\\n", "");
         assertThat(output, containsString("password123"));
     }
 
     @Test
     public void readSecondSecretPathWithCli() throws IOException, InterruptedException {
-        GenericContainer.ExecResult result = vaultContainer.execInContainer("vault", "kv", "get", "-format=json", "secret/testing2");
+        GenericContainer.ExecResult result = vaultContainer.execInContainer(
+            "vault",
+            "kv",
+            "get",
+            "-format=json",
+            "secret/testing2"
+        );
         final String output = result.getStdout().replaceAll("\\r?\\n", "");
         System.out.println("output = " + output);
         assertThat(output, containsString("password1"));
@@ -50,40 +64,44 @@ public void readSecondSecretPathWithCli() throws IOException, InterruptedExcepti
 
     @Test
     public void readFirstSecretPathOverHttpApi() throws InterruptedException {
-        given().
-            header("X-Vault-Token", VAULT_TOKEN).
-            when().
-            get("http://" + getHostAndPort() + "/v1/secret/data/testing1").
-            then().
-            assertThat().body("data.data.top_secret", equalTo("password123"));
+        given()
+            .header("X-Vault-Token", VAULT_TOKEN)
+            .when()
+            .get("http://" + getHostAndPort() + "/v1/secret/data/testing1")
+            .then()
+            .assertThat()
+            .body("data.data.top_secret", equalTo("password123"));
     }
 
     @Test
     public void readSecondSecretPathOverHttpApi() throws InterruptedException {
-        given().
-            header("X-Vault-Token", VAULT_TOKEN).
-            when().
-            get("http://" + getHostAndPort() + "/v1/secret/data/testing2").
-            then().
-            assertThat().body("data.data.secret_one", containsString("password1")).
-            assertThat().body("data.data.secret_two", containsString("password2")).
-            assertThat().body("data.data.secret_three", hasItem("password3")).
-            assertThat().body("data.data.secret_four", containsString("password4"));
+        given()
+            .header("X-Vault-Token", VAULT_TOKEN)
+            .when()
+            .get("http://" + getHostAndPort() + "/v1/secret/data/testing2")
+            .then()
+            .assertThat()
+            .body("data.data.secret_one", containsString("password1"))
+            .assertThat()
+            .body("data.data.secret_two", containsString("password2"))
+            .assertThat()
+            .body("data.data.secret_three", hasItem("password3"))
+            .assertThat()
+            .body("data.data.secret_four", containsString("password4"));
     }
 
     @Test
     public void readTransitKeyOverHttpApi() throws InterruptedException {
-        given().
-            header("X-Vault-Token", VAULT_TOKEN).
-            when().
-            get("http://" + getHostAndPort() + "/v1/transit/keys/my-key").
-            then().
-            assertThat().body("data.name", equalTo("my-key"));
+        given()
+            .header("X-Vault-Token", VAULT_TOKEN)
+            .when()
+            .get("http://" + getHostAndPort() + "/v1/transit/keys/my-key")
+            .then()
+            .assertThat()
+            .body("data.name", equalTo("my-key"));
     }
 
     private String getHostAndPort() {
         return vaultContainer.getHost() + ":" + vaultContainer.getMappedPort(8200);
     }
-
-
 }
diff --git a/test-support/src/main/java/org/testcontainers/testsupport/Flaky.java b/test-support/src/main/java/org/testcontainers/testsupport/Flaky.java
index cc5f6f947fa..83e18bfa161 100644
--- a/test-support/src/main/java/org/testcontainers/testsupport/Flaky.java
+++ b/test-support/src/main/java/org/testcontainers/testsupport/Flaky.java
@@ -1,19 +1,17 @@
 package org.testcontainers.testsupport;
 
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
 /**
  * Annotation for test methods that should be retried in the event of failure. See {@link FlakyTestJUnit4RetryRule} for
  * more details.
  */
-@Retention(RUNTIME)
-@Target({METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
 public @interface Flaky {
-
     /**
      * @return a URL for a GitHub issue where this flaky test can be discussed, and where actions to resolve it can be
      * coordinated.
diff --git a/test-support/src/main/java/org/testcontainers/testsupport/FlakyTestJUnit4RetryRule.java b/test-support/src/main/java/org/testcontainers/testsupport/FlakyTestJUnit4RetryRule.java
index aa1a3ed3c5f..759e23ebbca 100644
--- a/test-support/src/main/java/org/testcontainers/testsupport/FlakyTestJUnit4RetryRule.java
+++ b/test-support/src/main/java/org/testcontainers/testsupport/FlakyTestJUnit4RetryRule.java
@@ -31,7 +31,6 @@ public class FlakyTestJUnit4RetryRule implements TestRule {
 
     @Override
     public Statement apply(Statement base, Description description) {
-
         final Flaky annotation = description.getAnnotation(Flaky.class);
 
         if (annotation == null) {
@@ -53,11 +52,13 @@ public Statement apply(Statement base, Description description) {
         try {
             reviewDate = LocalDate.parse(annotation.reviewDate());
         } catch (DateTimeParseException e) {
-            throw new IllegalArgumentException("@Flaky reviewDate could not be parsed. Please provide a date in yyyy-mm-dd format");
+            throw new IllegalArgumentException(
+                "@Flaky reviewDate could not be parsed. Please provide a date in yyyy-mm-dd format"
+            );
         }
 
         // the annotation should only have an effect before the review date, to encourage review and resolution
-        if ( LocalDate.now().isBefore(reviewDate) ) {
+        if (LocalDate.now().isBefore(reviewDate)) {
             return new RetryingStatement(base, description, maxTries);
         } else {
             return base;
@@ -65,8 +66,11 @@ public Statement apply(Statement base, Description description) {
     }
 
     private static class RetryingStatement extends Statement {
+
         private final Statement base;
+
         private final Description description;
+
         private final int maxTries;
 
         RetryingStatement(Statement base, Description description, int maxTries) {
@@ -77,7 +81,6 @@ private static class RetryingStatement extends Statement {
 
         @Override
         public void evaluate() {
-
             int attempts = 0;
             final List causes = new ArrayList<>();
 
@@ -93,7 +96,8 @@ public void evaluate() {
 
             throw new IllegalStateException(
                 "@Flaky-annotated test failed despite retries.",
-                new MultipleFailureException(causes));
+                new MultipleFailureException(causes)
+            );
         }
     }
 }
diff --git a/test-support/src/test/java/org/testcontainers/testsupport/FlakyRuleTest.java b/test-support/src/test/java/org/testcontainers/testsupport/FlakyRuleTest.java
index 07b0ffe1fa8..14a3d4c018c 100644
--- a/test-support/src/test/java/org/testcontainers/testsupport/FlakyRuleTest.java
+++ b/test-support/src/test/java/org/testcontainers/testsupport/FlakyRuleTest.java
@@ -12,11 +12,15 @@
 public class FlakyRuleTest {
 
     private static final String VALID_URL = "http://some.url/here";
+
     private static final String INVALID_URL = "";
 
     private static final String VALID_DATE_IN_FAR_FUTURE = "2063-04-05";
+
     private static final String VALID_DATE_IN_PAST = "1991-08-16";
+
     private static final String INVALID_DATE = "91-01-45";
+
     private static final int DEFAULT_TRIES = 3;
 
     private FlakyTestJUnit4RetryRule rule = new FlakyTestJUnit4RetryRule();
@@ -28,9 +32,7 @@ public void testIgnoresMethodWithoutAnnotation() throws Throwable {
         try {
             rule.apply(statement, description).evaluate();
             fail("Should not reach here");
-        } catch (Exception ignored) {
-
-        }
+        } catch (Exception ignored) {}
         assertEquals("The statement should only be invoked once, even if it throws", 1, statement.invocationCount);
     }
 
@@ -42,9 +44,7 @@ public void testRetriesMethodWithAnnotationUntilFailure() throws Throwable {
         try {
             rule.apply(statement, description).evaluate();
             fail("Should not reach here");
-        } catch (Exception ignored) {
-
-        }
+        } catch (Exception ignored) {}
         assertEquals("The statement should be invoked three times", 3, statement.invocationCount);
     }
 
@@ -56,9 +56,7 @@ public void testCustomRetryCount() throws Throwable {
         try {
             rule.apply(statement, description).evaluate();
             fail("Should not reach here");
-        } catch (Exception ignored) {
-
-        }
+        } catch (Exception ignored) {}
         assertEquals("The statement should be invoked ten times", 10, statement.invocationCount);
     }
 
@@ -70,7 +68,11 @@ public void testRetriesMethodWithAnnotationUntilSuccess() throws Throwable {
 
         rule.apply(statement, description).evaluate();
 
-        assertEquals("The statement should be invoked three times, and succeed the third time", 3, statement.invocationCount);
+        assertEquals(
+            "The statement should be invoked three times, and succeed the third time",
+            3,
+            statement.invocationCount
+        );
     }
 
     @Test
@@ -91,9 +93,7 @@ public void testTreatsExpiredAnnotationAsNoAnnotation() throws Throwable {
         try {
             rule.apply(statement, description).evaluate();
             fail("Should not reach here");
-        } catch (Exception ignored) {
-
-        }
+        } catch (Exception ignored) {}
         assertEquals("The statement should only be invoked once, even if it throws", 1, statement.invocationCount);
     }
 
@@ -104,9 +104,7 @@ public void testThrowsOnInvalidDateFormat() throws Throwable {
         try {
             rule.apply(statement, description).evaluate();
             fail("Should not reach here");
-        } catch (IllegalArgumentException ignored) {
-
-        }
+        } catch (IllegalArgumentException ignored) {}
         assertEquals("The statement should not be invoked if the annotation is invalid", 0, statement.invocationCount);
     }
 
@@ -117,14 +115,16 @@ public void testThrowsOnInvalidGitHubUrl() throws Throwable {
         try {
             rule.apply(statement, description).evaluate();
             fail("Should not reach here");
-        } catch (IllegalArgumentException ignored) {
-
-        }
+        } catch (IllegalArgumentException ignored) {}
         assertEquals("The statement should not be invoked if the annotation is invalid", 0, statement.invocationCount);
     }
 
     private Description newDescriptionWithAnnotation(String reviewDate, String gitHubUrl) {
-        return Description.createTestDescription("SomeTestClass", "someMethod", newAnnotation(reviewDate, gitHubUrl, DEFAULT_TRIES));
+        return Description.createTestDescription(
+            "SomeTestClass",
+            "someMethod",
+            newAnnotation(reviewDate, gitHubUrl, DEFAULT_TRIES)
+        );
     }
 
     private Description newDescriptionWithoutAnnotation() {
@@ -132,15 +132,27 @@ private Description newDescriptionWithoutAnnotation() {
     }
 
     private Description newDescriptionWithAnnotation() {
-        return Description.createTestDescription("SomeTestClass", "someMethod", newAnnotation(VALID_DATE_IN_FAR_FUTURE, VALID_URL, DEFAULT_TRIES));
+        return Description.createTestDescription(
+            "SomeTestClass",
+            "someMethod",
+            newAnnotation(VALID_DATE_IN_FAR_FUTURE, VALID_URL, DEFAULT_TRIES)
+        );
     }
 
     private Description newDescriptionWithAnnotationAndCustomTries(int maxTries) {
-        return Description.createTestDescription("SomeTestClass", "someMethod", newAnnotation(VALID_DATE_IN_FAR_FUTURE, VALID_URL, maxTries));
+        return Description.createTestDescription(
+            "SomeTestClass",
+            "someMethod",
+            newAnnotation(VALID_DATE_IN_FAR_FUTURE, VALID_URL, maxTries)
+        );
     }
 
     private Description newDescriptionWithExpiredAnnotation() {
-        return Description.createTestDescription("SomeTestClass", "someMethod", newAnnotation(VALID_DATE_IN_PAST, VALID_URL, DEFAULT_TRIES));
+        return Description.createTestDescription(
+            "SomeTestClass",
+            "someMethod",
+            newAnnotation(VALID_DATE_IN_PAST, VALID_URL, DEFAULT_TRIES)
+        );
     }
 
     private Flaky newAnnotation(final String reviewDate, String gitHubUrl, int tries) {
@@ -174,7 +186,9 @@ private DummyStatement newStatement(int timesToThrow) {
     }
 
     private static class DummyStatement extends Statement {
+
         int shouldThrowTimes = -1;
+
         int invocationCount = 0;
 
         @Override