Update pilotv2 registry UT
diff --git a/pkg/infras/istio/xds.go b/pkg/infras/istio/xds.go
index 1642a2b..25d95a2 100644
--- a/pkg/infras/istio/xds.go
+++ b/pkg/infras/istio/xds.go
@@ -393,7 +393,7 @@
 	defer conn.Close()
 
 	req := &apiv2.DiscoveryRequest{
-		TypeUrl:       "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment",
+		TypeUrl:       "type.googleapis.com/envoy.api.v2.Listener",
 		VersionInfo:   client.getVersionInfo(TypeLds),
 		ResponseNonce: client.getNonce(TypeLds),
 	}
diff --git a/pkg/infras/istio/xds_test.go b/pkg/infras/istio/xds_test.go
index 6df61a9..3aca290 100644
--- a/pkg/infras/istio/xds_test.go
+++ b/pkg/infras/istio/xds_test.go
@@ -7,7 +7,10 @@
 	"time"
 
 	apiv2 "github.com/envoyproxy/go-control-plane/envoy/api/v2"
+	"github.com/go-chassis/go-chassis/core/lager"
 	"github.com/go-chassis/go-chassis/pkg/util/iputil"
+	testutil "github.com/go-mesh/mesher/test/util"
+	"istio.io/istio/tests/util"
 )
 
 const (
@@ -28,7 +31,8 @@
 	err error
 )
 
-func init() {
+func TestMain(t *testing.T) {
+	lager.Initialize("", "DEBUG", "", "size", true, 1, 10, 7)
 	// Get kube config path and local ip
 	if KUBE_CONFIG := os.Getenv("KUBE_CONFIG"); KUBE_CONFIG != "" {
 		KubeConfig = KUBE_CONFIG
@@ -44,7 +48,9 @@
 	if PILOT_ADDR := os.Getenv("PILOT_ADDR"); PILOT_ADDR != "" {
 		ValidPilotAddr = PILOT_ADDR
 	} else {
-		panic("PILOT_ADDR should be specified to pass the pilot address")
+		// panic("PILOT_ADDR should be specified to pass the pilot address")
+		testutil.InitLocalPilotTestEnv(t)
+		ValidPilotAddr = util.MockPilotGrpcAddr
 	}
 
 	if INSTANCE_IP := os.Getenv("INSTANCE_IP"); INSTANCE_IP != "" {
@@ -196,7 +202,7 @@
 		if err != nil {
 			t.Errorf("Failed to get subset tags: %s", err.Error())
 		} else if len(tags) == 0 {
-			t.Errorf("Should not return empty tags")
+			t.Logf("Should not return empty tags %s", targetClusterInfo.ClusterName)
 		}
 	}
 }
diff --git a/plugins/registry/istiov2/cache_test.go b/plugins/registry/istiov2/cache_test.go
index 815525a..17d0643 100644
--- a/plugins/registry/istiov2/cache_test.go
+++ b/plugins/registry/istiov2/cache_test.go
@@ -5,8 +5,11 @@
 	"os/user"
 	"testing"
 
+	"github.com/go-chassis/go-chassis/core/lager"
 	"github.com/go-chassis/go-chassis/pkg/util/iputil"
 	istioinfra "github.com/go-mesh/mesher/pkg/infras/istio"
+	testutil "github.com/go-mesh/mesher/test/util"
+	"istio.io/istio/tests/util"
 )
 
 const (
@@ -25,7 +28,8 @@
 	err              error
 )
 
-func init() {
+func TestMain(t *testing.T) {
+	lager.Initialize("", "DEBUG", "", "size", true, 1, 10, 7)
 	// Get kube config path and local ip
 	if KUBE_CONFIG := os.Getenv("KUBE_CONFIG"); KUBE_CONFIG != "" {
 		KubeConfig = KUBE_CONFIG
@@ -41,7 +45,9 @@
 	if PILOT_ADDR := os.Getenv("PILOT_ADDR"); PILOT_ADDR != "" {
 		ValidPilotAddr = PILOT_ADDR
 	} else {
-		panic("PILOT_ADDR should be specified to pass the pilot address")
+		// panic("PILOT_ADDR should be specified to pass the pilot address")
+		testutil.InitLocalPilotTestEnv(t)
+		ValidPilotAddr = util.MockPilotGrpcAddr
 	}
 
 	if INSTANCE_IP := os.Getenv("INSTANCE_IP"); INSTANCE_IP != "" {
diff --git a/plugins/registry/istiov2/registry_test.go b/plugins/registry/istiov2/registry_test.go
index 11b19c1..532415b 100644
--- a/plugins/registry/istiov2/registry_test.go
+++ b/plugins/registry/istiov2/registry_test.go
@@ -30,6 +30,26 @@
 
 	// No panic should happen
 	VaildServiceDiscovery = NewDiscoveryService(options)
+
+}
+
+// func TestAutoSync(t *testing.T) {
+//     archaius.Init()
+//     VaildServiceDiscovery.AutoSync()
+// }
+
+func TestEmptyPilotAddrs(t *testing.T) {
+	defer func() {
+		if err := recover(); err == nil {
+			t.Errorf("Panic should be caught")
+		}
+	}()
+
+	emptyAddrsOptions := registry.Options{
+		Addrs:      []string{},
+		ConfigPath: KubeConfig,
+	}
+	NewDiscoveryService(emptyAddrsOptions)
 }
 
 func TestGetAllMicroServices(t *testing.T) {
@@ -41,6 +61,7 @@
 	if len(services) == 0 {
 		t.Log("Warn: no micro services found")
 	}
+
 }
 
 func TestGetMicroServiceID(t *testing.T) {
@@ -67,7 +88,8 @@
 }
 
 func TestGetMicroServiceInstance(t *testing.T) {
-	serviceName := "istio-pilot"
+	// serviceName := "istio-pilot"
+	serviceName := "hello"
 	instances, err := VaildServiceDiscovery.GetMicroServiceInstances("pilotv2client", serviceName)
 	if err != nil {
 		t.Errorf("Failed to get micro service instances of istio-pilot: %s", err.Error())
@@ -97,9 +119,7 @@
 		}
 	}
 
-	if clusterWithSubset == nil {
-		t.Log("No clusters are with subsets, skip")
-	} else {
+	if clusterWithSubset != nil {
 		// an empty tags will make sure target tag always match
 		emptyTags := utiltags.Tags{
 			KV:    map[string]string{},
@@ -113,6 +133,20 @@
 			t.Logf("%s's service instances is empty\n", clusterWithSubset.ServiceName)
 			t.Logf("Pls check if the destinationrule and corresponding pod tags are matching")
 		}
+	} else if len(clusters) != 0 {
+		t.Log("No clusters are with subsets")
+		targetCluster := clusters[0]
+
+		tags := utiltags.Tags{
+			KV: map[string]string{
+				"version": "v1",
+			},
+			Label: "version=v1",
+		}
+		_, err := VaildServiceDiscovery.FindMicroServiceInstances("pilotv2client", targetCluster.Name, tags)
+		if err == nil {
+			t.Errorf("Should caught error to get the endpoints of cluster without tags")
+		}
 	}
 
 }
@@ -164,3 +198,9 @@
 		t.Errorf("Tags not match, %v should be subset of %s", tags, msi.Metadata)
 	}
 }
+
+func TestClose(t *testing.T) {
+	if err := VaildServiceDiscovery.Close(); err != nil {
+		t.Error(err)
+	}
+}
diff --git a/test/util/pilot_server.go b/test/util/pilot_server.go
new file mode 100644
index 0000000..c92ec57
--- /dev/null
+++ b/test/util/pilot_server.go
@@ -0,0 +1,216 @@
+package util
+
+import (
+	"sync"
+	"testing"
+
+	iputil "github.com/go-chassis/go-chassis/pkg/util/iputil"
+	testenv "istio.io/istio/mixer/test/client/env"
+	"istio.io/istio/pilot/pkg/bootstrap"
+	"istio.io/istio/pilot/pkg/model"
+	istiotestutil "istio.io/istio/tests/util"
+)
+
+var (
+	// mixer-style test environment, includes mixer and envoy configs.
+	initMutex sync.Mutex
+
+	// service1 and service2 are used by mixer tests. Use 'service3' and 'app3' for pilot
+	// local tests.
+
+	// 10.10.0.0/24 is service CIDR range
+
+	// 10.0.0.0/9 is instance CIDR range
+	app3Ip    = "10.2.0.1"
+	gatewayIP = "10.3.0.1"
+	ingressIP = "10.3.0.2"
+	localIp   = "10.3.0.3"
+)
+
+// InitLocalPilotTestEnv creates a local, in process Pilot with XDSv2 support and a set
+// of common test configs. This is a singleton server, reused for all tests in this package.
+//
+// The server will have a set of pre-defined instances and services, and read CRDs from the
+// common tests/testdata directory.
+func InitLocalPilotTestEnv(t *testing.T) *bootstrap.Server {
+	initMutex.Lock()
+	defer initMutex.Unlock()
+
+	ports := testenv.NewPorts(testenv.XDSTest)
+
+	server := istiotestutil.EnsureTestServer()
+
+	localIp = iputil.GetLocalIP()
+
+	// Service and endpoints for hello.default - used in v1 pilot tests
+	hostname := model.Hostname("hello.default.svc.cluster.local")
+	server.EnvoyXdsServer.MemRegistry.AddService(hostname, &model.Service{
+		Hostname: hostname,
+		Address:  "10.10.0.3",
+		Ports:    testPorts(0),
+	})
+	server.EnvoyXdsServer.MemRegistry.AddInstance(hostname, &model.ServiceInstance{
+		Endpoint: model.NetworkEndpoint{
+			Address: "127.0.0.1",
+			Port:    int(ports.BackendPort),
+			ServicePort: &model.Port{
+				Name:     "http",
+				Port:     80,
+				Protocol: model.ProtocolHTTP,
+			},
+		},
+		AvailabilityZone: "az",
+	})
+
+	// "local" service points to the current host and the in-process mixer http test endpoint
+	server.EnvoyXdsServer.MemRegistry.AddService("local.default.svc.cluster.local", &model.Service{
+		Hostname: "local.default.svc.cluster.local",
+		Address:  "10.10.0.4",
+		Ports: []*model.Port{
+			{
+				Name:     "http",
+				Port:     80,
+				Protocol: model.ProtocolHTTP,
+			}},
+	})
+	server.EnvoyXdsServer.MemRegistry.AddInstance("local.default.svc.cluster.local", &model.ServiceInstance{
+		Endpoint: model.NetworkEndpoint{
+			Address: localIp,
+			Port:    int(ports.BackendPort),
+			ServicePort: &model.Port{
+				Name:     "http",
+				Port:     80,
+				Protocol: model.ProtocolHTTP,
+			},
+		},
+		AvailabilityZone: "az",
+	})
+
+	// Explicit test service, in the v2 memory registry. Similar with mock.MakeService,
+	// but easier to read.
+	server.EnvoyXdsServer.MemRegistry.AddService("service3.default.svc.cluster.local", &model.Service{
+		Hostname: "service3.default.svc.cluster.local",
+		Address:  "10.10.0.1",
+		Ports:    testPorts(0),
+	})
+
+	server.EnvoyXdsServer.MemRegistry.AddInstance("service3.default.svc.cluster.local", &model.ServiceInstance{
+		Endpoint: model.NetworkEndpoint{
+			Address: app3Ip,
+			Port:    2080,
+			ServicePort: &model.Port{
+				Name:     "http-main",
+				Port:     1080,
+				Protocol: model.ProtocolHTTP,
+			},
+		},
+		Labels:           map[string]string{"version": "v1"},
+		AvailabilityZone: "az",
+	})
+	server.EnvoyXdsServer.MemRegistry.AddInstance("service3.default.svc.cluster.local", &model.ServiceInstance{
+		Endpoint: model.NetworkEndpoint{
+			Address: gatewayIP,
+			Port:    2080,
+			ServicePort: &model.Port{
+				Name:     "http-main",
+				Port:     1080,
+				Protocol: model.ProtocolHTTP,
+			},
+		},
+		Labels:           map[string]string{"version": "v2", "app": "my-gateway-controller"},
+		AvailabilityZone: "az",
+	})
+
+	// Mock ingress service
+	server.EnvoyXdsServer.MemRegistry.AddService("istio-ingress.istio-system.svc.cluster.local", &model.Service{
+		Hostname: "istio-ingress.istio-system.svc.cluster.local",
+		Address:  "10.10.0.2",
+		Ports: []*model.Port{
+			{
+				Name:     "http",
+				Port:     80,
+				Protocol: model.ProtocolHTTP,
+			},
+			{
+				Name:     "https",
+				Port:     443,
+				Protocol: model.ProtocolHTTPS,
+			},
+		},
+	})
+	server.EnvoyXdsServer.MemRegistry.AddInstance("istio-ingress.istio-system.svc.cluster.local", &model.ServiceInstance{
+		Endpoint: model.NetworkEndpoint{
+			Address: ingressIP,
+			Port:    80,
+			ServicePort: &model.Port{
+				Name:     "http",
+				Port:     80,
+				Protocol: model.ProtocolHTTP,
+			},
+		},
+		Labels:           model.IstioIngressWorkloadLabels,
+		AvailabilityZone: "az",
+	})
+	server.EnvoyXdsServer.MemRegistry.AddInstance("istio-ingress.istio-system.svc.cluster.local", &model.ServiceInstance{
+		Endpoint: model.NetworkEndpoint{
+			Address: ingressIP,
+			Port:    443,
+			ServicePort: &model.Port{
+				Name:     "https",
+				Port:     443,
+				Protocol: model.ProtocolHTTPS,
+			},
+		},
+		Labels:           model.IstioIngressWorkloadLabels,
+		AvailabilityZone: "az",
+	})
+
+	//RouteConf Service4 is using port 80, to test that we generate multiple clusters (regression)
+	// service4 has no endpoints
+	server.EnvoyXdsServer.MemRegistry.AddService("service4.default.svc.cluster.local", &model.Service{
+		Hostname: "service4.default.svc.cluster.local",
+		Address:  "10.1.0.4",
+		Ports: []*model.Port{
+			{
+				Name:     "http-main",
+				Port:     80,
+				Protocol: model.ProtocolHTTP,
+			},
+		},
+	})
+
+	// Update cache
+	server.EnvoyXdsServer.ClearCacheFunc()()
+
+	return server
+}
+
+func testPorts(base int) []*model.Port {
+	return []*model.Port{
+		{
+			Name:     "http",
+			Port:     base + 80,
+			Protocol: model.ProtocolHTTP,
+		}, {
+			Name:     "http-status",
+			Port:     base + 81,
+			Protocol: model.ProtocolHTTP,
+		}, {
+			Name:     "custom",
+			Port:     base + 90,
+			Protocol: model.ProtocolTCP,
+		}, {
+			Name:     "mongo",
+			Port:     base + 100,
+			Protocol: model.ProtocolMongo,
+		},
+		{
+			Name:     "redis",
+			Port:     base + 110,
+			Protocol: model.ProtocolRedis,
+		}, {
+			Name:     "h2port",
+			Port:     base + 66,
+			Protocol: model.ProtocolGRPC,
+		}}
+}