Skip to content

Commit

Permalink
Improve log messages when database container test query fails (#3015)
Browse files Browse the repository at this point in the history
Co-authored-by: Sergei Egorov <bsideup@gmail.com>
  • Loading branch information
vcvitaly and bsideup committed May 19, 2021
1 parent 137b00d commit 3858aff
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 16 deletions.
1 change: 1 addition & 0 deletions modules/jdbc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ dependencies {
testCompile 'com.zaxxer:HikariCP-java6:2.3.13'
testCompile 'com.googlecode.junit-toolbox:junit-toolbox:2.4'
testCompile 'org.rnorth.visible-assertions:visible-assertions:2.1.2'
testCompile 'org.assertj:assertj-core:3.16.1'
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.testcontainers.containers;

import com.github.dockerjava.api.command.InspectContainerResponse;
import java.sql.Statement;
import lombok.NonNull;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.testcontainers.containers.traits.LinkableContainer;
Expand Down Expand Up @@ -130,25 +132,23 @@ public SELF withInitScript(String initScriptPath) {
return self();
}

@SneakyThrows(InterruptedException.class)
@Override
protected void waitUntilContainerStarted() {
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();
try {
while (System.currentTimeMillis() < start + (1000 * startupTimeoutSeconds)) {
try {
if (!isRunning()) {
Thread.sleep(100L);
continue; // Don't attempt to connect yet
}

try (Connection connection = createConnection("")) {
boolean testQuerySucceeded = connection.createStatement().execute(this.getTestQueryString());
if (testQuerySucceeded) {
break;
}
while (System.currentTimeMillis() < start + (1000 * startupTimeoutSeconds)) {
if (!isRunning()) {
Thread.sleep(100L);
} else {
try (Statement statement = createConnection("").createStatement()) {
boolean testQuerySucceeded = statement.execute(this.getTestQueryString());
if (testQuerySucceeded) {
logger().info("Container is started (JDBC URL: {})", this.getJdbcUrl());
return;
}
} catch (NoDriverFoundException e) {
// we explicitly want this exception to fail fast without retries
Expand All @@ -159,12 +159,12 @@ protected void waitUntilContainerStarted() {
Thread.sleep(100L);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new ContainerLaunchException("Container startup wait was interrupted", e);
}

logger().info("Container is started (JDBC URL: {})", JdbcDatabaseContainer.this.getJdbcUrl());
throw new IllegalStateException(
String.format("Container is started, but cannot be accessed by (JDBC URL: %s), please check container logs",
this.getJdbcUrl())
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.testcontainers.containers;

import java.sql.Connection;
import java.sql.SQLException;
import lombok.NonNull;
import org.junit.Test;
import org.slf4j.Logger;

import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.Mockito.mock;

public class JdbcDatabaseContainerTest {

@Test
public void anExceptionIsThrownIfJdbcIsNotAvailable() {
JdbcDatabaseContainer<?> jdbcContainer = new JdbcDatabaseContainerStub("mysql:latest")
.withStartupTimeoutSeconds(1);

assertThatExceptionOfType(IllegalStateException.class).isThrownBy(jdbcContainer::waitUntilContainerStarted);
}

static class JdbcDatabaseContainerStub extends JdbcDatabaseContainer {

public JdbcDatabaseContainerStub(@NonNull String dockerImageName) {
super(dockerImageName);
}

@Override
public String getDriverClassName() {
return null;
}

@Override
public String getJdbcUrl() {
return null;
}

@Override
public String getUsername() {
return null;
}

@Override
public String getPassword() {
return null;
}

@Override
protected String getTestQueryString() {
return null;
}

@Override
public boolean isRunning() {
return true;
}

@Override
public Connection createConnection(String queryString) throws SQLException, NoDriverFoundException {
throw new SQLException("Could not create new connection");
}

@Override
protected Logger logger() {
return mock(Logger.class);
}

@Override
public void setDockerImageName(@NonNull String dockerImageName) {}
}
}

0 comments on commit 3858aff

Please sign in to comment.