func TestURLsString(t *testing.T) { tests := []struct { us URLs wstr string }{ { URLs{}, "", }, { testutil.MustNewURLs(t, []string{"http://127.0.0.1:2379"}), "http://127.0.0.1:2379", }, { testutil.MustNewURLs(t, []string{ "http://127.0.0.1:2379", "http://127.0.0.2:2379", }), "http://127.0.0.1:2379,http://127.0.0.2:2379", }, { testutil.MustNewURLs(t, []string{ "http://127.0.0.2:2379", "http://127.0.0.1:2379", }), "http://127.0.0.2:2379,http://127.0.0.1:2379", }, } for i, tt := range tests { g := tt.us.String() if g != tt.wstr { t.Errorf("#%d: string = %s, want %s", i, g, tt.wstr) } } }
func TestNewURLs(t *testing.T) { tests := []struct { strs []string wurls URLs }{ { []string{"http://127.0.0.1:2379"}, testutil.MustNewURLs(t, []string{"http://127.0.0.1:2379"}), }, // it can trim space { []string{" http://127.0.0.1:2379 "}, testutil.MustNewURLs(t, []string{"http://127.0.0.1:2379"}), }, // it does sort { []string{ "http://127.0.0.2:2379", "http://127.0.0.1:2379", }, testutil.MustNewURLs(t, []string{ "http://127.0.0.1:2379", "http://127.0.0.2:2379", }), }, } for i, tt := range tests { urls, _ := NewURLs(tt.strs) if !reflect.DeepEqual(urls, tt.wurls) { t.Errorf("#%d: urls = %+v, want %+v", i, urls, tt.wurls) } } }
func TestURLsStringSlice(t *testing.T) { tests := []struct { us URLs wstr []string }{ { URLs{}, []string{}, }, { testutil.MustNewURLs(t, []string{"http://127.0.0.1:2379"}), []string{"http://127.0.0.1:2379"}, }, { testutil.MustNewURLs(t, []string{ "http://127.0.0.1:2379", "http://127.0.0.2:2379", }), []string{"http://127.0.0.1:2379", "http://127.0.0.2:2379"}, }, { testutil.MustNewURLs(t, []string{ "http://127.0.0.2:2379", "http://127.0.0.1:2379", }), []string{"http://127.0.0.2:2379", "http://127.0.0.1:2379"}, }, } for i, tt := range tests { g := tt.us.StringSlice() if !reflect.DeepEqual(g, tt.wstr) { t.Errorf("#%d: string slice = %+v, want %+v", i, g, tt.wstr) } } }
// This is only tested in Go1.5+ because Go1.4 doesn't support literal IPv6 address with zone in // URI (https://github.com/golang/go/issues/6530). func TestNewURLsMapIPV6(t *testing.T) { c, err := NewURLsMap("mem1=http://[2001:db8::1]:2380,mem1=http://[fe80::6e40:8ff:feb1:58e4%25en0]:2380,mem2=http://[fe80::92e2:baff:fe7c:3224%25ext0]:2380") if err != nil { t.Fatalf("unexpected parse error: %v", err) } wc := URLsMap(map[string]URLs{ "mem1": testutil.MustNewURLs(t, []string{"http://[2001:db8::1]:2380", "http://[fe80::6e40:8ff:feb1:58e4%25en0]:2380"}), "mem2": testutil.MustNewURLs(t, []string{"http://[fe80::92e2:baff:fe7c:3224%25ext0]:2380"}), }) if !reflect.DeepEqual(c, wc) { t.Errorf("cluster = %#v, want %#v", c, wc) } }
func TestNameURLPairsString(t *testing.T) { cls := URLsMap(map[string]URLs{ "abc": testutil.MustNewURLs(t, []string{"http://1.1.1.1:1111", "http://0.0.0.0:0000"}), "def": testutil.MustNewURLs(t, []string{"http://2.2.2.2:2222"}), "ghi": testutil.MustNewURLs(t, []string{"http://3.3.3.3:1234", "http://127.0.0.1:2380"}), // no PeerURLs = not included "four": testutil.MustNewURLs(t, []string{}), "five": testutil.MustNewURLs(t, nil), }) w := "abc=http://0.0.0.0:0000,abc=http://1.1.1.1:1111,def=http://2.2.2.2:2222,ghi=http://127.0.0.1:2380,ghi=http://3.3.3.3:1234" if g := cls.String(); g != w { t.Fatalf("NameURLPairs.String():\ngot %#v\nwant %#v", g, w) } }
func TestParseInitialCluster(t *testing.T) { c, err := NewURLsMap("mem1=http://10.0.0.1:2379,mem1=http://128.193.4.20:2379,mem2=http://10.0.0.2:2379,default=http://127.0.0.1:2379") if err != nil { t.Fatalf("unexpected parse error: %v", err) } wc := URLsMap(map[string]URLs{ "mem1": testutil.MustNewURLs(t, []string{"http://10.0.0.1:2379", "http://128.193.4.20:2379"}), "mem2": testutil.MustNewURLs(t, []string{"http://10.0.0.2:2379"}), "default": testutil.MustNewURLs(t, []string{"http://127.0.0.1:2379"}), }) if !reflect.DeepEqual(c, wc) { t.Errorf("cluster = %+v, want %+v", c, wc) } }
func TestURLsSort(t *testing.T) { g := testutil.MustNewURLs(t, []string{ "http://127.0.0.4:2379", "http://127.0.0.2:2379", "http://127.0.0.1:2379", "http://127.0.0.3:2379", }) w := testutil.MustNewURLs(t, []string{ "http://127.0.0.1:2379", "http://127.0.0.2:2379", "http://127.0.0.3:2379", "http://127.0.0.4:2379", }) gurls := URLs(g) gurls.Sort() if !reflect.DeepEqual(g, w) { t.Errorf("URLs after sort = %#v, want %#v", g, w) } }
func TestTransportUpdate(t *testing.T) { peer := newFakePeer() tr := &transport{ peers: map[types.ID]Peer{types.ID(1): peer}, } u := "http://localhost:7001" tr.UpdatePeer(types.ID(1), []string{u}) wurls := types.URLs(testutil.MustNewURLs(t, []string{"http://localhost:7001"})) if !reflect.DeepEqual(peer.urls, wurls) { t.Errorf("urls = %+v, want %+v", peer.urls, wurls) } }
func TestURLPickerUpdate(t *testing.T) { picker := mustNewURLPicker(t, []string{"http://127.0.0.1:2380", "http://127.0.0.1:7001"}) picker.update(testutil.MustNewURLs(t, []string{"http://localhost:2380", "http://localhost:7001"})) u := picker.pick() urlmap := map[url.URL]bool{ url.URL{Scheme: "http", Host: "localhost:2380"}: true, url.URL{Scheme: "http", Host: "localhost:7001"}: true, } if !urlmap[u] { t.Errorf("url picked = %+v, want a possible url in %+v", u, urlmap) } }
func TestGenClusterString(t *testing.T) { tests := []struct { token string urls []string wstr string }{ { "default", []string{"http://127.0.0.1:4001"}, "default=http://127.0.0.1:4001", }, { "node1", []string{"http://0.0.0.0:2379", "http://1.1.1.1:2379"}, "node1=http://0.0.0.0:2379,node1=http://1.1.1.1:2379", }, } for i, tt := range tests { urls := testutil.MustNewURLs(t, tt.urls) str := genClusterString(tt.token, urls) if str != tt.wstr { t.Errorf("#%d: cluster = %s, want %s", i, str, tt.wstr) } } }
func mustNewURLPicker(t *testing.T, us []string) *urlPicker { urls := testutil.MustNewURLs(t, us) return newURLPicker(urls) }
func TestSRVGetCluster(t *testing.T) { defer func() { lookupSRV = net.LookupSRV resolveTCPAddr = net.ResolveTCPAddr }() name := "dnsClusterTest" tests := []struct { withSSL []*net.SRV withoutSSL []*net.SRV urls []string dns map[string]string expected string }{ { []*net.SRV{}, []*net.SRV{}, nil, nil, "", }, { []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2480}, &net.SRV{Target: "10.0.0.2", Port: 2480}, &net.SRV{Target: "10.0.0.3", Port: 2480}, }, []*net.SRV{}, nil, nil, "0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480", }, { []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2480}, &net.SRV{Target: "10.0.0.2", Port: 2480}, &net.SRV{Target: "10.0.0.3", Port: 2480}, }, []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2380}, }, nil, nil, "0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480,3=http://10.0.0.1:2380", }, { []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2480}, &net.SRV{Target: "10.0.0.2", Port: 2480}, &net.SRV{Target: "10.0.0.3", Port: 2480}, }, []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2380}, }, []string{"https://10.0.0.1:2480"}, nil, "dnsClusterTest=https://10.0.0.1:2480,0=https://10.0.0.2:2480,1=https://10.0.0.3:2480,2=http://10.0.0.1:2380", }, // matching local member with resolved addr and return unresolved hostnames { []*net.SRV{ &net.SRV{Target: "1.example.com.", Port: 2480}, &net.SRV{Target: "2.example.com.", Port: 2480}, &net.SRV{Target: "3.example.com.", Port: 2480}, }, nil, []string{"https://10.0.0.1:2480"}, map[string]string{"1.example.com:2480": "10.0.0.1:2480", "2.example.com:2480": "10.0.0.2:2480", "3.example.com:2480": "10.0.0.3:2480"}, "dnsClusterTest=https://1.example.com:2480,0=https://2.example.com:2480,1=https://3.example.com:2480", }, } for i, tt := range tests { lookupSRV = func(service string, proto string, domain string) (string, []*net.SRV, error) { if service == "etcd-server-ssl" { return "", tt.withSSL, nil } if service == "etcd-server" { return "", tt.withoutSSL, nil } return "", nil, errors.New("Unkown service in mock") } resolveTCPAddr = func(network, addr string) (*net.TCPAddr, error) { if tt.dns == nil || tt.dns[addr] == "" { return net.ResolveTCPAddr(network, addr) } return net.ResolveTCPAddr(network, tt.dns[addr]) } urls := testutil.MustNewURLs(t, tt.urls) str, token, err := SRVGetCluster(name, "example.com", "token", urls) if err != nil { t.Fatalf("%d: err: %#v", i, err) } if token != "token" { t.Errorf("%d: token: %s", i, token) } if str != tt.expected { t.Errorf("#%d: cluster = %s, want %s", i, str, tt.expected) } } }
func TestSRVGetCluster(t *testing.T) { defer func() { lookupSRV = net.LookupSRV }() name := "dnsClusterTest" tests := []struct { withSSL []*net.SRV withoutSSL []*net.SRV urls []string expected string }{ { []*net.SRV{}, []*net.SRV{}, nil, "", }, { []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2480}, &net.SRV{Target: "10.0.0.2", Port: 2480}, &net.SRV{Target: "10.0.0.3", Port: 2480}, }, []*net.SRV{}, nil, "0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480", }, { []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2480}, &net.SRV{Target: "10.0.0.2", Port: 2480}, &net.SRV{Target: "10.0.0.3", Port: 2480}, }, []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 7001}, }, nil, "0=https://10.0.0.1:2480,1=https://10.0.0.2:2480,2=https://10.0.0.3:2480,3=http://10.0.0.1:7001", }, { []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 2480}, &net.SRV{Target: "10.0.0.2", Port: 2480}, &net.SRV{Target: "10.0.0.3", Port: 2480}, }, []*net.SRV{ &net.SRV{Target: "10.0.0.1", Port: 7001}, }, []string{"https://10.0.0.1:2480"}, "dnsClusterTest=https://10.0.0.1:2480,0=https://10.0.0.2:2480,1=https://10.0.0.3:2480,2=http://10.0.0.1:7001", }, } for i, tt := range tests { lookupSRV = func(service string, proto string, domain string) (string, []*net.SRV, error) { if service == "etcd-server-ssl" { return "", tt.withSSL, nil } if service == "etcd-server" { return "", tt.withoutSSL, nil } return "", nil, errors.New("Unkown service in mock") } urls := testutil.MustNewURLs(t, tt.urls) str, token, err := SRVGetCluster(name, "example.com", "token", urls) if err != nil { t.Fatalf("%d: err: %#v", i, err) } if token != "token" { t.Errorf("%d: token: %s", i, token) } if str != tt.expected { t.Errorf("#%d: cluster = %s, want %s", i, str, tt.expected) } } }