-
Notifications
You must be signed in to change notification settings - Fork 201
loadbalancer: make address assertion in LoadBalancerTest order-independent #3357
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
base: main
Are you sure you want to change the base?
Conversation
…ndent The test resubscribeToEventsWhenAllHostsAreUnhealthy previously relied on the iteration order of lb.usedAddresses(), which is not guaranteed. Updated the assertion to use containsInAnyOrder(...) with hasProperty(...) to make it deterministic across different execution orders. No functional or behavioral change; improves test robustness.
…ed (apple#3354) Motivation: When gRPC client receives a response, it first validates that it's formed according to gRPC specification. If any headers or trailers are missing, `validateResponseAndGetPayload` will throw an exception. In this case, we leak undrained response payload body. Modifications: 1. Try catch logic of `validateResponseAndGetPayload`, subscribe and cancel response message body in case of unexpected exceptions. 2. Enhance `ProtocolCompatibilityTest` to validate we never leak responses across all tests. Result: Responses are properly drained even when we receive malformed responses.
…ToEventsWhenAllHostsAreUnhealthy
|
|
||
| // Events for the new Subscriber change the state | ||
| sendServiceDiscoveryEvents(upEvent("address-2"), upEvent("address-3"), upEvent("address-4")); | ||
| assertAddresses(lb.usedAddresses(), "address-2", "address-3", "address-4"); |
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.
In theory this will affect all uses of assertAddresses: can we fix assertAddresses directly?
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 will investigate a way to fix assertAddress and assertConnectionCount directly!
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.
hello @bryce-anderson, i have made changes to edit assertAddresses and assertConnectionCount! I have changed assertConnectionCount to use a containsInAnyOrder instead of a contains during the assertion, and used a list to iterate through the addresses for assertAddresses. the tests should now pass with both ./gradlew :servicetalk-loadbalancer:test --tests <qualified_test_path> and ./gradlew :servicetalk-loadbalancer:nondexTest --tests <qualified_test_path>
I removed ordering assumptions and avoided Hamcrest reflection matchers, comparing actual extracted keys instead. Because p2c didn't have deterministic selection, I used containsInAnyOrder to match this behavior
| assertThat(selected1, is(anyOf(expected.values()))); | ||
|
|
||
| if (isRoundRobin()) { | ||
| // These asserts are flaky for p2c because we don't have deterministic selection. |
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.
This comment is still valuable.
| // These asserts are flaky for p2c because we don't have deterministic selection. | ||
| expected.remove(selected1); | ||
| assertThat(lb.selectConnection(any(), null).toFuture().get().address(), is(anyOf(expected.values()))); | ||
| assertConnectionCount(lb.usedAddresses(), connectionsCount("address-2", 0), |
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 this is a similar problem with getConnectionCount: can we take the same approach as above and fix the assertion helper method?
…cally instead of editing test cases
|
I also noticed that when running Replacing the assumption by putting the test code inside of an if statement when roundRobining is true: if (isRoundRobin()) {
// assertion checks
}ensures no reactive work is started, so the test is skipped deterministically and no nondeterministic async behavior leaks past the assumption. Are you open to accepting this change? Running |
Motivation
A flaky test was identified in
LoadBalancerTest, specificallyresubscribeToEventsWhenAllHostsAreUnhealthy, using NonDex.The failure was caused by the use of
assertAddresses(...), which relied on a specific order of elements inlb.usedAddresses().Since the load balancer does not guarantee address ordering, this assertion was nondeterministic across runs.
Modifications
with:
to make the check independent of element order
Added missing imports for
Collections,containsInAnyOrder, andhasPropertyAlso, to resolve the flaky test further down caused by selection in p2c being non-deterministic, I changed the assertion from:
to
Result
Steps to Reproduce:
build.gradlein the servicetalk-loadbalancer module:build.gradlein the servicetalk-loadbalancer module:apply plugin: 'edu.illinois.nondex'./gradlew :servicetalk-loadbalancer:nondexTest -DnondexRuns=10in the terminal from the root repository. It should result in the output for a few of the runs below: