-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Support multiple HTTP status codes for HttpWaitStrategy #630
Conversation
In the context of elasticsearch test containers module, I'd like to add an ElasticsearchWaitStrategy class which extends the HttpWaitStrategy with some default settings so it will be even easier for a end user to start an ElasticsearchTestContainer. Anyway, in this context, I found helpful that the HttpWaitStrategy expects more than on status code. For example, you can imagine running elasticsearch in secure mode or without any security. In which cases the elasticsearch service might answer 200 or 401. This commit proposes this change.
*/ | ||
@Deprecated |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)`
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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)
)
There was a problem hiding this comment.
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
I don't know TBH. I could also have only change the existing signature. Up to you. I can update the PR if you wish but having 2 methods doing the same does not look appealing to me. |
Sorry to butt in here, but this class has never been released, so maybe there's no need to deprecate the method at all? This class (and package) was created as part of #600, and the previous implementation just wraps it. |
Thx for the comment @barrycommins. If this isn't released yet, WDYT about changing this internal API for now to allow for multiargs by default? |
@kiview I see no harm in it, but I think if it were up to me, I'd keep the original method name I think that allows the easiest upgrade path for current users of For users changing from a custom subclass, they would need to change the method signature to support varargs, but since they were changing the superclass anyway I don't think it's too big a problem. Of course, this is contingent on this PR being merged before the next release, because otherwise it would become a breaking change :-) |
Makes sense to me. I wanted initially to add the plural form to make obvious that you can many status codes but I'm fine keeping the singular form. I'll update the PR that way. |
`forStatusCodeMatching()` comes with a default Predicate which checks status codes that have been provided with `forStatusCode()`. Also copied the default tests which were using the deprecated package to the new one to make sure we test the new methods.
@@ -0,0 +1,93 @@ | |||
package org.testcontainers.junit.wait.strategy; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... I'm not sure these changes are related to the PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's somewhat needed to test the new methods I added. See strategy/HttpWaitStrategyTest.java
class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should just start using new implementation (under org.testcontainers.containers.wait.strategy
package) in HttpWaitStrategyTest
& AbstractWaitStrategyTest
since the old classes are just wrappers now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dadoonet ping :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum. I'm missing something. I probably misunderstood what you are expecting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I added a call to my method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I added a call to my method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should just fix the imports in the old test and start using new wait strategies, so that you can also add your new method to that test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me. I'll do that. In which case, I'll also move the tests to the new package, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks :)
* @param statusCodePredicate The predicate to test the response against | ||
* @return this | ||
*/ | ||
public HttpWaitStrategy forStatusCodeMatching(Predicate<Integer> statusCodePredicate) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking about the use case where somebody will call Wait.forHttp().forStatusCode(200).forStatusCodeMatching(it -> it > 400)
. Maybe we should throw an error, or handle both statuses?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do really like the Predicate approach here - it opens the door to having some useful ready-to-use predicates in the future (e.g. anySuccessfulStatusCode()
or anyServerErrorStatusCode()
etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the latest change below I'm now hopefully supporting both.
Also use a Set instead of a List to avoid duplicates.
* @return this | ||
*/ | ||
public HttpWaitStrategy forStatusCodeMatching(Predicate<Integer> statusCodePredicate) { | ||
this.statusCodePredicate.and(statusCodePredicate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be:
this.statusCodePredicate = this.statusCodePredicate.and(statusCodePredicate);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was unsure and thought that we can directly modify the existing predicate and chain it to a new one without changing its reference. Let me update that.
@@ -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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated to this PR
The travis failure seems unrelated to my changes. |
And stop testing deprecated methods
I believe it's ok now. |
@@ -59,7 +59,9 @@ protected void waitUntilReady() { | |||
super.waitUntilReady(); | |||
ready.set(true); | |||
} | |||
}.forResponsePredicate(s -> s.equals(GOOD_RESPONSE_BODY)); | |||
} | |||
.forResponsePredicate(s -> s.equals(GOOD_RESPONSE_BODY)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a test where both forStatusCodeMatching
and withStatusCode
are used (to check that it's not being overwritten)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. My code is actually failing! :p
I've been wondering how to add a test and by your question I actually understood how to write. (Was so easy that I feel dumb not having found that before...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But we're still missing a test where we call
forHttp()
.forStatusCode(200) // <-
.forStatusCode(205) // <-
.forStatusCodeMatching(it -> it > 400)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So should I clone the class or just change the buildWaitStrategy
method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just add a test method which is not based on buildWaitStrategy
's result
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it. A bit differently though so I can reuse most of the existing code and that could help in the future.
I hope it's ok for you
@dadoonet ok, looks good now! Just the last thing before we can merge - CHANGELOG.md :) P.S. we squash automatically when we merge, no need to squash it yourself 👍 |
No problem. |
@dadoonet merged, thanks a lot! Will be released this weeks :) |
Awesome! Thanks for guiding me for my 1st code PR :) |
….forStatusCode In #630 we introduced predicates but with a default one which is always present whatever what is passed in the `forStatusCodeMatching()` method. This commit adds a test that demonstrates the issue: * We have a service returning `200 OK` * The predicate expects anything which is a code >= to `300` * The test should throw a Timeout as this condition is never reached but without the current fix, the test never throws the Timeout as 200 matches the default builtin predicate. This commit fixes the problem by checking at startup time what is/are the predicates that needs to be applied. Note that in most cases, an HTTP service is expected to throw a `200 OK` status so that fix might not fix actually any real problem and might be a theory only. But I'd prefer to have code that actually implements what is supposed to work. Closes #880.
….forStatusCode (#881) In #630 we introduced predicates but with a default one which is always present whatever is passed in the `forStatusCodeMatching()` method. This commit adds a test that demonstrates the issue: * We have a service returning `200 OK` * The predicate expects anything which is a code >= to `300` * The test should throw a Timeout as this condition is never reached but without the current fix, the test never throws the Timeout as 200 matches the default builtin predicate. This commit fixes the problem by checking at startup time what is/are the predicates that needs to be applied. Note that in most cases, an HTTP service is expected to throw a `200 OK` status so that fix might not fix actually any real problem and might be a theory only. But I'd prefer to have code that actually implements what is supposed to work. Closes #880.
In the context of elasticsearch test containers module, I'd like to
add an ElasticsearchWaitStrategy class which extends the HttpWaitStrategy
with some default settings so it will be even easier for a end user to
start an ElasticsearchTestContainer.
Anyway, in this context, I found helpful that the HttpWaitStrategy expects
more than on status code.
For example, you can imagine running elasticsearch in secure mode or
without any security. In which cases the elasticsearch service might answer 200 or 401.
This commit proposes this change.