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

xdsclient: cleanup listener watchers test #5506

Merged
merged 6 commits into from
Jul 28, 2022

Conversation

easwars
Copy link
Contributor

@easwars easwars commented Jul 14, 2022

Current tests use way too much magic and rely on a lot of internal state. These were written prior to us having a go-control-plane management server.

This change tests exactly all the functionality that was being tested earlier, but uses a real management server and relies on actual events happening instead of internal state.

Once this change is merged, I will send PRs to switch the other watcher tests as well. Then, we will be able to get rid of some complicated test setup logic.

RELEASE NOTES: none

@easwars easwars added this to the 1.49 Release milestone Jul 14, 2022
@easwars easwars requested review from dfawley and zasweq July 14, 2022 23:41
@easwars
Copy link
Contributor Author

easwars commented Jul 14, 2022

I'd appreciate if @dfawley can also take a quick look at this. But I really want @zasweq to take a good look. I felt that the existing tests were very hard to read, over-specified, relying too much on internal state etc. So, I want to make sure the new ones are easier to read for someone who is not super familiar with them.

@easwars
Copy link
Contributor Author

easwars commented Jul 21, 2022

Gentle ping ...

Copy link
Contributor

@zasweq zasweq left a comment

Choose a reason for hiding this comment

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

Looks good, thanks for doing this, much cleaner. The old tests were very hard to understand. Minor nits throughout.

@@ -28,6 +28,7 @@ import (
// after the watcher is canceled. The caller needs to handle this case.
func (c *clientImpl) WatchListener(serviceName string, cb func(xdsresource.ListenerUpdate, error)) (cancel func()) {
n := xdsresource.ParseName(serviceName)
logger.Infof("easwars: parsed name is %+V, %s", n, n)
Copy link
Contributor

Choose a reason for hiding this comment

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

Delete.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops .. sorry

// TestLDSWatch_ThreeWatchesForDifferentResourceNames covers the case where
// three watchers exist across two listener resources. The following sequence of
// events happen:
// 1. Three watches are registered for two listener resources
Copy link
Contributor

Choose a reason for hiding this comment

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

"resources: two watches for one, one watch for the other"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

// happen:
// 1. Two watches are registered for two listener resources
// 2. Management server sends an update containing both resources.
// 3. Management server sends an update removing one of the above resources
Copy link
Contributor

Choose a reason for hiding this comment

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

"removing one of the above resources, should trigger callback with resource removed error". To keep it consistent with Menghan's comment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reworded the comment with this suggestion.

// 1. Two watches are registered for two listener resources
// 2. Management server sends an update containing both resources.
// 3. Management server sends an update removing one of the above resources
// 4. Management server sends an update which modifies the exisiting resource.
Copy link
Contributor

Choose a reason for hiding this comment

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

"resource. The second watch shouldn't receive any update."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reworded the comment with this suggestion.

// TestLDSWatch_ResourceRemoved covers the cases where a resource being watched
// is removed from the management server. The following sequence of events
// happen:
// 1. Two watches are registered for two listener resources
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Some of your events have periods after, some don't. I'd prefer periods. Here and other parts of the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed lists altogether. So, no more periods or the lack of them.


// Register the third watch for a different listener resource.
updateCh3 := testutils.NewChannel()
ldsCancel3 := client.WatchListener(fmt.Sprintf("xdstp:///envoy.config.listener.v3.Listener/%s", ldsName), func(u xdsresource.ListenerUpdate, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional: Make this fmt.Sprintf(expression) a var since used twice.

Copy link
Contributor

@zasweq zasweq Jul 22, 2022

Choose a reason for hiding this comment

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

Actually, this is used 10 times. Package level const like ldsName/rdsName?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

defaultTestShortTimeout = 10 * time.Millisecond // For events expected to *not* happen.
)

var cmpOpts = []cmp.Option{
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a style reason this variable only used once is declared here rather than in the function it's used in?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I first added this, I though it would be used from multiple places. Didn't realize that it was being used only from one place. Moved it to that function.

defer client.Close()

const (
ldsName = "xdsclient-test-lds-resource"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: These two consts are declared 7 times, taking up 14 lines. Make this a package scoped const?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

}

// Update the second listener resource on the management server. The first
// watcher should not see an update, while the second wather should.
Copy link
Contributor

Choose a reason for hiding this comment

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

watcher*

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

t.Fatalf("update received with error: %v, want %q", gotErr, wantNACKErr)
}

// Verify that the watcher requesting for the good resource receives a good update.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment wraps past 180. Perhaps reword to "Verify that the watcher watching the good resource". "Requesting for the good resource" feels off.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@zasweq zasweq assigned easwars and dfawley and unassigned zasweq Jul 22, 2022
@easwars easwars assigned zasweq and unassigned easwars Jul 25, 2022
@easwars
Copy link
Contributor Author

easwars commented Jul 25, 2022

Thanks for review @zasweq. Addressed all comments.

Copy link
Contributor

@zasweq zasweq left a comment

Choose a reason for hiding this comment

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

LGTM outside of very minor comment nits. Code looks good.

// TestLDSWatch covers the case where a single watcher exists for a single
// listener resource. The test verifies the following scenarios:
// 1. An update from the management server containing the resource being
// watched, results in the invocation of the watch callback
Copy link
Contributor

Choose a reason for hiding this comment

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

Super nit: s results/should result, should not result for 2 and 3. Also periods after?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Here and in other comments. Thanks.

tests := []struct {
desc string
resourceName string
watchedResource *v3listenerpb.Listener // The resource being watched.
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, it's fine, I feel mildly about it. Maybe will help future readers.

// exist for a single listener resource. The test verifies the following
// scenarios:
// 1. An update from the management server containing the resource being
// watched, results in the invocation of both watch callbacks
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to above, s/results to should result and s/does not result/should not result and add periods.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


// TestLDSWatch_ResourceCaching covers the case where a watch is registered for
// a resource which is already in the cache. The test verifies that the new
// watch is handled from the cache, without a request being sent to the
Copy link
Contributor

Choose a reason for hiding this comment

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

Super nit: handled from cache meaning? handle could mean a lot of things, including invoking watch callback with error. Can you switch this statement to receives update from resources present in cache or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Thanks.

// is removed from the management server. The test verifies that removing
// resources from the management server triggers the watch callback with
// resource removed error. It also verifies that the watch callback for an
// unrelated resource is not invoked during the above flow.
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional: also talk about line 656 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.

Done.

})
defer ldsCancel2()

// Configure the management server two listener resources. One of these is a
Copy link
Contributor

Choose a reason for hiding this comment

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

server with two

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

// TestLDSWatch_PartialValid covers the case where a response from the
// management server contains both valid and invalid resources and is expected
// to be NACK'ed by the xdsclient. The test verifies that watchers corresponding
// to the valid resource (in the response) receive the update, while watchers
Copy link
Contributor

Choose a reason for hiding this comment

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

in the response is implied?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.


// Register two watches for two listener resources and have the
// callbacks push the received updates on to a channel.
resourceName1 := ldsName
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are you aliasing here? I actually think it improves readability but wanted to hear an explanation from you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same. I thought the distinction between the resources (just the fact that they correspond to different resources) was more important here than whether the resource name is of the old style or the new style.

@zasweq zasweq assigned easwars and unassigned zasweq Jul 26, 2022
@easwars
Copy link
Contributor Author

easwars commented Jul 27, 2022

Thank you very much for the detailed review.

rdsNameNewStyle = "xdstp:///envoy.config.listener.v3.Listener/xdsclient-test-rds-resource"
)

func newStringP(s string) *string {
Copy link
Member

Choose a reason for hiding this comment

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

Is this unused? Or used by other tests that weren't changed 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.

Removed. Maybe it was used at some point in time.

Comment on lines +105 to +103
// A very short deadline is used while waiting for the update, as this function
// is intended to be used when an update is not expected.
func verifyNoListenerUpdate(ctx context.Context, updateCh *testutils.Channel) error {
Copy link
Member

Choose a reason for hiding this comment

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

In this case, why require a context parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The incoming context will have the overall test deadline. And then we apply a shorter deadline here. This way, the callsite can have a single context and pass it to both verifyNoListenerUpdate and verifyListenerUpdate.

@zasweq
Copy link
Contributor

zasweq commented Jul 27, 2022

LGTM.

@easwars easwars removed their assignment Jul 27, 2022
@easwars easwars force-pushed the xdsclient_simplify_watcher_tests branch from b2c81ec to 1d2733d Compare July 27, 2022 18:32
@easwars easwars merged commit fd4700c into grpc:master Jul 28, 2022
@easwars easwars deleted the xdsclient_simplify_watcher_tests branch July 28, 2022 17:06
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants