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