github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/service/rest_version_test.go (about) 1 package service 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "math/rand" 8 "net/http" 9 "net/http/httptest" 10 "path/filepath" 11 "testing" 12 "time" 13 14 "github.com/codegangsta/negroni" 15 "github.com/evergreen-ci/evergreen" 16 "github.com/evergreen-ci/evergreen/auth" 17 "github.com/evergreen-ci/evergreen/db" 18 "github.com/evergreen-ci/evergreen/model/build" 19 modelutil "github.com/evergreen-ci/evergreen/model/testutil" 20 "github.com/evergreen-ci/evergreen/model/version" 21 serviceutil "github.com/evergreen-ci/evergreen/service/testutil" 22 "github.com/evergreen-ci/evergreen/testutil" 23 "github.com/evergreen-ci/render" 24 . "github.com/smartystreets/goconvey/convey" 25 ) 26 27 var versionTestConfig = testutil.TestConfig() 28 29 func init() { 30 db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(versionTestConfig)) 31 } 32 33 func TestGetRecentVersions(t *testing.T) { 34 35 userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig) 36 testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") 37 38 uis := UIServer{ 39 RootURL: versionTestConfig.Ui.Url, 40 Settings: *versionTestConfig, 41 UserManager: userManager, 42 } 43 44 home := evergreen.FindEvergreenHome() 45 46 uis.Render = render.New(render.Options{ 47 Directory: filepath.Join(home, WebRootPath, Templates), 48 DisableCache: true, 49 }) 50 testutil.HandleTestingErr(uis.InitPlugins(), t, "problem loading plugins") 51 52 router, err := uis.NewRouter() 53 testutil.HandleTestingErr(err, t, "Failed to create ui server router") 54 55 err = modelutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "") 56 testutil.HandleTestingErr(err, t, "Error loading local config mci-test") 57 58 err = modelutil.CreateTestLocalConfig(buildTestConfig, "render", "") 59 testutil.HandleTestingErr(err, t, "Error loading local config render") 60 61 Convey("When finding recent versions", t, func() { 62 testutil.HandleTestingErr(db.ClearCollections(version.Collection, build.Collection), t, 63 "Error clearing '%v' collection", version.Collection) 64 65 projectName := "project_test" 66 67 err = modelutil.CreateTestLocalConfig(buildTestConfig, projectName, "") 68 So(err, ShouldBeNil) 69 otherProjectName := "my-other-project" 70 So(projectName, ShouldNotEqual, otherProjectName) // sanity-check 71 72 buildIdPreface := "build-id-for-version%v" 73 74 So(NumRecentVersions, ShouldBeGreaterThan, 0) 75 versions := make([]*version.Version, 0, NumRecentVersions) 76 77 // Insert a bunch of versions into the database 78 for i := 0; i < NumRecentVersions; i++ { 79 v := &version.Version{ 80 Id: fmt.Sprintf("version%v", i), 81 Identifier: projectName, 82 Author: fmt.Sprintf("author%v", i), 83 Revision: fmt.Sprintf("%x", rand.Int()), 84 Message: fmt.Sprintf("message%v", i), 85 RevisionOrderNumber: i + 1, 86 Requester: evergreen.RepotrackerVersionRequester, 87 } 88 So(v.Insert(), ShouldBeNil) 89 versions = append(versions, v) 90 } 91 92 // Construct a version that should not be present in the response 93 // since the length of the build ids slice is different than that 94 // of the build variants slice 95 earlyVersion := &version.Version{ 96 Id: "some-id", 97 Identifier: projectName, 98 Author: "some-author", 99 Revision: fmt.Sprintf("%x", rand.Int()), 100 Message: "some-message", 101 RevisionOrderNumber: 0, 102 Requester: evergreen.RepotrackerVersionRequester, 103 } 104 So(earlyVersion.Insert(), ShouldBeNil) 105 106 // Construct a version that should not be present in the response 107 // since it belongs to a different project 108 otherVersion := &version.Version{ 109 Id: "some-other-id", 110 Identifier: otherProjectName, 111 Author: "some-other-author", 112 Revision: fmt.Sprintf("%x", rand.Int()), 113 Message: "some-other-message", 114 RevisionOrderNumber: NumRecentVersions + 1, 115 Requester: evergreen.RepotrackerVersionRequester, 116 } 117 So(otherVersion.Insert(), ShouldBeNil) 118 119 builds := make([]*build.Build, 0, NumRecentVersions) 120 task := build.TaskCache{ 121 Id: "some-task-id", 122 DisplayName: "some-task-name", 123 Status: "success", 124 TimeTaken: time.Duration(100 * time.Millisecond), 125 } 126 127 for i := 0; i < NumRecentVersions; i++ { 128 build := &build.Build{ 129 Id: fmt.Sprintf(buildIdPreface, i), 130 Version: versions[i].Id, 131 BuildVariant: "some-build-variant", 132 DisplayName: "Some Build Variant", 133 Tasks: []build.TaskCache{task}, 134 } 135 So(build.Insert(), ShouldBeNil) 136 builds = append(builds, build) 137 } 138 139 url, err := router.Get("recent_versions").URL("project_id", projectName) 140 So(err, ShouldBeNil) 141 142 request, err := http.NewRequest("GET", url.String(), nil) 143 So(err, ShouldBeNil) 144 145 response := httptest.NewRecorder() 146 // Need match variables to be set so can call mux.Vars(request) 147 // in the actual handler function 148 router.ServeHTTP(response, request) 149 150 So(response.Code, ShouldEqual, http.StatusOK) 151 152 Convey("response should match contents of database", func() { 153 var jsonBody map[string]interface{} 154 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 155 So(err, ShouldBeNil) 156 157 var rawJsonBody map[string]*json.RawMessage 158 err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody) 159 So(err, ShouldBeNil) 160 161 So(jsonBody["project"], ShouldEqual, projectName) 162 163 var jsonVersions []map[string]interface{} 164 err = json.Unmarshal(*rawJsonBody["versions"], &jsonVersions) 165 So(err, ShouldBeNil) 166 So(len(jsonVersions), ShouldEqual, len(versions)) 167 168 for i, v := range versions { 169 jsonVersion := jsonVersions[len(jsonVersions)-i-1] // reverse order 170 171 So(jsonVersion["version_id"], ShouldEqual, v.Id) 172 So(jsonVersion["author"], ShouldEqual, v.Author) 173 So(jsonVersion["revision"], ShouldEqual, v.Revision) 174 So(jsonVersion["message"], ShouldEqual, v.Message) 175 176 _jsonBuilds, ok := jsonVersion["builds"] 177 So(ok, ShouldBeTrue) 178 jsonBuilds, ok := _jsonBuilds.(map[string]interface{}) 179 So(ok, ShouldBeTrue) 180 So(len(jsonBuilds), ShouldEqual, 1) 181 182 _jsonBuild, ok := jsonBuilds[builds[i].BuildVariant] 183 So(ok, ShouldBeTrue) 184 jsonBuild, ok := _jsonBuild.(map[string]interface{}) 185 So(ok, ShouldBeTrue) 186 187 So(jsonBuild["build_id"], ShouldEqual, builds[i].Id) 188 So(jsonBuild["name"], ShouldEqual, builds[i].DisplayName) 189 190 _jsonTasks, ok := jsonBuild["tasks"] 191 So(ok, ShouldBeTrue) 192 jsonTasks, ok := _jsonTasks.(map[string]interface{}) 193 So(ok, ShouldBeTrue) 194 So(len(jsonTasks), ShouldEqual, 1) 195 196 _jsonTask, ok := jsonTasks[task.DisplayName] 197 So(ok, ShouldBeTrue) 198 jsonTask, ok := _jsonTask.(map[string]interface{}) 199 So(ok, ShouldBeTrue) 200 201 So(jsonTask["task_id"], ShouldEqual, task.Id) 202 So(jsonTask["status"], ShouldEqual, task.Status) 203 So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken) 204 } 205 }) 206 }) 207 208 Convey("When finding recent versions for a nonexistent project", t, func() { 209 projectName := "not-present" 210 211 url, err := router.Get("recent_versions").URL("project_id", projectName) 212 So(err, ShouldBeNil) 213 214 request, err := http.NewRequest("GET", url.String(), nil) 215 So(err, ShouldBeNil) 216 217 response := httptest.NewRecorder() 218 // Need match variables to be set so can call mux.Vars(request) 219 // in the actual handler function 220 router.ServeHTTP(response, request) 221 222 So(response.Code, ShouldEqual, http.StatusOK) 223 224 Convey("response should contain no versions", func() { 225 var jsonBody map[string]interface{} 226 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 227 So(err, ShouldBeNil) 228 229 var rawJsonBody map[string]*json.RawMessage 230 err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody) 231 So(err, ShouldBeNil) 232 233 So(jsonBody["project"], ShouldEqual, projectName) 234 235 var jsonVersions []map[string]interface{} 236 err = json.Unmarshal(*rawJsonBody["versions"], &jsonVersions) 237 So(err, ShouldBeNil) 238 So(jsonVersions, ShouldBeEmpty) 239 }) 240 }) 241 } 242 243 func TestGetVersionInfo(t *testing.T) { 244 245 uis := UIServer{ 246 RootURL: versionTestConfig.Ui.Url, 247 Settings: *versionTestConfig, 248 UserManager: serviceutil.MockUserManager{}, 249 } 250 home := evergreen.FindEvergreenHome() 251 252 uis.Render = render.New(render.Options{ 253 Directory: filepath.Join(home, WebRootPath, Templates), 254 DisableCache: true, 255 }) 256 testutil.HandleTestingErr(uis.InitPlugins(), t, "problem loading plugins") 257 258 router, err := uis.NewRouter() 259 testutil.HandleTestingErr(err, t, "Failed to create ui server router") 260 261 err = modelutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "") 262 testutil.HandleTestingErr(err, t, "Error loading local config mci-test") 263 264 err = modelutil.CreateTestLocalConfig(buildTestConfig, "render", "") 265 testutil.HandleTestingErr(err, t, "Error loading local config render") 266 267 Convey("When finding info on a particular version", t, func() { 268 testutil.HandleTestingErr(db.Clear(version.Collection), t, 269 "Error clearing '%v' collection", version.Collection) 270 271 versionId := "my-version" 272 projectName := "project_test" 273 274 err = modelutil.CreateTestLocalConfig(buildTestConfig, projectName, "") 275 So(err, ShouldBeNil) 276 277 v := &version.Version{ 278 Id: versionId, 279 CreateTime: time.Now().Add(-20 * time.Minute), 280 StartTime: time.Now().Add(-10 * time.Minute), 281 FinishTime: time.Now().Add(-5 * time.Second), 282 Revision: fmt.Sprintf("%x", rand.Int()), 283 Author: "some-author", 284 AuthorEmail: "some-email", 285 Message: "some-message", 286 Status: "success", 287 BuildIds: []string{"some-build-id"}, 288 BuildVariants: []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}}, 289 RevisionOrderNumber: rand.Int(), 290 Owner: "some-owner", 291 Repo: "some-repo", 292 Branch: "some-branch", 293 RepoKind: "github", 294 Identifier: versionId, 295 Remote: false, 296 RemotePath: "", 297 Requester: evergreen.RepotrackerVersionRequester, 298 } 299 So(v.Insert(), ShouldBeNil) 300 301 url, err := router.Get("version_info").URL("version_id", versionId) 302 So(err, ShouldBeNil) 303 304 request, err := http.NewRequest("GET", url.String(), nil) 305 So(err, ShouldBeNil) 306 307 response := httptest.NewRecorder() 308 // Need match variables to be set so can call mux.Vars(request) 309 // in the actual handler function 310 router.ServeHTTP(response, request) 311 312 fmt.Println(response.Body) 313 314 So(response.Code, ShouldEqual, http.StatusOK) 315 validateVersionInfo(v, response) 316 }) 317 318 Convey("When finding info on a nonexistent version", t, func() { 319 versionId := "not-present" 320 321 url, err := router.Get("version_info").URL("version_id", versionId) 322 So(err, ShouldBeNil) 323 324 request, err := http.NewRequest("GET", url.String(), nil) 325 So(err, ShouldBeNil) 326 327 response := httptest.NewRecorder() 328 // Need match variables to be set so can call mux.Vars(request) 329 // in the actual handler function 330 router.ServeHTTP(response, request) 331 332 So(response.Code, ShouldEqual, http.StatusNotFound) 333 334 Convey("response should contain a sensible error message", func() { 335 var jsonBody map[string]interface{} 336 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 337 So(err, ShouldBeNil) 338 So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0) 339 }) 340 }) 341 } 342 343 func TestGetVersionInfoViaRevision(t *testing.T) { 344 345 userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig) 346 testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") 347 348 uis := UIServer{ 349 RootURL: versionTestConfig.Ui.Url, 350 Settings: *versionTestConfig, 351 UserManager: userManager, 352 } 353 354 home := evergreen.FindEvergreenHome() 355 356 uis.Render = render.New(render.Options{ 357 Directory: filepath.Join(home, WebRootPath, Templates), 358 DisableCache: true, 359 }) 360 testutil.HandleTestingErr(uis.InitPlugins(), t, "problem loading plugins") 361 362 router, err := uis.NewRouter() 363 testutil.HandleTestingErr(err, t, "Failed to create ui server router") 364 365 projectName := "project_test" 366 367 Convey("When finding info on a particular version by its revision", t, func() { 368 testutil.HandleTestingErr(db.Clear(version.Collection), t, 369 "Error clearing '%v' collection", version.Collection) 370 371 versionId := "my-version" 372 revision := fmt.Sprintf("%x", rand.Int()) 373 374 v := &version.Version{ 375 Id: versionId, 376 CreateTime: time.Now().Add(-20 * time.Minute), 377 StartTime: time.Now().Add(-10 * time.Minute), 378 FinishTime: time.Now().Add(-5 * time.Second), 379 Revision: revision, 380 Author: "some-author", 381 AuthorEmail: "some-email", 382 Message: "some-message", 383 Status: "success", 384 BuildIds: []string{"some-build-id"}, 385 BuildVariants: []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}}, 386 RevisionOrderNumber: rand.Int(), 387 Owner: "some-owner", 388 Repo: "some-repo", 389 Branch: "some-branch", 390 RepoKind: "github", 391 Identifier: projectName, 392 Remote: false, 393 RemotePath: "", 394 Requester: evergreen.RepotrackerVersionRequester, 395 } 396 So(v.Insert(), ShouldBeNil) 397 398 url, err := router.Get("version_info_via_revision").URL( 399 "project_id", projectName, "revision", revision) 400 So(err, ShouldBeNil) 401 402 request, err := http.NewRequest("GET", url.String(), nil) 403 So(err, ShouldBeNil) 404 405 response := httptest.NewRecorder() 406 // Need match variables to be set so can call mux.Vars(request) 407 // in the actual handler function 408 router.ServeHTTP(response, request) 409 410 So(response.Code, ShouldEqual, http.StatusOK) 411 validateVersionInfo(v, response) 412 }) 413 414 Convey("When finding info on a nonexistent version by its revision", t, func() { 415 revision := "not-present" 416 417 url, err := router.Get("version_info_via_revision").URL( 418 "project_id", projectName, "revision", revision) 419 So(err, ShouldBeNil) 420 421 request, err := http.NewRequest("GET", url.String(), nil) 422 So(err, ShouldBeNil) 423 424 response := httptest.NewRecorder() 425 // Need match variables to be set so can call mux.Vars(request) 426 // in the actual handler function 427 router.ServeHTTP(response, request) 428 429 So(response.Code, ShouldEqual, http.StatusNotFound) 430 431 Convey("response should contain a sensible error message", func() { 432 var jsonBody map[string]interface{} 433 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 434 So(err, ShouldBeNil) 435 So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0) 436 }) 437 }) 438 } 439 440 func TestActivateVersion(t *testing.T) { 441 442 uis := UIServer{ 443 RootURL: versionTestConfig.Ui.Url, 444 Settings: *versionTestConfig, 445 UserManager: serviceutil.MockUserManager{}, 446 } 447 448 home := evergreen.FindEvergreenHome() 449 450 uis.Render = render.New(render.Options{ 451 Directory: filepath.Join(home, WebRootPath, Templates), 452 DisableCache: true, 453 }) 454 testutil.HandleTestingErr(uis.InitPlugins(), t, "problem loading plugins") 455 456 router, err := uis.NewRouter() 457 testutil.HandleTestingErr(err, t, "Failed to create ui server router") 458 459 n := negroni.New() 460 n.Use(negroni.HandlerFunc(UserMiddleware(uis.UserManager))) 461 n.UseHandler(router) 462 463 Convey("When marking a particular version as active", t, func() { 464 testutil.HandleTestingErr(db.ClearCollections(version.Collection, build.Collection), t, 465 "Error clearing collections") 466 467 versionId := "my-version" 468 projectName := "project_test" 469 470 build := &build.Build{ 471 Id: "some-build-id", 472 BuildVariant: "some-build-variant", 473 } 474 So(build.Insert(), ShouldBeNil) 475 476 v := &version.Version{ 477 Id: versionId, 478 CreateTime: time.Now().Add(-20 * time.Minute), 479 StartTime: time.Now().Add(-10 * time.Minute), 480 FinishTime: time.Now().Add(-5 * time.Second), 481 Revision: fmt.Sprintf("%x", rand.Int()), 482 Author: "some-author", 483 AuthorEmail: "some-email", 484 Message: "some-message", 485 Status: "success", 486 BuildIds: []string{build.Id}, 487 BuildVariants: []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}}, 488 RevisionOrderNumber: rand.Int(), 489 Owner: "some-owner", 490 Repo: "some-repo", 491 Branch: "some-branch", 492 RepoKind: "github", 493 Identifier: projectName, 494 Remote: false, 495 RemotePath: "", 496 Requester: evergreen.RepotrackerVersionRequester, 497 } 498 So(v.Insert(), ShouldBeNil) 499 500 url, err := router.Get("version_info").URL("version_id", versionId) 501 So(err, ShouldBeNil) 502 503 var body = map[string]interface{}{ 504 "activated": true, 505 } 506 jsonBytes, err := json.Marshal(body) 507 So(err, ShouldBeNil) 508 bodyReader := bytes.NewReader(jsonBytes) 509 510 request, err := http.NewRequest("PATCH", url.String(), bodyReader) 511 So(err, ShouldBeNil) 512 // add auth cookie--this can be anything if we are using a MockUserManager 513 request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"}) 514 515 response := httptest.NewRecorder() 516 // Need match variables to be set so can call mux.Vars(request) 517 // in the actual handler function 518 n.ServeHTTP(response, request) 519 520 So(response.Code, ShouldEqual, http.StatusOK) 521 522 validateVersionInfo(v, response) 523 }) 524 525 Convey("When marking a nonexistent version as active", t, func() { 526 versionId := "not-present" 527 528 url, err := router.Get("version_info").URL("version_id", versionId) 529 So(err, ShouldBeNil) 530 531 var body = map[string]interface{}{ 532 "activated": true, 533 } 534 jsonBytes, err := json.Marshal(body) 535 So(err, ShouldBeNil) 536 bodyReader := bytes.NewReader(jsonBytes) 537 538 request, err := http.NewRequest("PATCH", url.String(), bodyReader) 539 So(err, ShouldBeNil) 540 541 response := httptest.NewRecorder() 542 // add auth cookie--this can be anything if we are using a MockUserManager 543 request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"}) 544 n.ServeHTTP(response, request) 545 546 So(response.Code, ShouldEqual, http.StatusNotFound) 547 548 Convey("response should contain a sensible error message", func() { 549 var jsonBody map[string]interface{} 550 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 551 So(err, ShouldBeNil) 552 So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0) 553 }) 554 }) 555 556 Convey("When modifying a version without credentials", t, func() { 557 versionId := "not-present" 558 559 url, err := router.Get("version_info").URL("version_id", versionId) 560 So(err, ShouldBeNil) 561 562 var body = map[string]interface{}{ 563 "activated": true, 564 } 565 jsonBytes, err := json.Marshal(body) 566 So(err, ShouldBeNil) 567 bodyReader := bytes.NewReader(jsonBytes) 568 569 request, err := http.NewRequest("PATCH", url.String(), bodyReader) 570 So(err, ShouldBeNil) 571 572 response := httptest.NewRecorder() 573 n.ServeHTTP(response, request) 574 575 Convey("response should indicate a permission error", func() { 576 So(response.Code, ShouldEqual, http.StatusUnauthorized) 577 }) 578 }) 579 } 580 581 func TestGetVersionStatus(t *testing.T) { 582 583 userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig) 584 testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") 585 586 uis := UIServer{ 587 RootURL: versionTestConfig.Ui.Url, 588 Settings: *versionTestConfig, 589 UserManager: userManager, 590 } 591 592 home := evergreen.FindEvergreenHome() 593 594 uis.Render = render.New(render.Options{ 595 Directory: filepath.Join(home, WebRootPath, Templates), 596 DisableCache: true, 597 }) 598 testutil.HandleTestingErr(uis.InitPlugins(), t, "problem loading plugins") 599 600 router, err := uis.NewRouter() 601 testutil.HandleTestingErr(err, t, "Failed to create ui server router") 602 603 Convey("When finding the status of a particular version", t, func() { 604 testutil.HandleTestingErr(db.Clear(build.Collection), t, 605 "Error clearing '%v' collection", build.Collection) 606 607 versionId := "my-version" 608 609 task := build.TaskCache{ 610 Id: "some-task-id", 611 DisplayName: "some-task-name", 612 Status: "success", 613 TimeTaken: time.Duration(100 * time.Millisecond), 614 } 615 build := &build.Build{ 616 Id: "some-build-id", 617 Version: versionId, 618 BuildVariant: "some-build-variant", 619 DisplayName: "Some Build Variant", 620 Tasks: []build.TaskCache{task}, 621 } 622 So(build.Insert(), ShouldBeNil) 623 624 Convey("grouped by tasks", func() { 625 groupBy := "tasks" 626 627 url, err := router.Get("version_status").URL("version_id", versionId) 628 So(err, ShouldBeNil) 629 630 query := url.Query() 631 query.Set("groupby", groupBy) 632 url.RawQuery = query.Encode() 633 634 request, err := http.NewRequest("GET", url.String(), nil) 635 So(err, ShouldBeNil) 636 637 response := httptest.NewRecorder() 638 // Need match variables to be set so can call mux.Vars(request) 639 // in the actual handler function 640 router.ServeHTTP(response, request) 641 642 So(response.Code, ShouldEqual, http.StatusOK) 643 644 Convey("response should match contents of database", func() { 645 var jsonBody map[string]interface{} 646 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 647 So(err, ShouldBeNil) 648 649 So(jsonBody["version_id"], ShouldEqual, versionId) 650 651 _jsonTasks, ok := jsonBody["tasks"] 652 So(ok, ShouldBeTrue) 653 jsonTasks, ok := _jsonTasks.(map[string]interface{}) 654 So(ok, ShouldBeTrue) 655 So(len(jsonTasks), ShouldEqual, 1) 656 657 _jsonTask, ok := jsonTasks[task.DisplayName] 658 So(ok, ShouldBeTrue) 659 jsonTask, ok := _jsonTask.(map[string]interface{}) 660 So(ok, ShouldBeTrue) 661 662 _jsonBuild, ok := jsonTask[build.BuildVariant] 663 So(ok, ShouldBeTrue) 664 jsonBuild, ok := _jsonBuild.(map[string]interface{}) 665 So(ok, ShouldBeTrue) 666 667 So(jsonBuild["task_id"], ShouldEqual, task.Id) 668 So(jsonBuild["status"], ShouldEqual, task.Status) 669 So(jsonBuild["time_taken"], ShouldEqual, task.TimeTaken) 670 }) 671 672 Convey("is the default option", func() { 673 url, err := router.Get("version_status").URL("version_id", versionId) 674 So(err, ShouldBeNil) 675 676 request, err := http.NewRequest("GET", url.String(), nil) 677 So(err, ShouldBeNil) 678 679 _response := httptest.NewRecorder() 680 // Need match variables to be set so can call mux.Vars(request) 681 // in the actual handler function 682 router.ServeHTTP(_response, request) 683 684 So(_response, ShouldResemble, response) 685 }) 686 }) 687 688 Convey("grouped by builds", func() { 689 groupBy := "builds" 690 691 url, err := router.Get("version_status").URL("version_id", versionId) 692 So(err, ShouldBeNil) 693 694 query := url.Query() 695 query.Set("groupby", groupBy) 696 url.RawQuery = query.Encode() 697 698 request, err := http.NewRequest("GET", url.String(), nil) 699 So(err, ShouldBeNil) 700 701 response := httptest.NewRecorder() 702 // Need match variables to be set so can call mux.Vars(request) 703 // in the actual handler function 704 router.ServeHTTP(response, request) 705 706 So(response.Code, ShouldEqual, http.StatusOK) 707 708 Convey("response should match contents of database", func() { 709 var jsonBody map[string]interface{} 710 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 711 So(err, ShouldBeNil) 712 713 So(jsonBody["version_id"], ShouldEqual, versionId) 714 715 _jsonBuilds, ok := jsonBody["builds"] 716 So(ok, ShouldBeTrue) 717 jsonBuilds, ok := _jsonBuilds.(map[string]interface{}) 718 So(ok, ShouldBeTrue) 719 So(len(jsonBuilds), ShouldEqual, 1) 720 721 _jsonBuild, ok := jsonBuilds[build.BuildVariant] 722 So(ok, ShouldBeTrue) 723 jsonBuild, ok := _jsonBuild.(map[string]interface{}) 724 So(ok, ShouldBeTrue) 725 726 _jsonTask, ok := jsonBuild[task.DisplayName] 727 So(ok, ShouldBeTrue) 728 jsonTask, ok := _jsonTask.(map[string]interface{}) 729 So(ok, ShouldBeTrue) 730 731 So(jsonTask["task_id"], ShouldEqual, task.Id) 732 So(jsonTask["status"], ShouldEqual, task.Status) 733 So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken) 734 }) 735 }) 736 737 Convey("grouped by an invalid option", func() { 738 groupBy := "invalidOption" 739 740 url, err := router.Get("version_status").URL("version_id", versionId) 741 So(err, ShouldBeNil) 742 743 query := url.Query() 744 query.Set("groupby", groupBy) 745 url.RawQuery = query.Encode() 746 747 request, err := http.NewRequest("GET", url.String(), nil) 748 So(err, ShouldBeNil) 749 750 response := httptest.NewRecorder() 751 // Need match variables to be set so can call mux.Vars(request) 752 // in the actual handler function 753 router.ServeHTTP(response, request) 754 755 So(response.Code, ShouldEqual, http.StatusBadRequest) 756 757 var jsonBody map[string]interface{} 758 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 759 So(err, ShouldBeNil) 760 761 So(jsonBody["message"], ShouldEqual, 762 fmt.Sprintf("Invalid groupby parameter '%v'", groupBy)) 763 }) 764 }) 765 766 Convey("When finding the status of a nonexistent version", t, func() { 767 versionId := "not-present" 768 769 Convey("grouped by tasks", func() { 770 groupBy := "tasks" 771 772 url, err := router.Get("version_status").URL("version_id", versionId) 773 So(err, ShouldBeNil) 774 775 query := url.Query() 776 query.Set("groupby", groupBy) 777 url.RawQuery = query.Encode() 778 779 request, err := http.NewRequest("GET", url.String(), nil) 780 So(err, ShouldBeNil) 781 782 response := httptest.NewRecorder() 783 // Need match variables to be set so can call mux.Vars(request) 784 // in the actual handler function 785 router.ServeHTTP(response, request) 786 787 So(response.Code, ShouldEqual, http.StatusOK) 788 789 Convey("response should contain a sensible error message", func() { 790 var jsonBody map[string]interface{} 791 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 792 So(err, ShouldBeNil) 793 794 _jsonTasks, ok := jsonBody["tasks"] 795 So(ok, ShouldBeTrue) 796 jsonTasks, ok := _jsonTasks.(map[string]interface{}) 797 So(ok, ShouldBeTrue) 798 So(jsonTasks, ShouldBeEmpty) 799 }) 800 }) 801 802 Convey("grouped by builds", func() { 803 versionId := "not-present" 804 groupBy := "builds" 805 806 url, err := router.Get("version_status").URL("version_id", versionId) 807 So(err, ShouldBeNil) 808 809 query := url.Query() 810 query.Set("groupby", groupBy) 811 url.RawQuery = query.Encode() 812 813 request, err := http.NewRequest("GET", url.String(), nil) 814 So(err, ShouldBeNil) 815 816 response := httptest.NewRecorder() 817 // Need match variables to be set so can call mux.Vars(request) 818 // in the actual handler function 819 router.ServeHTTP(response, request) 820 821 So(response.Code, ShouldEqual, http.StatusOK) 822 823 Convey("response should contain a sensible error message", func() { 824 var jsonBody map[string]interface{} 825 err = json.Unmarshal(response.Body.Bytes(), &jsonBody) 826 So(err, ShouldBeNil) 827 828 _jsonBuilds, ok := jsonBody["builds"] 829 So(ok, ShouldBeTrue) 830 jsonBuilds, ok := _jsonBuilds.(map[string]interface{}) 831 So(ok, ShouldBeTrue) 832 So(jsonBuilds, ShouldBeEmpty) 833 }) 834 }) 835 }) 836 } 837 838 func validateVersionInfo(v *version.Version, response *httptest.ResponseRecorder) { 839 Convey("response should match contents of database", func() { 840 var jsonBody map[string]interface{} 841 err := json.Unmarshal(response.Body.Bytes(), &jsonBody) 842 So(err, ShouldBeNil) 843 844 var rawJsonBody map[string]*json.RawMessage 845 err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody) 846 So(err, ShouldBeNil) 847 848 So(jsonBody["id"], ShouldEqual, v.Id) 849 850 var createTime time.Time 851 err = json.Unmarshal(*rawJsonBody["create_time"], &createTime) 852 So(err, ShouldBeNil) 853 So(createTime, ShouldHappenWithin, TimePrecision, v.CreateTime) 854 855 var startTime time.Time 856 err = json.Unmarshal(*rawJsonBody["start_time"], &startTime) 857 So(err, ShouldBeNil) 858 So(startTime, ShouldHappenWithin, TimePrecision, v.StartTime) 859 860 var finishTime time.Time 861 err = json.Unmarshal(*rawJsonBody["finish_time"], &finishTime) 862 So(err, ShouldBeNil) 863 So(finishTime, ShouldHappenWithin, TimePrecision, v.FinishTime) 864 865 So(jsonBody["project"], ShouldEqual, v.Identifier) 866 So(jsonBody["revision"], ShouldEqual, v.Revision) 867 So(jsonBody["author"], ShouldEqual, v.Author) 868 So(jsonBody["author_email"], ShouldEqual, v.AuthorEmail) 869 So(jsonBody["message"], ShouldEqual, v.Message) 870 So(jsonBody["status"], ShouldEqual, v.Status) 871 872 var buildIds []string 873 err = json.Unmarshal(*rawJsonBody["builds"], &buildIds) 874 So(err, ShouldBeNil) 875 So(buildIds, ShouldResemble, v.BuildIds) 876 877 var buildVariants []string 878 err = json.Unmarshal(*rawJsonBody["build_variants"], &buildVariants) 879 So(err, ShouldBeNil) 880 So(buildVariants[0], ShouldResemble, v.BuildVariants[0].BuildVariant) 881 882 So(jsonBody["order"], ShouldEqual, v.RevisionOrderNumber) 883 So(jsonBody["owner_name"], ShouldEqual, v.Owner) 884 So(jsonBody["repo_name"], ShouldEqual, v.Repo) 885 So(jsonBody["branch_name"], ShouldEqual, v.Branch) 886 So(jsonBody["repo_kind"], ShouldEqual, v.RepoKind) 887 So(jsonBody["identifier"], ShouldEqual, v.Identifier) 888 So(jsonBody["remote"], ShouldEqual, v.Remote) 889 So(jsonBody["remote_path"], ShouldEqual, v.RemotePath) 890 So(jsonBody["requester"], ShouldEqual, v.Requester) 891 }) 892 }