Skip to content

grpctest: add test coverages of ExitIdle #8375

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

Merged
merged 19 commits into from
Aug 15, 2025

Conversation

hugehoo
Copy link
Contributor

@hugehoo hugehoo commented May 31, 2025

Fixes: #8118

  • Add test cases for
    • ExitIdle()
    • ExitIdleOne()
    • UpdateClientConnState
    • ResolverError

RELEASE NOTES: N/A

Copy link

codecov bot commented May 31, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.82%. Comparing base (a5e7cd6) to head (705625a).
⚠️ Report is 22 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8375      +/-   ##
==========================================
- Coverage   82.48%   81.82%   -0.67%     
==========================================
  Files         414      413       -1     
  Lines       40464    40518      +54     
==========================================
- Hits        33376    33152     -224     
- Misses       5736     5990     +254     
- Partials     1352     1376      +24     

see 48 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@eshitachandwani eshitachandwani self-requested a review June 6, 2025 13:52
@eshitachandwani eshitachandwani self-assigned this Jun 6, 2025

stub.Register(balancerName, stub.BalancerFuncs{
ExitIdle: func(_ *stub.BalancerData) {
called = true
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
called = true
close(exitIdleCh)

Here instead of a variable , a channel can be closed and waited for in a select block since this operation is done only once.

@hugehoo hugehoo requested a review from eshitachandwani June 8, 2025 08:37
select {
case <-exitIdleCh:
t.Fatalf("ExitIdle was called on sub-balancer even after BalancerGroup was closed")
case <-time.After(defaultTestTimeout):
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
case <-time.After(defaultTestTimeout):
case <-time.After(defaultShortTestTimeout):

We use defaultShortTestTimeout to wait for some time for cases that are not expected to happen , and use defaultTestTimeout for cases that are expected to happen.

@@ -484,6 +484,63 @@ func (s) TestBalancerGroupBuildOptions(t *testing.T) {
}
}

func (s) TestBalancerGroup_UpdateClientConnState_AfterClose(t *testing.T) {
balancerName := "stub-balancer-test-update-client-state-after-close"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: balancerName could be set to t.Name(). Here and elsewhere.

@hugehoo hugehoo force-pushed the test-coverage-ExitIdle branch from 9a6e323 to f2b8e02 Compare June 15, 2025 14:14
@eshitachandwani
Copy link
Member

Hey @hugehoo , is this ready for review or is it still a work in progress? If it is ready for review , please request a review and unassign yourself so that we can review it.

@hugehoo
Copy link
Contributor Author

hugehoo commented Jun 20, 2025

Hey @hugehoo , is this ready for review or is it still a work in progress? If it is ready for review , please request a review and unassign yourself so that we can review it.

hi, i'm still working on this pr, testing is still broken. i think i can request a review within this weekend.

@eshitachandwani
Copy link
Member

Hey @hugehoo are you still working on this PR?

@eshitachandwani eshitachandwani added Type: Testing Area: Testing Includes tests and testing utilities that we have for unit and e2e tests within our repo. labels Jul 14, 2025
@eshitachandwani eshitachandwani added this to the 1.75 Release milestone Jul 14, 2025
Copy link

This PR is labeled as requiring an update from the reporter, and no update has been received after 6 days. If no update is provided in the next 7 days, this issue will be automatically closed.

@github-actions github-actions bot added the stale label Jul 20, 2025
Copy link
Member

@eshitachandwani eshitachandwani left a comment

Choose a reason for hiding this comment

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

LGTM. Adding @easwars as a second reviewer.

@@ -484,6 +484,67 @@ func (s) TestBalancerGroupBuildOptions(t *testing.T) {
}
}

func (s) TestBalancerGroup_UpdateClientConnState_AfterClose(t *testing.T) {
balancerName := t.Name()
exitIdleCh := make(chan struct{}, 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not a channel used to indicate that ExitIdle was called. Can you please rename it appropriately. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed it to clientConnStateCh


func (s) TestBalancerGroup_ResolverError_AfterClose(t *testing.T) {
balancerName := t.Name()
exitIdleCh := make(chan struct{}, 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated name as resolveErrorCh

bg.Add(testBalancerIDs[0], balancer.Get(balancerName))
bg.ExitIdleOne("non-existent-id")

if called {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use a channel as used in the other tests instead of a local variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

chaged to declare channel as exitIdleCh

}

func (s) TestBalancerGroup_ExitIdleOne_NonExistentID(t *testing.T) {
balancerName := "stub-balancer-test-exit-idle-one-missing-id"
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be t.Name() as well, right? Any reason for that not to be the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i missed to fixed it,
just updated as t.Name() here too

Comment on lines 759 to 761
balancerOne := "stub-balancer-test-balancer-group-exit-idle-one"
balancerTwo := "stub-balancer-test-balancer-group-exit-idle-two"
balancerThree := "stub-balancer-test-balancer-group-exit-idle-three"
Copy link
Contributor

Choose a reason for hiding this comment

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

Does three balancers add any more value than two?

And why not?
balancer1 := t.Name() + "-1"
balancer2 := t.Name() + "-2"

Comment on lines 763 to 774
balancerNames := []string{balancerOne, balancerTwo, balancerThree}
testIDs := []string{testBalancerIDs[0], testBalancerIDs[1], testBalancerIDs[2]}

exitIdleCh := make(chan string, len(balancerNames))

for _, name := range balancerNames {
stub.Register(name, stub.BalancerFuncs{
ExitIdle: func(_ *stub.BalancerData) {
exitIdleCh <- name
},
})
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I would get rid of the slices and the loops and instead keep this downright simple and dump.

  // Have two test IDs: testID1 and testID2
  // Have two channels, exitIdleCh1 and exitIdleCh2
  // Register two stub balancers, the first one for balancer1 that writes to exitIdleCh1 and the second one for balancer2 that writes to exitIdleCh2

  // Create the balancer group, and add the child balancers in there

  // Call ExitIdle

  // Validate that both exitIdleCh1 and exitIdleCh2 are written to. (I don't think it's an issue if one of those are written to more than once). In this case though, you might have to spawn goroutines to validate that both channels are written to, since we cannot guarantee the order in which they would be written to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

applied in 9d703f2

}

func (s) TestBalancerGroup_ExitIdle_AfterClose(t *testing.T) {
balancerName := "stub-balancer-test-balancer-group-exit-idle-after-close"
Copy link
Contributor

Choose a reason for hiding this comment

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

t.Name here as well.


stub.Register(balancerName, stub.BalancerFuncs{
ExitIdle: func(_ *stub.BalancerData) {
close(exitIdleCh)
Copy link
Contributor

Choose a reason for hiding this comment

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

In some places, you write an empty struct to the channel, while in other places, you close the channel. I understand this is minor and super nit-picky, but can you please choose one approach and stay consistent across the PR. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i decided to send an empty struct to a buffered channel, it's more robust and consistent approach i think.

@easwars easwars assigned hugehoo and unassigned easwars Aug 6, 2025
@easwars easwars assigned easwars and unassigned hugehoo Aug 7, 2025
@hugehoo hugehoo requested a review from easwars August 8, 2025 16:01
@easwars easwars assigned hugehoo and unassigned easwars Aug 13, 2025
@hugehoo hugehoo requested a review from easwars August 14, 2025 00:40
Copy link
Contributor

@easwars easwars left a comment

Choose a reason for hiding this comment

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

LGTM, modulo the last minor comment.


func (s) TestBalancerGroup_ExitIdle_AfterClose(t *testing.T) {
balancerName := t.Name()
exitIdleCh := make(chan struct{})
Copy link
Contributor

Choose a reason for hiding this comment

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

Oops. Sorry, didn't catch this earlier. This channel needs to have a buffer of 1. Otherwise, the writer would block if there is no reader.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@easwars fixed here 705625a.
thx for the helpful review 👍🏻

@easwars easwars assigned easwars and hugehoo and unassigned hugehoo and easwars Aug 14, 2025
@hugehoo hugehoo requested a review from easwars August 15, 2025 08:52
@easwars easwars merged commit 0ebea3e into grpc:master Aug 15, 2025
15 checks passed
@easwars
Copy link
Contributor

easwars commented Aug 15, 2025

Thank you, @hugehoo, for your contribution!

case <-time.After(defaultTestShortTimeout):
}
}

func (s) TestBalancerExitIdleOne(t *testing.T) {
const balancerName = "stub-balancer-test-balancergroup-exit-idle-one"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@easwars i just got nitpicking question.
in this pr, i got reviewed to use t.Name() for balancerName. but some of the cases are still using hard-coded name. Is there any specific reason for it? or would it be better to be updated as t.name() too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Testing Includes tests and testing utilities that we have for unit and e2e tests within our repo. Type: Testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

balancergroup: Add test coverage
4 participants