Repository: grpc/grpc-go
File: internal/xds/resolver/xds_resolver_test.go (Go)

Code before:
				ConfigType: &v3listenerpb.Filter_TypedConfig{TypedConfig: hcm},
			}},
		}},
	}
	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, []*v3listenerpb.Listener{lis}, nil)

	// Build the resolver inline (duplicating buildResolverForTarget internals)
	// to avoid issues with blocked channel writes when NACKs occur.
	target := resolver.Target{URL: *testutils.MustParseURL("xds:///" + defaultTestServiceName)}
	var builder resolver.Builder
	if bc != nil {
		// Create an xDS resolver with the provided bootstrap configuration.
		if internal.NewXDSResolverWithConfigForTesting == nil {
			t.Fatalf("internal.NewXDSResolverWithConfigForTesting is nil")
		}
		var err error
		builder, err = internal.NewXDSResolverWithConfigForTesting.(func([]byte) (resolver.Builder, error))(bc)
		if err != nil {
			t.Fatalf("Failed to create xDS resolver for testing: %v", err)
		}
	} else {
		builder = resolver.Get(xdsresolver.Scheme)
		if builder == nil {
			t.Fatalf("Scheme %q is not registered", xdsresolver.Scheme)
		}
	}

	errCh := testutils.NewChannel()
	reportErrorF := func(err error) {
		errCh.Replace(err)
	}
	tcc := &testutils.ResolverClientConn{Logger: t, ReportErrorF: reportErrorF}
	r, err := builder.Build(target, tcc, resolver.BuildOptions{
		Authority: url.PathEscape(target.Endpoint()),
	})
	if err != nil {
		t.Fatalf("Failed to build xDS resolver for target %q: %v", target, err)
	}
	t.Cleanup(func() {
		r.Close()
	})

	// Wait for and verify the error update from the resolver.
	// Since the resource is not cached, it should be received as resource error.
	select {
	case <-ctx.Done():
		t.Fatalf("Timeout waiting for error to be propagated to the ClientConn")
	case gotErr := <-errCh.C:
		if gotErr == nil {
			t.Fatalf("got nil error from resolver, want error containing 'no RouteSpecifier'")
		}

Review comment (suggestion):
We can get rid of this `else` block since `bootstrapContents` returned by `setupManagementServerForTest` are always non-nil.

Code after:
			}},
		}},
	}
	configureResourcesOnManagementServer(ctx, t, mgmtServer, nodeID, []*v3listenerpb.Listener{lis}, nil)

	// Build the resolver inline (duplicating buildResolverForTarget internals)
	// to avoid issues with blocked channel writes when NACKs occur.
	target := resolver.Target{URL: *testutils.MustParseURL("xds:///" + defaultTestServiceName)}

	// Create an xDS resolver with the provided bootstrap configuration.
	if internal.NewXDSResolverWithConfigForTesting == nil {
		t.Fatalf("internal.NewXDSResolverWithConfigForTesting is nil")
	}

	builder, err := internal.NewXDSResolverWithConfigForTesting.(func([]byte) (resolver.Builder, error))(bc)
	if err != nil {
		t.Fatalf("Failed to create xDS resolver for testing: %v", err)
	}

	errCh := testutils.NewChannel()
	tcc := &testutils.ResolverClientConn{Logger: t, ReportErrorF: func(err error) { errCh.Replace(err) }}
	r, err := builder.Build(target, tcc, resolver.BuildOptions{
		Authority: url.PathEscape(target.Endpoint()),
	})
	if err != nil {
		t.Fatalf("Failed to build xDS resolver for target %q: %v", target, err)
	}
	defer r.Close()

	// Wait for and verify the error update from the resolver.
	// Since the resource is not cached, it should be received as resource error.
	select {
	case <-ctx.Done():
		t.Fatalf("Timeout waiting for error to be propagated to the ClientConn")
	case gotErr := <-errCh.C:
		if gotErr == nil {
			t.Fatalf("got nil error from resolver, want error containing 'no RouteSpecifier'")
		}
		errStr := fmt.Sprint(gotErr)
		if !strings.Contains(errStr, "no RouteSpecifier") {
			t.Fatalf("got error from resolver %q, want error containing 'no RouteSpecifier'", errStr)
		}
		if !strings.Contains(errStr, nodeID) {
			t.Fatalf("got error from resolver %q, want nodeID %q", errStr, nodeID)
		}
	}
}

// Tests the case where a resource, present in cache, returned by the
// management server is NACKed by the xDS client, which then returns
// an update containing an ambient error to the resolver. Verifies that the