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

Add LogMessageWaitStrategy #322

Merged
merged 5 commits into from
Apr 10, 2017
Merged

Add LogMessageWaitStrategy #322

merged 5 commits into from
Apr 10, 2017

Conversation

kiview
Copy link
Member

@kiview kiview commented Apr 3, 2017

Added a LogMessageWaitStrategy which checks, if a log message contains the specified String. This might help in fixing #317 when incorporating it into PostgreSQLContainer in the future.


@Test
public void testWaitUntilReady_Success() {
waitUntilReadyAndSucceed("while true; do sleep 1; echo -e \"" + READY_MESSAGE + "\"; done");
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 avoid sleep here because it adds a static delay to the test execution, how about "print & infinite sleep" instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wanted a delay between the prints to avoid excessive printing, your version sounds better though.

container.followOutput(waitingConsumer);

Predicate<OutputFrame> waitPredicate = outputFrame ->
outputFrame.getUtf8String().contains(expectedLogPart);
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if simple contains() is enough or not... Maybe some pattern based solution would be better?

Copy link
Member Author

Choose a reason for hiding this comment

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

At first I wanted to expose a method forPredicate(), but I think something like OutputFrame shouldn't be part of the public API?

WDYT about using matches() instead?

Copy link
Member

Choose a reason for hiding this comment

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

I'd imagine an overloaded withExpectedLogPart method that accepts a Pattern could be flexible enough, couldn't it?

@Override
protected void waitUntilReady() {
WaitingConsumer waitingConsumer = new WaitingConsumer();
container.followOutput(waitingConsumer);
Copy link
Member

Choose a reason for hiding this comment

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

@rnorth correct me if I'm wrong, but I think here will be a race because WaitingConsumer doesn't use .since(0) and if container prints something immediately after the launch then this code will fail. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think you're right. The WaitingConsumer will start following output after the container was started and will only receive new frames.

Copy link
Member

Choose a reason for hiding this comment

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

Ah yes, I think so. Just thinking, would there be any reason not to amend WaitingConsumer to use since(0)? I can't think of anything off the top of my head...

Copy link
Member

Choose a reason for hiding this comment

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

@rnorth sounds good to me 👍 I would even expect such behavior :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Should I do the change in this PR then?

Copy link
Member Author

@kiview kiview Apr 7, 2017

Choose a reason for hiding this comment

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

So I did a change, but I'm not entirely sure if this was the code you were thinking about ;)
I also wonder if this is really necessary, since the Javadoc says

 * @param since
 *    - UNIX timestamp (integer) to filter logs. Specifying a timestamp will only output log-entries since that timestamp. Default:
 *   0 (unfiltered)

Copy link
Member

Choose a reason for hiding this comment

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

Ah, good. Should be no need then.

Copy link
Member Author

@kiview kiview Apr 9, 2017

Choose a reason for hiding this comment

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

Or we keep the change, in order to document the intent more clearly. I'm fine with either way.

Copy link
Member

Choose a reason for hiding this comment

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

Sure, let's keep the withSince(0) there now that it's in - no harm, and like you say, it documents the intent.

@bsideup bsideup added this to the 1.3.0 milestone Apr 4, 2017
@kiview
Copy link
Member Author

kiview commented Apr 7, 2017

The failing codacy check is because of an underscore inside the test method BTW, but I wanted the test class to look similar to the existing WaitStrategy tests.

@bsideup
Copy link
Member

bsideup commented Apr 7, 2017

LGTM

/cc @rnorth

@kiview
Copy link
Member Author

kiview commented Apr 7, 2017

Regarding the problem with postgres #317, the LogWaitStrategy might need to cater for more complex log output (like logline sequence?). Wouldn't really be happy to introduce this kind of complexity though TBH.

@kiview
Copy link
Member Author

kiview commented Apr 8, 2017

I'd like to implement multi line matching in WaitingConsumer before merging the PR.

@rnorth
Copy link
Member

rnorth commented Apr 9, 2017

How shall we go about implementing the multi-line matching? A few options spring to mind:

  • Add times as a parameter to WaitingConsumer methods, so that the predicate has to be matched multiple times. This would be simple, and clearly works for the docker-maven-plugin team.
  • Allow Predicates to be used that allow the entire LinkedBlockingDeque<OutputFrame> to be looked at. However, Deque doesn't lend itself to performant traversal..
  • Do something around composing a chain of Predicates. Perhaps this is something that already exists in a library. This feels like an interesting exercise otherwise, but perhaps a bit yak-shavy.

Personally I think the first option is probably good enough for now, and we could make it more sophisticated if/when we find a compelling need.

Or maybe there's another way?

WDYT?

@kiview
Copy link
Member Author

kiview commented Apr 9, 2017

@rnorth AFAIK the docker-maven-plugin keeps on continuously building one single multi line String, using a StringBuilder and matching against the resulting String. In the PostgreSQL case, this allows them to match for

"(?s)ready to accept connections.*ready to accept connections"

.

I think this is nice from an API user perspective, but it doesn't work that well with the current OutputFrame model.

Would it be okay to switch from using LinkedBlockingDeque to a normal List? I think performance and memory implications shouldn't be so bad, especially since we are inside a testing context.

On the other hand, regarding your proposed solutions, I'd agree with implementing the times based solution first, since it's really easy and serves our current needs. We are working around non optimal implemented container images after all and it should be sufficient to be pragmatic at the moment.

@kiview
Copy link
Member Author

kiview commented Apr 10, 2017

I've implemented a solution by adding a times parameter to the WaitingConsumer method. IMO it's enough for the moment.

@rnorth
Copy link
Member

rnorth commented Apr 10, 2017

This looks good to me - thanks for this!
I'll go ahead and merge into master, and aim to release in the next couple of days.

@rnorth rnorth merged commit c2eae85 into testcontainers:master Apr 10, 2017
@kiview kiview deleted the waitForLog branch April 10, 2017 20:32
@kiview
Copy link
Member Author

kiview commented Apr 10, 2017

I'll look into fixing #317 tomorrow by using WaitingConsumer, might work without bigger refactorings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants