Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple HTTP status codes for HttpWaitStrategy #630

Merged
merged 17 commits into from
Apr 13, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.testcontainers.containers.GenericContainer;

import java.util.Arrays;
import java.util.function.Predicate;

/**
Expand All @@ -21,12 +22,25 @@ public class HttpWaitStrategy extends GenericContainer.AbstractWaitStrategy {
*
* @param statusCode the expected status code
* @return this
* @deprecated Use {@link #forStatusCodes(Integer...)} instead
*/
@Deprecated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really think we should deprecate the old API? From a technical standpoint you are of course right, I'm just thinking about the developer experience, with a lot of people using this API right now I assume.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep this method and add one more with ranges. ES' case (two values, 200 and 401) is not as popular as e.g. ranges like 200-299 where any 2xx code is considered valid.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, to keep this PR small, we can allow calling forStatusCode multiple times:

 Wait.forHttp("/all").forStatusCode(200).forStatusCode(401)`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it works for the ES module, I'd be fine with calling the method multiple times.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bsideup

ES' case (two values, 200 and 401) is not as popular as e.g. ranges like 200-299 where any 2xx code is considered valid.

Yeah. I thought about that as well as I saw how fabric8 docker maven plugin offers that as well. But my plan was to come with this later may be with something like forStatusCodes(String...).

Wait.forHttp("/all").forStatusCode(200).forStatusCode(401)

Yeah. I agree with this proposal. And I can then support as well:

Wait.forHttp("/all").forStatusCode(200, 299).forStatusCode(401)

WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forStatusCode(200, 299) is too unambiguous :(

I would actually go for

Wait.forHttp("/all").forStatusCodeMatching(it -> it >= 200 && it < 300 || it == 401)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also keep forStatusCode, plus maybe make it chain-able ( Wait.forHttp("/all").forStatusCode(200).forStatusCode(401) )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. Sounds like great ideas. I'll do that

public HttpWaitStrategy forStatusCode(int statusCode) {
delegateStrategy.forStatusCode(statusCode);
return this;
}

/**
* Waits for one of the given status codes.
*
* @param statusCodes the expected status codes
* @return this
*/
public HttpWaitStrategy forStatusCodes(Integer... statusCodes) {
delegateStrategy.forStatusCodes(statusCodes);
return this;
}

/**
* Waits for the given path.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static HostPortWaitStrategy forListeningPort() {
public static HttpWaitStrategy forHttp(String path) {
return new HttpWaitStrategy()
.forPath(path)
.forStatusCode(HttpURLConnection.HTTP_OK);
.forStatusCodes(HttpURLConnection.HTTP_OK);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
Expand All @@ -32,7 +35,7 @@ public class HttpWaitStrategy extends AbstractWaitStrategy {
private static final String AUTH_BASIC = "Basic ";

private String path = "/";
private int statusCode = HttpURLConnection.HTTP_OK;
private List<Integer> statusCodes = Collections.singletonList(HttpURLConnection.HTTP_OK);
private boolean tlsEnabled;
private String username;
private String password;
Expand All @@ -43,9 +46,22 @@ public class HttpWaitStrategy extends AbstractWaitStrategy {
*
* @param statusCode the expected status code
* @return this
* @deprecated Use {@link #forStatusCodes(Integer...)} instead
*/
@Deprecated
public HttpWaitStrategy forStatusCode(int statusCode) {
this.statusCode = statusCode;
forStatusCodes(statusCode);
return this;
}

/**
* Waits for one of the given status codes.
*
* @param statusCodes the expected status codes
* @return this
*/
public HttpWaitStrategy forStatusCodes(Integer... statusCodes) {
this.statusCodes = Arrays.asList(statusCodes);
return this;
}

Expand Down Expand Up @@ -122,7 +138,7 @@ protected void waitUntilReady() {
connection.setRequestMethod("GET");
connection.connect();

if (statusCode != connection.getResponseCode()) {
if (!statusCodes.contains(connection.getResponseCode())) {
throw new RuntimeException(String.format("HTTP response code was: %s",
connection.getResponseCode()));
}
Expand All @@ -144,7 +160,7 @@ protected void waitUntilReady() {

} catch (TimeoutException e) {
throw new ContainerLaunchException(String.format(
"Timed out waiting for URL to be accessible (%s should return HTTP %s)", uri, statusCode));
"Timed out waiting for URL to be accessible (%s should return HTTP %s)", uri, statusCodes));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static HostPortWaitStrategy forListeningPort() {
public static HttpWaitStrategy forHttp(String path) {
return new HttpWaitStrategy()
.forPath(path)
.forStatusCode(HttpURLConnection.HTTP_OK);
.forStatusCodes(HttpURLConnection.HTTP_OK);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions docs/usage/docker_compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ public static DockerComposeContainer environment =
Wait.forListeningPort().withStartupTimeout(Duration.ofSeconds(30)));
```

Wait for arbitrary status code on an HTTPS endpoint:
Wait for arbitrary status codes on an HTTPS endpoint:
```java
@ClassRule
public static DockerComposeContainer environment =
new DockerComposeContainer(new File("src/test/resources/compose-test.yml"))
.withExposedService("elasticsearch_1", ELASTICSEARCH_PORT,
Wait.forHttp("/all")
.forStatusCode(301)
.forStatusCodes(200, 401)
.usingTls());
```

Expand All @@ -91,7 +91,7 @@ public static DockerComposeContainer environment =
.withExposedService("redis_1", REDIS_PORT, Wait.forListeningPort())
.withExposedService("elasticsearch_1", ELASTICSEARCH_PORT,
Wait.forHttp("/all")
.forStatusCode(301)
.forStatusCodes(200, 401)
.usingTls());
```

Expand Down
4 changes: 2 additions & 2 deletions docs/usage/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ public static GenericContainer elasticsearch =
.waitingFor(Wait.forHttp("/all"));
```

Wait for arbitrary status code on an HTTPS endpoint:
Wait for 200 or 401 status codes on an HTTPS endpoint:
```java
@ClassRule
public static GenericContainer elasticsearch =
new GenericContainer("elasticsearch:2.3")
.withExposedPorts(9200)
.waitingFor(
Wait.forHttp("/all")
.forStatusCode(301)
.forStatusCodes(200, 401)
.usingTls());
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import org.junit.ClassRule;
import org.junit.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.Wait;
import org.testcontainers.containers.wait.strategy.Wait;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated to this PR


import java.io.IOException;

Expand All @@ -30,7 +30,7 @@ public class VaultContainerTest {
.withSecretInVault("secret/testing2", "secret_one=password1",
"secret_two=password2", "secret_three=password3", "secret_three=password3",
"secret_four=password4")
.waitingFor(Wait.forHttp("/v1/secret/testing1").forStatusCode(400));
.waitingFor(Wait.forHttp("/v1/secret/testing1").forStatusCodes(400));

@Test
public void readFirstSecretPathWithCli() throws IOException, InterruptedException {
Expand Down