Repository: grpc/grpc-go
File: xds/internal/xdsclient/tests/lds_watchers_test.go (Go)

Code before:
	resources = e2e.UpdateOptions{
		NodeID:         nodeID,
		Listeners:      []*v3listenerpb.Listener{e2e.DefaultClientListener(resourceName2, "new-rds-resource")},
		SkipValidation: true,
	}
	if err := mgmtServer.Update(ctx, resources); err != nil {
		t.Fatalf("Failed to update management server with resources: %v, err: %v", resources, err)
	}
	if err := verifyNoListenerUpdate(ctx, lw1.updateCh); err != nil {
		t.Fatal(err)
	}
	wantUpdate = listenerUpdateErrTuple{
		update: xdsresource.ListenerUpdate{
			RouteConfigName: "new-rds-resource",
			HTTPFilters:     []xdsresource.HTTPFilter{{Name: "router"}},
		},
	}
	if err := verifyListenerUpdate(ctx, lw2.updateCh, wantUpdate); err != nil {
		t.Fatal(err)
	}
}

// TestLDSWatch_NewWatcherForRemovedResource covers the case where a new
// watcher registers for the resource which is removed. The test verifies
// the following scenarios:
//  1. Removing a resource should trigger the watch callback with a resource
//     removed error to existing watcher.
//  2. If any new watcher try to register for removed resource, it should
//     trigger watch callback to it with a resource removed error as well.
func TestLDSWatch_NewWatcherForRemovedResource(t *testing.T) {
	mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})

	nodeID := uuid.New().String()
	bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address)
	testutils.CreateBootstrapFileForTesting(t, bc)

	// Create an xDS client with the above bootstrap contents.
	client, close, err := xdsclient.NewForTesting(xdsclient.OptionsForTesting{
		Name:     t.Name(),
		Contents: bc,
	})
	if err != nil {
		t.Fatalf("Failed to create xDS client: %v", err)
	}
	defer close()

	// Register watch for the listener resources and have the
	// callbacks push the received updates on to a channel.
	resourceName := ldsName
	lw1 := newListenerWatcher()
	ldsCancel1 := xdsresource.WatchListener(client, resourceName, lw1)

Review comment (suggestion):
How about:

```
// 1. When a resource is deleted by the management server, any active 
// watchers of that resource should be notified with a "resource removed" error through their watch callback.
// 2. If a new watcher attempts to register for a resource that has already been deleted, 
// its watch callback should be immediately invoked with a "resource removed" error.
```

Code after:
	resources = e2e.UpdateOptions{
		NodeID:         nodeID,
		Listeners:      []*v3listenerpb.Listener{e2e.DefaultClientListener(resourceName2, "new-rds-resource")},
		SkipValidation: true,
	}
	if err := mgmtServer.Update(ctx, resources); err != nil {
		t.Fatalf("Failed to update management server with resources: %v, err: %v", resources, err)
	}
	if err := verifyNoListenerUpdate(ctx, lw1.updateCh); err != nil {
		t.Fatal(err)
	}
	wantUpdate = listenerUpdateErrTuple{
		update: xdsresource.ListenerUpdate{
			RouteConfigName: "new-rds-resource",
			HTTPFilters:     []xdsresource.HTTPFilter{{Name: "router"}},
		},
	}
	if err := verifyListenerUpdate(ctx, lw2.updateCh, wantUpdate); err != nil {
		t.Fatal(err)
	}
}

// TestLDSWatch_NewWatcherForRemovedResource covers the case where a new
// watcher registers for a resource that has been removed. The test verifies
// the following scenarios:
//  1. When a resource is deleted by the management server, any active
//     watchers of that resource should be notified with a "resource removed"
//     error through their watch callback.
//  2. If a new watcher attempts to register for a resource that has already
//     been deleted, its watch callback should be immediately invoked with a
//     "resource removed" error.
func (s) TestLDSWatch_NewWatcherForRemovedResource(t *testing.T) {
	mgmtServer := e2e.StartManagementServer(t, e2e.ManagementServerOptions{})

	nodeID := uuid.New().String()
	bc := e2e.DefaultBootstrapContents(t, nodeID, mgmtServer.Address)

	// Create an xDS client with the above bootstrap contents.
	client, close, err := xdsclient.NewForTesting(xdsclient.OptionsForTesting{
		Name:     t.Name(),
		Contents: bc,
	})
	if err != nil {
		t.Fatalf("Failed to create xDS client: %v", err)
	}
	defer close()

	// Register watch for the listener resource and have the
	// callbacks push the received updates on to a channel.
	lw1 := newListenerWatcher()
	ldsCancel1 := xdsresource.WatchListener(client, ldsName, lw1)