github.com/vmware/govmomi@v0.43.0/vim25/soap/client_test.go (about) 1 /* 2 Copyright (c) 2015 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package soap 18 19 import ( 20 "context" 21 "fmt" 22 "net/http" 23 "net/url" 24 "os" 25 "reflect" 26 "testing" 27 ) 28 29 type mockRT struct{} 30 31 func (m mockRT) RoundTrip(req *http.Request) (*http.Response, error) { 32 var res http.Response 33 res.Header = req.Header.Clone() 34 return &res, nil 35 } 36 37 func TestUserAgent(t *testing.T) { 38 tests := []struct { 39 name string 40 agent string 41 }{ 42 {name: "default agent", agent: ""}, 43 {name: "custom agent", agent: "govmomi-test/0.0.0"}, 44 } 45 46 const rawURL = "https://vcenter.local" 47 u, err := url.Parse(rawURL) 48 if err != nil { 49 t.Fatalf("parse url: %v", err) 50 } 51 52 for _, test := range tests { 53 t.Run(test.name, func(t *testing.T) { 54 c := NewClient(u, false) 55 c.Transport = &mockRT{} 56 57 req, err := http.NewRequest(http.MethodPost, rawURL, nil) 58 if err != nil { 59 t.Fatalf("create request: %v", err) 60 } 61 62 if test.agent != "" { 63 c.UserAgent = test.agent 64 } 65 66 if err = c.Do(context.Background(), req, func(response *http.Response) error { 67 got := response.Header.Get("user-agent") 68 want := func() string { 69 if test.agent == "" { 70 return defaultUserAgent 71 } 72 return test.agent 73 } 74 75 if got != want() { 76 return fmt.Errorf("user-agent header mismatch: got=%s want=%s", got, want()) 77 } 78 return nil 79 }); err != nil { 80 t.Errorf("user-agent header validation failed: %v", err) 81 } 82 }) 83 } 84 } 85 86 func TestSplitHostPort(t *testing.T) { 87 tests := []struct { 88 url string 89 host string 90 port string 91 }{ 92 {"127.0.0.1", "127.0.0.1", ""}, 93 {"*:1234", "*", "1234"}, 94 {"127.0.0.1:80", "127.0.0.1", "80"}, 95 {"[::1]:6767", "[::1]", "6767"}, 96 {"[::1]", "[::1]", ""}, 97 } 98 99 for _, test := range tests { 100 host, port := splitHostPort(test.url) 101 if host != test.host { 102 t.Errorf("(%s) %s != %s", test.url, host, test.host) 103 } 104 if port != test.port { 105 t.Errorf("(%s) %s != %s", test.url, port, test.port) 106 } 107 } 108 } 109 110 func TestMultipleCAPaths(t *testing.T) { 111 err := setCAsOnClient("fixtures/invalid-cert.pem:fixtures/valid-cert.pem") 112 113 certErr, ok := err.(errInvalidCACertificate) 114 if !ok { 115 t.Fatalf("Expected errInvalidCACertificate to occur") 116 } 117 if certErr.File != "fixtures/invalid-cert.pem" { 118 t.Fatalf("Expected Err to show invalid file") 119 } 120 } 121 122 func TestInvalidRootCAPath(t *testing.T) { 123 err := setCAsOnClient("fixtures/there-is-no-such-file") 124 125 if _, ok := err.(*os.PathError); !ok { 126 t.Fatalf("os.PathError should have occurred: %#v", err) 127 } 128 } 129 130 func TestValidRootCAs(t *testing.T) { 131 err := setCAsOnClient("fixtures/valid-cert.pem") 132 if err != nil { 133 t.Fatalf("Err should not have occurred: %#v", err) 134 } 135 } 136 137 func TestInvalidRootCAs(t *testing.T) { 138 err := setCAsOnClient("fixtures/invalid-cert.pem") 139 140 certErr, ok := err.(errInvalidCACertificate) 141 if !ok { 142 t.Fatalf("Expected errInvalidCACertificate to occur") 143 } 144 if certErr.File != "fixtures/invalid-cert.pem" { 145 t.Fatalf("Expected Err to show invalid file") 146 } 147 } 148 149 func setCAsOnClient(cas string) error { 150 url := &url.URL{ 151 Scheme: "https", 152 Host: "some.host.tld:8080", 153 } 154 insecure := false 155 156 client := NewClient(url, insecure) 157 158 return client.SetRootCAs(cas) 159 } 160 161 func TestParseURL(t *testing.T) { 162 tests := []struct { 163 name string 164 s string 165 want *url.URL 166 wantErr bool 167 }{ 168 { 169 name: "empty URL should return null", 170 want: nil, 171 }, 172 { 173 name: "just endpoint should return full URL", 174 s: "some.vcenter.tld", 175 want: &url.URL{ 176 Scheme: "https", 177 Path: "/sdk", 178 Host: "some.vcenter.tld", 179 User: url.UserPassword("", ""), 180 }, 181 }, 182 { 183 name: "URL with / on suffix should be trimmed", 184 s: "https://some.vcenter.tld/", 185 want: &url.URL{ 186 Scheme: "https", 187 Path: "/sdk", 188 Host: "some.vcenter.tld", 189 User: url.UserPassword("", ""), 190 }, 191 }, 192 { 193 name: "URL with user and password should be used", 194 s: "https://user:password@some.vcenter.tld", 195 want: &url.URL{ 196 Scheme: "https", 197 Path: "/sdk", 198 Host: "some.vcenter.tld", 199 User: url.UserPassword("user", "password"), 200 }, 201 }, 202 { 203 name: "existing path should be used", 204 s: "https://some.vcenter.tld/othersdk", 205 want: &url.URL{ 206 Scheme: "https", 207 Path: "/othersdk", 208 Host: "some.vcenter.tld", 209 User: url.UserPassword("", ""), 210 }, 211 }, 212 { 213 name: "Invalid URL should be rejected", 214 s: "https://user:password@some.vcenter.tld:xpto1234", 215 want: nil, 216 wantErr: true, 217 }, 218 } 219 for _, tt := range tests { 220 t.Run(tt.name, func(t *testing.T) { 221 got, err := ParseURL(tt.s) 222 if (err != nil) != tt.wantErr { 223 t.Errorf("ParseURL() error = %v, wantErr %v", err, tt.wantErr) 224 return 225 } 226 if !reflect.DeepEqual(got, tt.want) { 227 t.Errorf("ParseURL() = %v, want %v", got, tt.want) 228 } 229 }) 230 } 231 }