github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/utils/testing/choose_version_test.go (about) 1 package testing 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "strings" 8 "testing" 9 10 "github.com/vnpaycloud-console/gophercloud/v2" 11 "github.com/vnpaycloud-console/gophercloud/v2/openstack/utils" 12 th "github.com/vnpaycloud-console/gophercloud/v2/testhelper" 13 ) 14 15 func setupVersionHandler() { 16 th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 17 fmt.Fprintf(w, ` 18 { 19 "versions": { 20 "values": [ 21 { 22 "status": "stable", 23 "id": "v3.0", 24 "links": [ 25 { "href": "%s/v3.0", "rel": "self" } 26 ] 27 }, 28 { 29 "status": "stable", 30 "id": "v2.0", 31 "links": [ 32 { "href": "%s/v2.0", "rel": "self" } 33 ] 34 } 35 ] 36 } 37 } 38 `, th.Server.URL, th.Server.URL) 39 }) 40 // Compute v2.1 API 41 th.Mux.HandleFunc("/compute/v2.1/", func(w http.ResponseWriter, r *http.Request) { 42 fmt.Fprintf(w, ` 43 { 44 "version": { 45 "id": "v2.1", 46 "status": "CURRENT", 47 "version": "2.90", 48 "min_version": "2.1", 49 "updated": "2013-07-23T11:33:21Z", 50 "links": [ 51 { 52 "rel": "self", 53 "href": "%s/compute/v2.1/" 54 }, 55 { 56 "rel": "describedby", 57 "type": "text/html", 58 "href": "http://docs.openstack.org/" 59 } 60 ], 61 "media-types": [ 62 { 63 "base": "application/json", 64 "type": "application/vnd.openstack.compute+json;version=2.1" 65 } 66 ] 67 } 68 } 69 `, th.Server.URL) 70 }) 71 // Compute v2 API 72 th.Mux.HandleFunc("/compute/v2/", func(w http.ResponseWriter, r *http.Request) { 73 fmt.Fprintf(w, ` 74 { 75 "version": { 76 "id": "v2.0", 77 "status": "SUPPORTED", 78 "version": "", 79 "min_version": "", 80 "updated": "2011-01-21T11:33:21Z", 81 "links": [ 82 { 83 "rel": "self", 84 "href": "%s/compute/v2/" 85 }, 86 { 87 "rel": "describedby", 88 "type": "text/html", 89 "href": "http://docs.openstack.org/" 90 } 91 ], 92 "media-types": [ 93 { 94 "base": "application/json", 95 "type": "application/vnd.openstack.compute+json;version=2" 96 } 97 ] 98 } 99 } 100 `, th.Server.URL) 101 }) 102 // Ironic API 103 th.Mux.HandleFunc("/ironic/v1/", func(w http.ResponseWriter, r *http.Request) { 104 fmt.Fprintf(w, ` 105 { 106 "name": "OpenStack Ironic API", 107 "description": "Ironic is an OpenStack project which enables the provision and management of baremetal machines.", 108 "default_version": { 109 "id": "v1", 110 "links": [ 111 { 112 "href": "%s/ironic/v1/", 113 "rel": "self" 114 } 115 ], 116 "status": "CURRENT", 117 "min_version": "1.1", 118 "version": "1.87" 119 }, 120 "versions": [ 121 { 122 "id": "v1", 123 "links": [ 124 { 125 "href": "%s/ironic/v1/", 126 "rel": "self" 127 } 128 ], 129 "status": "CURRENT", 130 "min_version": "1.1", 131 "version": "1.87" 132 } 133 ] 134 } 135 `, th.Server.URL, th.Server.URL) 136 }) 137 // Ironic multi-version 138 th.Mux.HandleFunc("/ironic/v1.2/", func(w http.ResponseWriter, r *http.Request) { 139 fmt.Fprintf(w, ` 140 { 141 "name": "OpenStack Ironic API", 142 "description": "Ironic is an OpenStack project which enables the provision and management of baremetal machines.", 143 "default_version": { 144 "id": "v1", 145 "links": [ 146 { 147 "href": "%s/ironic/v1/", 148 "rel": "self" 149 } 150 ], 151 "status": "CURRENT", 152 "min_version": "1.1", 153 "version": "1.87" 154 }, 155 "versions": [ 156 { 157 "id": "v1", 158 "links": [ 159 { 160 "href": "%s/ironic/v1/", 161 "rel": "self" 162 } 163 ], 164 "status": "CURRENT", 165 "min_version": "1.1", 166 "version": "1.87" 167 }, 168 { 169 "id": "v1.2", 170 "links": [ 171 { 172 "href": "%s/ironic/v1/", 173 "rel": "self" 174 } 175 ], 176 "status": "CURRENT", 177 "min_version": "1.2", 178 "version": "1.90" 179 } 180 ] 181 } 182 `, th.Server.URL, th.Server.URL, th.Server.URL) 183 }) 184 } 185 186 func TestChooseVersion(t *testing.T) { 187 th.SetupHTTP() 188 defer th.TeardownHTTP() 189 setupVersionHandler() 190 191 v2 := &utils.Version{ID: "v2.0", Priority: 2, Suffix: "blarg"} 192 v3 := &utils.Version{ID: "v3.0", Priority: 3, Suffix: "hargl"} 193 194 c := &gophercloud.ProviderClient{ 195 IdentityBase: th.Endpoint(), 196 IdentityEndpoint: "", 197 } 198 v, endpoint, err := utils.ChooseVersion(context.TODO(), c, []*utils.Version{v2, v3}) 199 200 if err != nil { 201 t.Fatalf("Unexpected error from ChooseVersion: %v", err) 202 } 203 204 if v != v3 { 205 t.Errorf("Expected %#v to win, but %#v did instead", v3, v) 206 } 207 208 expected := th.Endpoint() + "v3.0/" 209 if endpoint != expected { 210 t.Errorf("Expected endpoint [%s], but was [%s] instead", expected, endpoint) 211 } 212 } 213 214 func TestChooseVersionOpinionatedLink(t *testing.T) { 215 th.SetupHTTP() 216 defer th.TeardownHTTP() 217 setupVersionHandler() 218 219 v2 := &utils.Version{ID: "v2.0", Priority: 2, Suffix: "nope"} 220 v3 := &utils.Version{ID: "v3.0", Priority: 3, Suffix: "northis"} 221 222 c := &gophercloud.ProviderClient{ 223 IdentityBase: th.Endpoint(), 224 IdentityEndpoint: th.Endpoint() + "v2.0/", 225 } 226 v, endpoint, err := utils.ChooseVersion(context.TODO(), c, []*utils.Version{v2, v3}) 227 if err != nil { 228 t.Fatalf("Unexpected error from ChooseVersion: %v", err) 229 } 230 231 if v != v2 { 232 t.Errorf("Expected %#v to win, but %#v did instead", v2, v) 233 } 234 235 expected := th.Endpoint() + "v2.0/" 236 if endpoint != expected { 237 t.Errorf("Expected endpoint [%s], but was [%s] instead", expected, endpoint) 238 } 239 } 240 241 func TestChooseVersionFromSuffix(t *testing.T) { 242 th.SetupHTTP() 243 defer th.TeardownHTTP() 244 245 v2 := &utils.Version{ID: "v2.0", Priority: 2, Suffix: "/v2.0/"} 246 v3 := &utils.Version{ID: "v3.0", Priority: 3, Suffix: "/v3.0/"} 247 248 c := &gophercloud.ProviderClient{ 249 IdentityBase: th.Endpoint(), 250 IdentityEndpoint: th.Endpoint() + "v2.0/", 251 } 252 v, endpoint, err := utils.ChooseVersion(context.TODO(), c, []*utils.Version{v2, v3}) 253 if err != nil { 254 t.Fatalf("Unexpected error from ChooseVersion: %v", err) 255 } 256 257 if v != v2 { 258 t.Errorf("Expected %#v to win, but %#v did instead", v2, v) 259 } 260 261 expected := th.Endpoint() + "v2.0/" 262 if endpoint != expected { 263 t.Errorf("Expected endpoint [%s], but was [%s] instead", expected, endpoint) 264 } 265 } 266 267 type getSupportedServiceMicroversions struct { 268 Endpoint string 269 ExpectedMax string 270 ExpectedMin string 271 ExpectedErr bool 272 } 273 274 func TestGetSupportedVersions(t *testing.T) { 275 th.SetupHTTP() 276 defer th.TeardownHTTP() 277 setupVersionHandler() 278 279 tests := []getSupportedServiceMicroversions{ 280 { 281 // v2 does not support microversions and returns error 282 Endpoint: th.Endpoint() + "compute/v2/", 283 ExpectedMax: "", 284 ExpectedMin: "", 285 ExpectedErr: true, 286 }, 287 { 288 Endpoint: th.Endpoint() + "compute/v2.1/", 289 ExpectedMax: "2.90", 290 ExpectedMin: "2.1", 291 ExpectedErr: false, 292 }, 293 { 294 Endpoint: th.Endpoint() + "ironic/v1/", 295 ExpectedMax: "1.87", 296 ExpectedMin: "1.1", 297 ExpectedErr: false, 298 }, 299 { 300 // This endpoint returns multiple versions, which is not supported 301 Endpoint: th.Endpoint() + "ironic/v1.2/", 302 ExpectedMax: "not-relevant", 303 ExpectedMin: "not-relevant", 304 ExpectedErr: true, 305 }, 306 } 307 308 for _, test := range tests { 309 c := &gophercloud.ProviderClient{ 310 IdentityBase: th.Endpoint(), 311 IdentityEndpoint: th.Endpoint() + "v2.0/", 312 } 313 314 client := &gophercloud.ServiceClient{ 315 ProviderClient: c, 316 Endpoint: test.Endpoint, 317 } 318 319 supported, err := utils.GetSupportedMicroversions(context.TODO(), client) 320 321 if test.ExpectedErr { 322 if err == nil { 323 t.Error("Expected error but got none!") 324 } 325 // Check for reasonable error message 326 if !strings.Contains(err.Error(), "not supported") { 327 t.Error("Expected error to contain 'not supported' but it did not!") 328 } 329 // No point parsing and comparing versions after error, so continue to next test case 330 continue 331 } else { 332 if err != nil { 333 t.Errorf("Expected no error but got %s", err.Error()) 334 } 335 } 336 337 min := fmt.Sprintf("%d.%d", supported.MinMajor, supported.MinMinor) 338 max := fmt.Sprintf("%d.%d", supported.MaxMajor, supported.MaxMinor) 339 340 if (min != test.ExpectedMin) || (max != test.ExpectedMax) { 341 t.Errorf("Expected min=%s and max=%s but got min=%s and max=%s", test.ExpectedMin, test.ExpectedMax, min, max) 342 } 343 } 344 } 345 346 type microversionSupported struct { 347 Version string 348 MinVersion string 349 MaxVersion string 350 Supported bool 351 Error bool 352 } 353 354 func TestMicroversionSupported(t *testing.T) { 355 tests := []microversionSupported{ 356 { 357 // Checking min version 358 Version: "2.1", 359 MinVersion: "2.1", 360 MaxVersion: "2.90", 361 Supported: true, 362 Error: false, 363 }, 364 { 365 // Checking max version 366 Version: "2.90", 367 MinVersion: "2.1", 368 MaxVersion: "2.90", 369 Supported: true, 370 Error: false, 371 }, 372 { 373 // Checking too high version 374 Version: "2.95", 375 MinVersion: "2.1", 376 MaxVersion: "2.90", 377 Supported: false, 378 Error: false, 379 }, 380 { 381 // Checking too low version 382 Version: "2.1", 383 MinVersion: "2.53", 384 MaxVersion: "2.90", 385 Supported: false, 386 Error: false, 387 }, 388 { 389 // Invalid version 390 Version: "2.1.53", 391 MinVersion: "2.53", 392 MaxVersion: "2.90", 393 Supported: false, 394 Error: true, 395 }, 396 } 397 398 for _, test := range tests { 399 var err error 400 var supportedVersions utils.SupportedMicroversions 401 supportedVersions.MaxMajor, supportedVersions.MaxMinor, err = utils.ParseMicroversion(test.MaxVersion) 402 if err != nil { 403 t.Error("Error parsing MaxVersion!") 404 } 405 supportedVersions.MinMajor, supportedVersions.MinMinor, err = utils.ParseMicroversion(test.MinVersion) 406 if err != nil { 407 t.Error("Error parsing MinVersion!") 408 } 409 410 supported, err := supportedVersions.IsSupported(test.Version) 411 if test.Error { 412 if err == nil { 413 t.Error("Expected error but got none!") 414 } 415 } else { 416 if err != nil { 417 t.Errorf("Expected no error but got %s", err.Error()) 418 } 419 } 420 if test.Supported != supported { 421 t.Errorf("Expected supported=%t to be %t, when version=%s, min=%s and max=%s", 422 supported, test.Supported, test.Version, test.MinVersion, test.MaxVersion) 423 } 424 } 425 }