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

Code before:
		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'")
		}
		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
// update is propagated to the ClientConn by the resolver. It tests the
// case where the resolver gets a good update first, and an error

Review comment (refactor):
nit: Since this is the main test function, and not a test helper anymore, we can use a simpler `defer r.Close()` instead of a `t.Cleanup()`.

Code after:
	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
// update is propagated to the ClientConn by the resolver. It tests the
// case where the resolver gets a good update first, and an error
// after the good update. The test also verifies that these are propagated to
// the ClientConn and that RPC succeeds as expected after receiving good update
// as well as ambient error.
func (s) TestResolverBadServiceUpdate_NACKedWithCache(t *testing.T) {
	// Spin up an xDS management server for the test.
	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()
	nodeID := uuid.New().String()
	mgmtServer, _, _, bc := setupManagementServerForTest(t, nodeID)

	stateCh, errCh, _ := buildResolverForTarget(t, resolver.Target{URL: *testutils.MustParseURL("xds:///" + defaultTestServiceName)}, bc)

	// Configure good listener and route configuration resources on the