func (s) TestResourceResolverOneDNSResource(t *testing.T) {
	for _, test := range []struct {
		name       string
		target     string
		wantTarget resolver.Target
		addrs      []resolver.Address
		want       []priorityConfig
	}{
		{
			name:       "watch DNS",
			target:     testDNSTarget,
			wantTarget: resolver.Target{Scheme: "dns", Endpoint: testDNSTarget},
			addrs:      []resolver.Address{{Addr: "1.1.1.1"}, {Addr: "2.2.2.2"}},
			want: []priorityConfig{{
				mechanism: DiscoveryMechanism{
					Type:        DiscoveryMechanismTypeLogicalDNS,
					DNSHostname: testDNSTarget,
				},
				addresses: []string{"1.1.1.1", "2.2.2.2"},
			}},
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			dnsTargetCh, dnsCloseCh, _, dnsR, cleanup := setupDNS()
			defer cleanup()
			fakeClient := fakeclient.NewClient()
			rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient})
			rr.updateMechanisms([]DiscoveryMechanism{{
				Type:        DiscoveryMechanismTypeLogicalDNS,
				DNSHostname: test.target,
			}})
			ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
			defer ctxCancel()
			select {
			case target := <-dnsTargetCh:
				if diff := cmp.Diff(target, test.wantTarget); diff != "" {
					t.Fatalf("got unexpected DNS target to watch, diff (-got, +want): %v", diff)
				}
			case <-ctx.Done():
				t.Fatal("Timed out waiting for building DNS resolver")
			}
			dnsR.UpdateState(resolver.State{Addresses: test.addrs})
			select {
			case u := <-rr.updateChannel:
				if diff := cmp.Diff(u.priorities, test.want, cmp.AllowUnexported(priorityConfig{})); diff != "" {
					t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff)
				}
			case <-ctx.Done():
				t.Fatal("Timed out waiting for update from update channel.")
			}
			rr.stop()
			select {
			case <-dnsCloseCh:
			case <-ctx.Done():
				t.Fatal("Timed out waiting for closing DNS resolver")
			}
		})
	}
}
Test the simple case of one DNS resolver.
package clusterresolver
import (
	"context"
	"fmt"
	"testing"
	"github.com/google/go-cmp/cmp"
	"google.golang.org/grpc/resolver"
	"google.golang.org/grpc/resolver/manual"
	"google.golang.org/grpc/xds/internal/testutils"
	"google.golang.org/grpc/xds/internal/testutils/fakeclient"
	xdsclient "google.golang.org/grpc/xds/internal/xdsclient"
)
const (
	testDNSTarget = "dns.com"
)
var (
	testEDSUpdates []xdsclient.EndpointsUpdate
)
func init() {
	clab1 := testutils.NewClusterLoadAssignmentBuilder(testClusterNames[0], nil)
	clab1.AddLocality(testSubZones[0], 1, 0, testEndpointAddrs[:1], nil)
	testEDSUpdates = append(testEDSUpdates, parseEDSRespProtoForTesting(clab1.Build()))
	clab2 := testutils.NewClusterLoadAssignmentBuilder(testClusterNames[0], nil)
	clab2.AddLocality(testSubZones[1], 1, 0, testEndpointAddrs[1:2], nil)
	testEDSUpdates = append(testEDSUpdates, parseEDSRespProtoForTesting(clab2.Build()))
}
func (s) TestResourceResolverOneEDSResource(t *testing.T) {
	for _, test := range []struct {
		name                 string
		clusterName, edsName string
		wantName             string
		edsUpdate            xdsclient.EndpointsUpdate
		want                 []priorityConfig
	}{
		{name: "watch EDS",
			clusterName: testClusterName,
			edsName:     testEDSServcie,
			wantName:    testEDSServcie,
			edsUpdate:   testEDSUpdates[0],
			want: []priorityConfig{{
				mechanism: DiscoveryMechanism{
					Type:           DiscoveryMechanismTypeEDS,
					Cluster:        testClusterName,
					EDSServiceName: testEDSServcie,
				},
				edsResp: testEDSUpdates[0],
			}},
		},
		{
			name:        "watch EDS no EDS name",  
			clusterName: testClusterName,
			wantName:    testClusterName,
			edsUpdate:   testEDSUpdates[1],
			want: []priorityConfig{{
				mechanism: DiscoveryMechanism{
					Type:    DiscoveryMechanismTypeEDS,
					Cluster: testClusterName,
				},
				edsResp: testEDSUpdates[1],
			}},
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			fakeClient := fakeclient.NewClient()
			rr := newResourceResolver(&clusterResolverBalancer{xdsClient: fakeClient})
			rr.updateMechanisms([]DiscoveryMechanism{{
				Type:           DiscoveryMechanismTypeEDS,
				Cluster:        test.clusterName,
				EDSServiceName: test.edsName,
			}})
			ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
			defer ctxCancel()
			gotEDSName, err := fakeClient.WaitForWatchEDS(ctx)
			if err != nil {
				t.Fatalf("xdsClient.WatchCDS failed with error: %v", err)
			}
			if gotEDSName != test.wantName {
				t.Fatalf("xdsClient.WatchEDS called for cluster: %v, want: %v", gotEDSName, test.wantName)
			}
			fakeClient.InvokeWatchEDSCallback("", test.edsUpdate, nil)
			select {
			case u := <-rr.updateChannel:
				if diff := cmp.Diff(u.priorities, test.want, cmp.AllowUnexported(priorityConfig{})); diff != "" {
					t.Fatalf("got unexpected resource update, diff (-got, +want): %v", diff)
				}
			case <-ctx.Done():
				t.Fatal("Timed out waiting for update from update channel.")
			}
			rr.stop()
			edsNameCanceled, err := fakeClient.WaitForCancelEDSWatch(ctx)
			if err != nil {
				t.Fatalf("xdsClient.CancelCDS failed with error: %v", err)
			}
			if edsNameCanceled != test.wantName {
				t.Fatalf("xdsClient.CancelEDS called for %v, want: %v", edsNameCanceled, testEDSServcie)
			}
		})
	}
}
func setupDNS() (chan resolver.Target, chan struct{}, chan resolver.ResolveNowOptions, *manual.Resolver, func()) {
	dnsTargetCh := make(chan resolver.Target, 1)
	dnsCloseCh := make(chan struct{}, 1)
	resolveNowCh := make(chan resolver.ResolveNowOptions, 1)
	mr := manual.NewBuilderWithScheme("dns")
	mr.BuildCallback = func(target resolver.Target, _ resolver.ClientConn, _ resolver.BuildOptions) { dnsTargetCh <- target }
	mr.CloseCallback = func() { dnsCloseCh <- struct{}{} }
	mr.ResolveNowCallback = func(opts resolver.ResolveNowOptions) { resolveNowCh <- opts }
	oldNewDNS := newDNS
	newDNS = func(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
		return mr.Build(target, cc, opts)
	}
	return dnsTargetCh, dnsCloseCh, resolveNowCh, mr, func() { newDNS = oldNewDNS }
}