Skip to content

Conversation

schiemon
Copy link
Contributor

@schiemon schiemon commented Jun 25, 2025

Motivation:

RetryingClientTest and RetryingRpcClientTest validate the respective retrying clients under various (failure) conditions.
However, not all test cases check whether the client-side request log is properly propagated by the client, e.g., whether:

  • the log is completed,
  • all child logs are added and completed as well,
  • all child logs have the expected status code and exception.

Verifying the logs becomes even more important for #6252, where the retrying client must ensure it properly completes concurrent pending requests—either when a response is received or when a request fails unrecoverably, thereby also failing all other pending requests. Aforementioned tests would increase our confidence that the upcoming hedging client does not cause regressions.

Modifications:

All changes are test-only.

  • Introduced a small testing utility (RequestContextUtils) for verifying ClientRequestContexts, especially the log, in a concise way.
  • Extended test cases in RetryingClientTest and RetryingRpcClientTest by incorporating verifications using that utility class.

Result:

  • 26 + 10 test cases now also verify ClientRequestContext under various failure scenarios.
  • RequestContextUtils now helps in writing concise tests that validate ClientRequestContext, e.g., for request hedging.

@schiemon schiemon mentioned this pull request Jun 25, 2025
6 tasks
Copy link

codecov bot commented Jun 25, 2025

Codecov Report

❌ Patch coverage is 79.06977% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.56%. Comparing base (8150425) to head (b4be00e).
⚠️ Report is 195 commits behind head on main.

Files with missing lines Patch % Lines
.../armeria/internal/testing/RequestContextUtils.java 79.06% 13 Missing and 5 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #6296      +/-   ##
============================================
+ Coverage     74.46%   74.56%   +0.10%     
- Complexity    22234    22611     +377     
============================================
  Files          1963     2022      +59     
  Lines         82437    83734    +1297     
  Branches      10764    10866     +102     
============================================
+ Hits          61385    62439    +1054     
- Misses        15918    16094     +176     
- Partials       5134     5201      +67     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@schiemon schiemon changed the title Add verifications of ClientRequestContexts to RetryClientTest Add verifications of ClientRequestContexts to RetryClientTest and RetryingRpcClientTest Jun 26, 2025
@schiemon schiemon marked this pull request as ready for review June 26, 2025 10:22
Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

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

I appreciate the additional validation in retrying tests. I've reviewed mainly RequestContextUtils mainly considering how we can use this utility more extensively within the code-base.

Comment on lines 148 to 177
if (childLogVerifiers.length == 0) {
childLogVerifiers = new RequestLogVerifier[ctx.log().children().size()];
Arrays.fill(childLogVerifiers, VERIFY_NOTHING);
}

assertValidRequestContextWithVerifier(
ctx,
childLogVerifiers.length == 0 ?
VERIFY_NOTHING
: verifyAllValid(
childLog -> {
// Default parent log verifier.
final HttpRequest req = ctx.request();
assertThat(req).isNotNull();
assert req != null;
assertThat(req.isComplete()).isTrue();

if (ctx.rpcRequest() != null) {
final HttpRequest lastHttpReq =
ctx.log().children()
.get(ctx.log().children().size() - 1).context().request();

if (lastHttpReq != null) {
assertThat(lastHttpReq).isSameAs(ctx.log().context().request());
}
}
},
childLogVerifiers[childLogVerifiers.length - 1]
), childLogVerifiers
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Question) I was a little surprised this validation only exists in this overriding variant. Would it make sense that this method simply calls assertValidRequestContextWithVerifier without the parent verifier?

Can the lastHttpReq check be included in the method at L180, or provided as a separate verifyLastChildHasSameHttpRequest() verifier if necessary?

e.g.

Suggested change
if (childLogVerifiers.length == 0) {
childLogVerifiers = new RequestLogVerifier[ctx.log().children().size()];
Arrays.fill(childLogVerifiers, VERIFY_NOTHING);
}
assertValidRequestContextWithVerifier(
ctx,
childLogVerifiers.length == 0 ?
VERIFY_NOTHING
: verifyAllValid(
childLog -> {
// Default parent log verifier.
final HttpRequest req = ctx.request();
assertThat(req).isNotNull();
assert req != null;
assertThat(req.isComplete()).isTrue();
if (ctx.rpcRequest() != null) {
final HttpRequest lastHttpReq =
ctx.log().children()
.get(ctx.log().children().size() - 1).context().request();
if (lastHttpReq != null) {
assertThat(lastHttpReq).isSameAs(ctx.log().context().request());
}
}
},
childLogVerifiers[childLogVerifiers.length - 1]
), childLogVerifiers
);
assertValidRequestContextWithVerifier(ctx,VERIFY_NOTHING, childLogVerifiers);

Copy link
Contributor Author

@schiemon schiemon Jul 2, 2025

Choose a reason for hiding this comment

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

There are situations where the caller wants to override the default parent log verifier so that is why it was only at that place and not integrated further dowstream.

I reflected on this and I think it is best to extract those checks into separate verifiers as you said and just always demand from the caller to provide a parent log verifier. The advantage of that is that the test are then more explicit on what to expect from the parent log which is less given with a hidden default parent log verifier.


@FunctionalInterface
public interface RequestLogVerifier {
void verifyChildLog(RequestLog childLog) throws Exception;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit; I wonder if it makes sense to drop the child prefix since the validation can also be applied to the parent log.

Suggested change
void verifyChildLog(RequestLog childLog) throws Exception;
void verifyLog(RequestLog requestLog) throws Exception;

};
}

public static RequestLogVerifier verifyExactlyOneValid(RequestLogVerifier... childLogVerifiers) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe just me, but I was imagining exactly one child is valid for all of the verifiers when looking at the name

Suggested change
public static RequestLogVerifier verifyExactlyOneValid(RequestLogVerifier... childLogVerifiers) {
public static RequestLogVerifier verifyExactlyOneVerifierValid(RequestLogVerifier... childLogVerifiers) {

Comment on lines 188 to 190
if (expectedNumRequests == 0) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Question) What do you think of removing this restriction? I still think this method can be useful in validating parentLogVerifier

Comment on lines 1081 to 1082
final WebClient client = client(rule,
10000, 0, 100);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit;

Suggested change
final WebClient client = client(rule,
10000, 0, 100);
final WebClient client = client(rule, 10000, 0, 100);

@schiemon
Copy link
Contributor Author

schiemon commented Jul 2, 2025

@jrhee17 Thank you for the review 🤙 . I addressed your comments. I am not sure if you like me to close the comments myself or leave them open. Feel free to educate me if there some Armeria-wide convention for this

@schiemon schiemon requested a review from jrhee17 July 3, 2025 11:26
@jrhee17 jrhee17 added this to the 1.33.0 milestone Jul 31, 2025
@ikhoon ikhoon modified the milestones: 1.33.0, 1.34.0 Aug 1, 2025
@github-actions github-actions bot added the Stale label Sep 1, 2025
@github-actions github-actions bot removed the Stale label Sep 2, 2025
@github-actions github-actions bot added the Stale label Oct 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants