1/* 2 * 3 * Copyright 2017 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19package grpc 20 21import ( 22 "fmt" 23 "net" 24 "testing" 25 "time" 26 27 "google.golang.org/grpc/resolver" 28) 29 30func (s) TestParseTarget(t *testing.T) { 31 for _, test := range []resolver.Target{ 32 {Scheme: "dns", Authority: "", Endpoint: "google.com"}, 33 {Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com"}, 34 {Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com/?a=b"}, 35 {Scheme: "passthrough", Authority: "", Endpoint: "/unix/socket/address"}, 36 } { 37 str := test.Scheme + "://" + test.Authority + "/" + test.Endpoint 38 got := parseTarget(str) 39 if got != test { 40 t.Errorf("parseTarget(%q) = %+v, want %+v", str, got, test) 41 } 42 } 43} 44 45func (s) TestParseTargetString(t *testing.T) { 46 for _, test := range []struct { 47 targetStr string 48 want resolver.Target 49 }{ 50 {targetStr: "", want: resolver.Target{Scheme: "", Authority: "", Endpoint: ""}}, 51 {targetStr: ":///", want: resolver.Target{Scheme: "", Authority: "", Endpoint: ""}}, 52 {targetStr: "a:///", want: resolver.Target{Scheme: "a", Authority: "", Endpoint: ""}}, 53 {targetStr: "://a/", want: resolver.Target{Scheme: "", Authority: "a", Endpoint: ""}}, 54 {targetStr: ":///a", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a"}}, 55 {targetStr: "a://b/", want: resolver.Target{Scheme: "a", Authority: "b", Endpoint: ""}}, 56 {targetStr: "a:///b", want: resolver.Target{Scheme: "a", Authority: "", Endpoint: "b"}}, 57 {targetStr: "://a/b", want: resolver.Target{Scheme: "", Authority: "a", Endpoint: "b"}}, 58 {targetStr: "a://b/c", want: resolver.Target{Scheme: "a", Authority: "b", Endpoint: "c"}}, 59 {targetStr: "dns:///google.com", want: resolver.Target{Scheme: "dns", Authority: "", Endpoint: "google.com"}}, 60 {targetStr: "dns://a.server.com/google.com", want: resolver.Target{Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com"}}, 61 {targetStr: "dns://a.server.com/google.com/?a=b", want: resolver.Target{Scheme: "dns", Authority: "a.server.com", Endpoint: "google.com/?a=b"}}, 62 63 {targetStr: "/", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "/"}}, 64 {targetStr: "google.com", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "google.com"}}, 65 {targetStr: "google.com/?a=b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "google.com/?a=b"}}, 66 {targetStr: "/unix/socket/address", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "/unix/socket/address"}}, 67 68 // If we can only parse part of the target. 69 {targetStr: "://", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "://"}}, 70 {targetStr: "unix://domain", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "unix://domain"}}, 71 {targetStr: "a:b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a:b"}}, 72 {targetStr: "a/b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a/b"}}, 73 {targetStr: "a:/b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a:/b"}}, 74 {targetStr: "a//b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a//b"}}, 75 {targetStr: "a://b", want: resolver.Target{Scheme: "", Authority: "", Endpoint: "a://b"}}, 76 } { 77 got := parseTarget(test.targetStr) 78 if got != test.want { 79 t.Errorf("parseTarget(%q) = %+v, want %+v", test.targetStr, got, test.want) 80 } 81 } 82} 83 84// The target string with unknown scheme should be kept unchanged and passed to 85// the dialer. 86func (s) TestDialParseTargetUnknownScheme(t *testing.T) { 87 for _, test := range []struct { 88 targetStr string 89 want string 90 }{ 91 {"/unix/socket/address", "/unix/socket/address"}, 92 93 // Special test for "unix:///". 94 {"unix:///unix/socket/address", "unix:///unix/socket/address"}, 95 96 // For known scheme. 97 {"passthrough://a.server.com/google.com", "google.com"}, 98 } { 99 dialStrCh := make(chan string, 1) 100 cc, err := Dial(test.targetStr, WithInsecure(), WithDialer(func(addr string, _ time.Duration) (net.Conn, error) { 101 select { 102 case dialStrCh <- addr: 103 default: 104 } 105 return nil, fmt.Errorf("test dialer, always error") 106 })) 107 if err != nil { 108 t.Fatalf("Failed to create ClientConn: %v", err) 109 } 110 got := <-dialStrCh 111 cc.Close() 112 if got != test.want { 113 t.Errorf("Dial(%q), dialer got %q, want %q", test.targetStr, got, test.want) 114 } 115 } 116} 117