fix: refining CLIResult asserts related to missing or repeated messages - #51238
fix: refining CLIResult asserts related to missing or repeated messages#51238shawkins wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Refines CLI output assertions used in Quarkus distribution/integration tests to better handle “no message” checks without relying on implicit timing, especially for running-server scenarios (issue #51095).
Changes:
- Extends
CLIResult“no output” assertion helper to optionally allow assertions while the server is still running. - Adds new
CLIResultassertion helpers (assertNoMessageAfter,assertNoStartupMessage) and updates existing assertions to guard against misuse on running servers. - Updates multiple distribution tests to use the new assertions for startup/running-server output.
Reviewed changes
Copilot reviewed 1 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java | Adds new assertion helpers and enforces safer usage when the server is still running. |
| quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/MetricsDistTest.java | Switches to startup-safe “no message” assertion for running server. |
| quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/ManagementOffDistTest.java | Switches to startup-safe “no message” assertion for running server. |
| quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/ManagementDistTest.java | Switches to startup-safe “no message” assertion for running server. |
| quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/LoggingDistTest.java | Updates logging assertions to use new helpers and adds a test provider. |
| quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FipsDistTest.java | Replaces “shown 0 times” with startup-safe “no message” assertion. |
856dab2 to
4a57489
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java:139
expecteddoes not act as a completion fence unless it is emitted after every possiblenotExpectedmessage. The new callers use the@PreMatchingTestFilterrequest log asexpected, but the HTTP access log is emitted after request processing, so this can still snapshot output before the forbidden access-log line arrives and false-pass. Use a marker that is emitted after access logging/output collection has completed.
assertMessage(expected);
noOutput("The standard output contains: " + notExpected, notExpected, this::getOutput, this, true);
quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java:147
- This bypass is unsafe for failed manual starts.
RawKeycloakDistribution.waitFor(true)returns immediately when the process has already stopped without joining the asynchronous output reader, andManagementDistTest.testManagementNoHttpsnow invokes this helper on an expected startup failure; the assertion can therefore false-pass while stdout is still being drained. Drain completed-process output or require a reliable completion signal before checking absence.
default void assertNoStartupMessage(String message) {
noOutput("The standard output contains: " + message, message, this::getOutput, this, true);
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 7 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java:139
assertMessage(expected)is not an output-completion barrier: the expected line may precede a forbidden line that is still being produced or drained. In the new access-log usages,TestFilterlogs from aContainerRequestFilterbefore access logging completes, so this immediate absence check can still falsely pass; use a sentinel guaranteed to be emitted after the candidate output (and wait for its new occurrence), or stop and fully drain the process before checking.
default void assertNoMessageGiven(String expected, String notExpected) {
assertMessage(expected);
noOutput("The standard output contains: " + notExpected, notExpected, this::getOutput, this, true);
Pepo48
left a comment
There was a problem hiding this comment.
I played with assertNoMessageGiven and managed to get it to false-pass. I broke the exclude pattern in Quarkus AccessLogHandler (the exact bug the test is meant to catch) and added a non-blocking 3s delay before the log write. The assertNoMessageGiven check passed silently - the access-log line just hadn't hit stdout yet. Only the file-based Awaitility check in httpAccessLogNotNamedPattern caught it.
I think it's because assertNoMessageGiven does a single snapshot right after finding the expected message, so anything arriving a bit later slips through.
Regardless, it's not a blocker for me, the real-world window is tiny and this is way better than the old approach. Just thought it was worth mentioning.
Therefore, I'm approving. Thanks, Steve.
This is possible and relates to what copilot was calling out as well. Essentially I had started down the path of reworking the TestFilter for this purpose, but that started to seem like overkill, so I just let it be based upon looking for a subsequent request log. Let me take a look again at what doing this the right way would entail. |
closes: keycloak#51095 Signed-off-by: Steve Hawkins <shawkins@redhat.com>
|
@Pepo48 added a done handler to run after the access logging. |
Pepo48
left a comment
There was a problem hiding this comment.
CI failure is related - we just need to adjust the strings.
Apart from that LGTM as well.
| when().get("http://127.0.0.1:8080/realms/master/clients/account/redirect").then() | ||
| .statusCode(200); | ||
| cliResult.assertNoMessage("127.0.0.1 GET /realms/master/clients/account/redirect"); | ||
| cliResult.assertNoMessageGiven("Request GET /realms/master/clients/account/redirect has context request", "127.0.0.1 GET /realms/master/clients/account/redirect"); |
There was a problem hiding this comment.
| cliResult.assertNoMessageGiven("Request GET /realms/master/clients/account/redirect has context request", "127.0.0.1 GET /realms/master/clients/account/redirect"); | |
| cliResult.assertNoMessageGiven("TestFilter Request GET /realms/master/clients/account/redirect is done", "127.0.0.1 GET /realms/master/clients/account/redirect"); |
| fileCliResult.assertNoMessageGiven("TestFilter GET Request /realms/master/clients/account/redirect is done", "[org.keycloak.http.access-log]"); | ||
| fileCliResult.assertNoMessageGiven("TestFilter GET Request /realms/master/clients/account/redirect is done", "127.0.0.1 GET /realms/master/.well-known/openid-configuration"); | ||
| fileCliResult.assertNoMessageGiven("TestFilter GET Request /realms/master/clients/account/redirect is done", "127.0.0.1 GET /realms/master/clients/account/redirect"); |
There was a problem hiding this comment.
| fileCliResult.assertNoMessageGiven("TestFilter GET Request /realms/master/clients/account/redirect is done", "[org.keycloak.http.access-log]"); | |
| fileCliResult.assertNoMessageGiven("TestFilter GET Request /realms/master/clients/account/redirect is done", "127.0.0.1 GET /realms/master/.well-known/openid-configuration"); | |
| fileCliResult.assertNoMessageGiven("TestFilter GET Request /realms/master/clients/account/redirect is done", "127.0.0.1 GET /realms/master/clients/account/redirect"); | |
| fileCliResult.assertNoMessageGiven("TestFilter Request GET /realms/master/clients/account/redirect is done", "[org.keycloak.http.access-log]"); | |
| fileCliResult.assertNoMessageGiven("TestFilter Request GET /realms/master/clients/account/redirect is done", "127.0.0.1 GET /realms/master/.well-known/openid-configuration"); | |
| fileCliResult.assertNoMessageGiven("TestFilter Request GET /realms/master/clients/account/redirect is done", "127.0.0.1 GET /realms/master/clients/account/redirect"); |
Signed-off-by: Steve Hawkins <shawkins@redhat.com>
Yes, sorry I copied those in wrong to that test. I see we also have a few more spots for false positives like line 356, but I'm not sure it's worth the complexity to keep addressing this. |
These changes should keep the intention of the asserts, but avoid adding a baked in atLeast durations when checking for no messages.
closes: #51095