From b543d2c46e6170bc613e71f68136e0cc344c05d1 Mon Sep 17 00:00:00 2001 From: Richard North Date: Sat, 30 Apr 2016 16:56:43 +0100 Subject: [PATCH 1/2] Resolve #136: Add a 5s stabilisation period for the launched Virtuoso container, as it seems newer versions of the base container are responding OK to the first 'SELECT 1' but then rejecting the subsequent query. Lock down Virtuoso containers to a fixed tag rather than latest, unless specified. Reduce verbosity of logs for Virtuoso tests. Add fixed Virtuoso version to JDBC test Update to latest version of duct-tape to allow use of fixed Inconsistents get Reinstate virtuoso maven module --- core/pom.xml | 2 +- .../containers/VirtuosoContainer.java | 156 +++++++++++------- .../containers/VirtuosoJDBCDriverTest.java | 4 +- .../src/test/resources/logback-test.xml | 1 + pom.xml | 1 + 5 files changed, 104 insertions(+), 60 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 74d74b2e2ae..729f55bc3af 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -27,7 +27,7 @@ org.rnorth.duct-tape duct-tape - 1.0.5 + 1.0.6 org.slf4j diff --git a/modules/virtuoso/src/main/java/org/testcontainers/containers/VirtuosoContainer.java b/modules/virtuoso/src/main/java/org/testcontainers/containers/VirtuosoContainer.java index 29865bec34c..3f601b22812 100644 --- a/modules/virtuoso/src/main/java/org/testcontainers/containers/VirtuosoContainer.java +++ b/modules/virtuoso/src/main/java/org/testcontainers/containers/VirtuosoContainer.java @@ -1,64 +1,106 @@ package org.testcontainers.containers; -import org.testcontainers.containers.JdbcDatabaseContainer; +import org.rnorth.ducttape.inconsistents.Inconsistents; +import org.rnorth.ducttape.ratelimits.RateLimiter; +import org.rnorth.ducttape.ratelimits.RateLimiterBuilder; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.concurrent.TimeUnit; public class VirtuosoContainer> extends JdbcDatabaseContainer { - public static final String NAME = "virtuoso"; - public static final String IMAGE = "tenforce/virtuoso"; - public static final Integer JDBC_PORT = 1111; - public static final Integer SPARQL_SERVICE_PORT = 8890; - - public VirtuosoContainer() { - super(IMAGE + ":latest"); - } - - public VirtuosoContainer(String dockerImageName) { - super(dockerImageName); - } - - @Override - protected void configure() { - addExposedPort(JDBC_PORT); - addExposedPort(SPARQL_SERVICE_PORT); - addEnv("DBA_PASSWORD", getPassword()); - addEnv("SPARQL_UPDATE", "true"); - addEnv("DEFAULT_GRAPH", "http://localhost:8890/DAV"); - addExposedPorts(JDBC_PORT, SPARQL_SERVICE_PORT); - } - - @Override - protected String getDriverClassName() { - return "virtuoso.jdbc4.Driver"; - } - - @Override - public String getJdbcUrl() { - return "jdbc:virtuoso://" + getContainerIpAddress() + ":" + getMappedPort(JDBC_PORT); - } - - public String getSparqlUrl() { - return "http://" + getContainerIpAddress() + ":" + getMappedPort(SPARQL_SERVICE_PORT) + "/sparql"; - } - - @Override - public String getUsername() { - return "dba"; - } - - @Override - public String getPassword() { - return "myDbaPassword"; - } - - @Override - protected String getTestQueryString() { - return "SELECT 1"; - } - - @Override - protected Integer getLivenessCheckPort() { - return getMappedPort(JDBC_PORT); - } + public static final String NAME = "virtuoso"; + public static final String IMAGE = "tenforce/virtuoso"; + public static final Integer JDBC_PORT = 1111; + public static final Integer SPARQL_SERVICE_PORT = 8890; + private static final RateLimiter LIVENESS_RATE_LIMITER = RateLimiterBuilder.newBuilder() + .withConstantThroughput() + .withRate(1, TimeUnit.SECONDS) + .build(); + + public VirtuosoContainer() { + super(IMAGE + ":1.0.0-virtuoso7.2.2"); + } + + public VirtuosoContainer(String dockerImageName) { + super(dockerImageName); + } + + @Override + protected void configure() { + addExposedPort(JDBC_PORT); + addExposedPort(SPARQL_SERVICE_PORT); + addEnv("DBA_PASSWORD", getPassword()); + addEnv("SPARQL_UPDATE", "true"); + addEnv("DEFAULT_GRAPH", "http://localhost:8890/DAV"); + addExposedPorts(JDBC_PORT, SPARQL_SERVICE_PORT); + } + + @Override + protected String getDriverClassName() { + return "virtuoso.jdbc4.Driver"; + } + + @Override + public String getJdbcUrl() { + return "jdbc:virtuoso://" + getContainerIpAddress() + ":" + getMappedPort(JDBC_PORT); + } + + public String getSparqlUrl() { + return "http://" + getContainerIpAddress() + ":" + getMappedPort(SPARQL_SERVICE_PORT) + "/sparql"; + } + + @Override + public String getUsername() { + return "dba"; + } + + @Override + public String getPassword() { + return "myDbaPassword"; + } + + @Override + protected String getTestQueryString() { + return "SELECT 1"; + } + + @Override + protected Integer getLivenessCheckPort() { + return getMappedPort(JDBC_PORT); + } + + @Override + protected void waitUntilContainerStarted() { + // Repeatedly try and open a connection to the DB and execute a test query + + logger().info("Waiting for database connection to become available at {} using query '{}'", getJdbcUrl(), getTestQueryString()); + + // Wait for consecutive JDBC connection successes over a period of time. The Virtuoso container seems + // to initially return a connection that fails on subsequent attempts, so wait for a consistently stable connection + Inconsistents.retryUntilConsistent(5, 120, TimeUnit.SECONDS, () -> { + //noinspection CodeBlock2Expr + return LIVENESS_RATE_LIMITER.getWhenReady(() -> { + if (!isRunning()) { + throw new ContainerLaunchException("Container failed to start"); + } + + try { + Connection connection = createConnection(""); + + boolean success = connection.createStatement().execute(this.getTestQueryString()); + if (success) { + logger().info("Obtained a connection to container ({})", this.getJdbcUrl()); + return true; + } else { + throw new SQLException("Failed to execute test query"); + } + } catch (SQLException e) { + throw new ContainerLaunchException(e.getMessage()); + } + }); + }); + } } diff --git a/modules/virtuoso/src/test/java/org/testcontainers/containers/VirtuosoJDBCDriverTest.java b/modules/virtuoso/src/test/java/org/testcontainers/containers/VirtuosoJDBCDriverTest.java index fe52518d3cc..19edef04282 100644 --- a/modules/virtuoso/src/test/java/org/testcontainers/containers/VirtuosoJDBCDriverTest.java +++ b/modules/virtuoso/src/test/java/org/testcontainers/containers/VirtuosoJDBCDriverTest.java @@ -14,8 +14,8 @@ public class VirtuosoJDBCDriverTest { @Test - public void testVirtuosoWithNoSpecifiedVersion() throws SQLException { - performSimpleTest("jdbc:tc:virtuoso://hostname/databasename"); + public void testVirtuosoWithSpecifiedVersion() throws SQLException { + performSimpleTest("jdbc:tc:virtuoso:1.0.0-virtuoso7.2.2://hostname/databasename"); } diff --git a/modules/virtuoso/src/test/resources/logback-test.xml b/modules/virtuoso/src/test/resources/logback-test.xml index 4c96fd1b863..634cc113fd0 100644 --- a/modules/virtuoso/src/test/resources/logback-test.xml +++ b/modules/virtuoso/src/test/resources/logback-test.xml @@ -16,5 +16,6 @@ + \ No newline at end of file diff --git a/pom.xml b/pom.xml index c1290556166..86fa8bb0c3e 100644 --- a/pom.xml +++ b/pom.xml @@ -153,6 +153,7 @@ modules/postgresql modules/selenium modules/nginx + modules/virtuoso From 247531e67399a6f109cc236c8b17d9b0c442e7cb Mon Sep 17 00:00:00 2001 From: Richard North Date: Sat, 30 Apr 2016 20:00:03 +0100 Subject: [PATCH 2/2] Move Virtuoso module to proprietary dependencies maven group, given that it relies on a third party maven repository. This allows developer testing if the Virtuoso drivers are available, but does not couple CI to the availability of the drivers. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 86fa8bb0c3e..efd404073f1 100644 --- a/pom.xml +++ b/pom.xml @@ -153,7 +153,6 @@ modules/postgresql modules/selenium modules/nginx - modules/virtuoso @@ -161,6 +160,7 @@ proprietary-deps modules/oracle-xe + modules/virtuoso