github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/cli/cli_integration_test.go (about) 1 package cli 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "testing" 9 "time" 10 11 "github.com/evergreen-ci/evergreen" 12 "github.com/evergreen-ci/evergreen/db" 13 "github.com/evergreen-ci/evergreen/model" 14 "github.com/evergreen-ci/evergreen/model/artifact" 15 "github.com/evergreen-ci/evergreen/model/build" 16 "github.com/evergreen-ci/evergreen/model/patch" 17 "github.com/evergreen-ci/evergreen/model/task" 18 "github.com/evergreen-ci/evergreen/model/user" 19 "github.com/evergreen-ci/evergreen/model/version" 20 "github.com/evergreen-ci/evergreen/plugin" 21 "github.com/evergreen-ci/evergreen/service" 22 "github.com/evergreen-ci/evergreen/testutil" 23 . "github.com/smartystreets/goconvey/convey" 24 "gopkg.in/mgo.v2/bson" 25 "gopkg.in/yaml.v2" 26 ) 27 28 var testConfig = testutil.TestConfig() 29 30 var testPatch = `diff --git a/README.md b/README.md 31 index e69de29..e5dcf0f 100644 32 --- a/README.md 33 +++ b/README.md 34 @@ -0,0 +1,2 @@ 35 + 36 +sdgs 37 ` 38 39 var testModulePatch = ` 40 diff --git a/blah.md b/blah.md 41 new file mode 100644 42 index 0000000..ce01362 43 --- /dev/null 44 +++ b/blah.md 45 @@ -0,0 +1 @@ 46 +hello 47 ` 48 49 var emptyPatch = `` 50 51 func init() { 52 db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(testConfig)) 53 } 54 55 type cliTestHarness struct { 56 testServer *service.TestServer 57 settingsFilePath string 58 } 59 60 func setupCLITestHarness() cliTestHarness { 61 // create a test API server 62 testServer, err := service.CreateTestServer(testConfig, nil, plugin.APIPlugins) 63 So(err, ShouldBeNil) 64 So( 65 db.ClearCollections( 66 task.Collection, 67 build.Collection, 68 user.Collection, 69 patch.Collection, 70 model.ProjectRefCollection, 71 artifact.Collection, 72 version.Collection, 73 ), 74 ShouldBeNil) 75 So(db.Clear(patch.Collection), ShouldBeNil) 76 So(db.Clear(model.ProjectRefCollection), ShouldBeNil) 77 So((&user.DBUser{Id: "testuser", APIKey: "testapikey", EmailAddress: "tester@mongodb.com"}).Insert(), ShouldBeNil) 78 localConfBytes, err := ioutil.ReadFile(filepath.Join(testutil.GetDirectoryOfFile(), "testdata", "sample.yml")) 79 So(err, ShouldBeNil) 80 81 projectRef := &model.ProjectRef{ 82 Identifier: "sample", 83 Owner: "evergreen-ci", 84 Repo: "sample", 85 RepoKind: "github", 86 Branch: "master", 87 RemotePath: "evergreen.yml", 88 LocalConfig: string(localConfBytes), 89 Enabled: true, 90 BatchTime: 180, 91 } 92 So(projectRef.Insert(), ShouldBeNil) 93 94 // create a settings file for the command line client 95 settings := model.CLISettings{ 96 APIServerHost: testServer.URL + "/api", 97 UIServerHost: "http://dev-evg.mongodb.com", 98 APIKey: "testapikey", 99 User: "testuser", 100 } 101 settingsFile, err := ioutil.TempFile("", "settings") 102 So(err, ShouldBeNil) 103 settingsBytes, err := yaml.Marshal(settings) 104 So(err, ShouldBeNil) 105 _, err = settingsFile.Write(settingsBytes) 106 So(err, ShouldBeNil) 107 So(settingsFile.Close(), ShouldBeNil) 108 return cliTestHarness{testServer, settingsFile.Name()} 109 } 110 111 func TestCLIFetchSource(t *testing.T) { 112 testutil.ConfigureIntegrationTest(t, testConfig, "TestCLIFetchSource") 113 Convey("with a task containing patches and modules", t, func() { 114 testSetup := setupCLITestHarness() 115 defer testSetup.testServer.Close() 116 err := os.RemoveAll("source-patch-1_sample") 117 So(err, ShouldBeNil) 118 119 // first, create a patch 120 patchSub := patchSubmission{"sample", 121 testPatch, 122 "sample patch", 123 "3c7bfeb82d492dc453e7431be664539c35b5db4b", 124 "all", 125 []string{"all"}, 126 false} 127 128 // Set up a test patch that contains module changes 129 ac, rc, _, err := getAPIClients(&Options{testSetup.settingsFilePath}) 130 So(err, ShouldBeNil) 131 newPatch, err := ac.PutPatch(patchSub) 132 So(err, ShouldBeNil) 133 _, err = ac.GetPatches(0) 134 So(err, ShouldBeNil) 135 So(ac.UpdatePatchModule(newPatch.Id.Hex(), "render-module", testModulePatch, "1e5232709595db427893826ce19289461cba3f75"), 136 ShouldBeNil) 137 So(ac.FinalizePatch(newPatch.Id.Hex()), ShouldBeNil) 138 139 patches, err := ac.GetPatches(0) 140 So(err, ShouldBeNil) 141 testTask, err := task.FindOne( 142 db.Query(bson.M{ 143 task.VersionKey: patches[0].Version, 144 task.BuildVariantKey: "ubuntu", 145 })) 146 So(err, ShouldBeNil) 147 So(testTask, ShouldNotBeNil) 148 149 err = fetchSource(ac, rc, "", testTask.Id, false) 150 So(err, ShouldBeNil) 151 152 fileStat, err := os.Stat("./source-patch-1_sample/README.md") 153 So(err, ShouldBeNil) 154 // If patch was applied correctly, README.md will have a non-zero size 155 So(fileStat.Size, ShouldNotEqual, 0) 156 // If module was fetched, "render" directory should have been created. 157 // The "blah.md" file should have been created if the patch was applied successfully. 158 fileStat, err = os.Stat("./source-patch-1_sample/modules/render-module/blah.md") 159 So(err, ShouldBeNil) 160 So(fileStat.Size, ShouldNotEqual, 0) 161 162 }) 163 } 164 165 func TestCLIFetchArtifacts(t *testing.T) { 166 testutil.ConfigureIntegrationTest(t, testConfig, "TestCLIFetchArtifacts") 167 Convey("with API test server running", t, func() { 168 testSetup := setupCLITestHarness() 169 defer testSetup.testServer.Close() 170 171 err := os.RemoveAll("artifacts-abcdef-rest_task_variant_task_one") 172 So(err, ShouldBeNil) 173 err = os.RemoveAll("artifacts-abcdef-rest_task_variant_task_two") 174 So(err, ShouldBeNil) 175 176 err = (&task.Task{ 177 Id: "rest_task_test_id1", 178 BuildVariant: "rest_task_variant", 179 Revision: "abcdef1234", 180 DependsOn: []task.Dependency{{TaskId: "rest_task_test_id2"}}, 181 DisplayName: "task_one", 182 }).Insert() 183 So(err, ShouldBeNil) 184 185 err = (&task.Task{ 186 Id: "rest_task_test_id2", 187 Revision: "abcdef1234", 188 BuildVariant: "rest_task_variant", 189 DependsOn: []task.Dependency{}, 190 DisplayName: "task_two", 191 }).Insert() 192 193 err = (&artifact.Entry{ 194 TaskId: "rest_task_test_id1", 195 TaskDisplayName: "task_one", 196 Files: []artifact.File{{Link: "http://www.google.com/robots.txt"}}, 197 }).Upsert() 198 So(err, ShouldBeNil) 199 200 err = (&artifact.Entry{ 201 TaskId: "rest_task_test_id2", 202 TaskDisplayName: "task_two", 203 Files: []artifact.File{{Link: "http://www.google.com/humans.txt"}}, 204 }).Upsert() 205 So(err, ShouldBeNil) 206 207 _, rc, _, err := getAPIClients(&Options{testSetup.settingsFilePath}) 208 So(err, ShouldBeNil) 209 210 Convey("shallow fetch artifacts should download a single task's artifacts successfully", func() { 211 err = fetchArtifacts(rc, "rest_task_test_id1", "", true) 212 So(err, ShouldBeNil) 213 // downloaded file should exist where we expect 214 fileStat, err := os.Stat("./artifacts-abcdef-rest_task_variant_task_one/robots.txt") 215 So(err, ShouldBeNil) 216 So(fileStat.Size(), ShouldBeGreaterThan, 0) 217 218 fileStat, err = os.Stat("./rest_task_variant_task_two/humans.txt") 219 So(os.IsNotExist(err), ShouldBeTrue) 220 Convey("deep fetch artifacts should also download artifacts from dependency", func() { 221 err = fetchArtifacts(rc, "rest_task_test_id1", "", false) 222 So(err, ShouldBeNil) 223 fileStat, err = os.Stat("./artifacts-abcdef-rest_task_variant_task_two/humans.txt") 224 So(os.IsNotExist(err), ShouldBeFalse) 225 }) 226 }) 227 }) 228 } 229 230 func TestCLITestHistory(t *testing.T) { 231 testutil.ConfigureIntegrationTest(t, testConfig, "TestCLITestHistory") 232 Convey("with API test server running", t, func() { 233 testSetup := setupCLITestHarness() 234 defer testSetup.testServer.Close() 235 236 Convey("with a set of tasks being inserted into the database", func() { 237 now := time.Now() 238 revisionBeginning := "101112dfac9f1251466afe7c4bf9f56b" 239 project := "sample" 240 testVersion := version.Version{ 241 Id: "version1", 242 Revision: fmt.Sprintf("%vversion1", revisionBeginning), 243 RevisionOrderNumber: 1, 244 Identifier: project, 245 Requester: evergreen.RepotrackerVersionRequester, 246 } 247 So(testVersion.Insert(), ShouldBeNil) 248 testVersion2 := version.Version{ 249 Id: "version2", 250 Revision: fmt.Sprintf("%vversion2", revisionBeginning), 251 RevisionOrderNumber: 2, 252 Identifier: project, 253 Requester: evergreen.RepotrackerVersionRequester, 254 } 255 So(testVersion2.Insert(), ShouldBeNil) 256 testVersion3 := version.Version{ 257 Id: "version3", 258 Revision: fmt.Sprintf("%vversion3", revisionBeginning), 259 RevisionOrderNumber: 4, 260 Identifier: project, 261 Requester: evergreen.RepotrackerVersionRequester, 262 } 263 So(testVersion3.Insert(), ShouldBeNil) 264 // create tasks with three different display names that start and finish at various times 265 for i := 0; i < 10; i++ { 266 startTime := now.Add(time.Minute * time.Duration(i)) 267 endTime := now.Add(time.Minute * time.Duration(i+1)) 268 passingResult := task.TestResult{ 269 TestFile: "passingTest", 270 Status: evergreen.TestSucceededStatus, 271 StartTime: float64(startTime.Unix()), 272 EndTime: float64(endTime.Unix()), 273 } 274 failedResult := task.TestResult{ 275 TestFile: "failingTest", 276 Status: evergreen.TestFailedStatus, 277 StartTime: float64(startTime.Unix()), 278 EndTime: float64(endTime.Unix()), 279 } 280 t := task.Task{ 281 Id: fmt.Sprintf("task_%v", i), 282 Project: project, 283 DisplayName: fmt.Sprintf("testTask_%v", i%3), 284 Revision: fmt.Sprintf("%vversion%v", revisionBeginning, i%3), 285 Version: fmt.Sprintf("version%v", i%3), 286 BuildVariant: "osx", 287 Status: evergreen.TaskFailed, 288 TestResults: []task.TestResult{passingResult, failedResult}, 289 } 290 So(t.Insert(), ShouldBeNil) 291 } 292 293 Convey("with a CLI test history command with tasks, executing should set defaults and print out results", func() { 294 thc := TestHistoryCommand{ 295 GlobalOpts: &Options{testSetup.settingsFilePath}, 296 Project: project, 297 Tasks: []string{"testTask_1"}, 298 Limit: 20, 299 } 300 So(thc.Execute([]string{}), ShouldBeNil) 301 }) 302 }) 303 }) 304 305 } 306 307 func TestCLIFunctions(t *testing.T) { 308 testutil.ConfigureIntegrationTest(t, testConfig, "TestCLIFunctions") 309 310 var patches []patch.Patch 311 312 Convey("with API test server running", t, func() { 313 testSetup := setupCLITestHarness() 314 defer testSetup.testServer.Close() 315 316 ac, _, _, err := getAPIClients(&Options{testSetup.settingsFilePath}) 317 So(err, ShouldBeNil) 318 319 Convey("check that creating a patch works", func() { 320 Convey("user should start with no patches present", func() { 321 patches, err = ac.GetPatches(0) 322 So(err, ShouldBeNil) 323 So(len(patches), ShouldEqual, 0) 324 }) 325 326 Convey("Creating a simple patch should be successful", func() { 327 patchSub := patchSubmission{"sample", 328 testPatch, 329 "sample patch", 330 "3c7bfeb82d492dc453e7431be664539c35b5db4b", 331 "all", 332 []string{"all"}, 333 false} 334 335 newPatch, err := ac.PutPatch(patchSub) 336 So(err, ShouldBeNil) 337 338 Convey("Newly created patch should be fetchable via API", func() { 339 patches, err = ac.GetPatches(0) 340 So(err, ShouldBeNil) 341 So(len(patches), ShouldEqual, 1) 342 }) 343 344 Convey("Adding a module to the patch should work", func() { 345 err = ac.UpdatePatchModule(newPatch.Id.Hex(), "render-module", testPatch, "1e5232709595db427893826ce19289461cba3f75") 346 So(err, ShouldBeNil) 347 patches, err = ac.GetPatches(0) 348 So(err, ShouldBeNil) 349 So(patches[0].Patches[0].ModuleName, ShouldEqual, "") 350 So(patches[0].Patches[1].ModuleName, ShouldEqual, "render-module") 351 Convey("Removing the module from the patch should work", func() { 352 So(ac.DeletePatchModule(newPatch.Id.Hex(), "render-module"), ShouldBeNil) 353 patches, err = ac.GetPatches(0) 354 So(err, ShouldBeNil) 355 So(len(patches[0].Patches), ShouldEqual, 1) 356 Convey("Finalizing the patch should work", func() { 357 // First double check that the patch starts with no "version" field 358 So(patches[0].Version, ShouldEqual, "") 359 So(ac.FinalizePatch(newPatch.Id.Hex()), ShouldBeNil) 360 patches, err = ac.GetPatches(0) 361 So(err, ShouldBeNil) 362 // After finalizing, the patch should now have a version populated 363 So(patches[0].Version, ShouldNotEqual, "") 364 Convey("Canceling the patch should work", func() { 365 So(ac.CancelPatch(newPatch.Id.Hex()), ShouldBeNil) 366 patches, err = ac.GetPatches(0) 367 So(err, ShouldBeNil) 368 // After canceling, tasks in the version should be deactivated 369 tasks, err := task.Find(task.ByVersion(patches[0].Version)) 370 So(err, ShouldBeNil) 371 for _, t := range tasks { 372 So(t.Activated, ShouldBeFalse) 373 } 374 }) 375 }) 376 }) 377 }) 378 }) 379 380 Convey("Creating a patch without variants should be successful", func() { 381 patchSub := patchSubmission{ 382 "sample", 383 testPatch, 384 "sample patch", 385 "3c7bfeb82d492dc453e7431be664539c35b5db4b", 386 "all", 387 []string{}, 388 false, 389 } 390 _, err := ac.PutPatch(patchSub) 391 So(err, ShouldBeNil) 392 }) 393 394 Convey("Creating a complex patch should be successful", func() { 395 patchSub := patchSubmission{"sample", 396 testPatch, 397 "sample patch #2", 398 "3c7bfeb82d492dc453e7431be664539c35b5db4b", 399 "osx-108", 400 []string{"failing_test"}, 401 false} 402 403 _, err := ac.PutPatch(patchSub) 404 So(err, ShouldBeNil) 405 406 Convey("Newly created patch should be fetchable via API", func() { 407 patches, err = ac.GetPatches(1) 408 So(err, ShouldBeNil) 409 So(len(patches), ShouldEqual, 1) 410 So(len(patches[0].BuildVariants), ShouldEqual, 1) 411 So(patches[0].BuildVariants[0], ShouldEqual, "osx-108") 412 So(len(patches[0].Tasks), ShouldEqual, 2) 413 So(patches[0].Tasks, ShouldContain, "failing_test") 414 Convey("and have expanded dependencies", func() { 415 So(patches[0].Tasks, ShouldContain, "compile") 416 }) 417 418 Convey("putting the patch again", func() { 419 _, err := ac.PutPatch(patchSub) 420 So(err, ShouldBeNil) 421 Convey("GetPatches where n=1 should return 1 patch", func() { 422 patches, err = ac.GetPatches(1) 423 So(err, ShouldBeNil) 424 So(len(patches), ShouldEqual, 1) 425 }) 426 Convey("GetPatches where n=2 should return 2 patches", func() { 427 patches, err = ac.GetPatches(2) 428 So(err, ShouldBeNil) 429 So(len(patches), ShouldEqual, 2) 430 }) 431 }) 432 }) 433 }) 434 435 Convey("Creating an empty patch should not error out anything", func() { 436 patchSub := patchSubmission{ 437 projectId: "sample", 438 patchData: emptyPatch, 439 description: "sample patch", 440 base: "3c7bfeb82d492dc453e7431be664539c35b5db4b", 441 variants: "all", 442 tasks: []string{"all"}, 443 finalize: false} 444 445 newPatch, err := ac.PutPatch(patchSub) 446 So(err, ShouldBeNil) 447 448 Convey("Newly created patch should be fetchable via API", func() { 449 patches, err = ac.GetPatches(0) 450 So(err, ShouldBeNil) 451 So(len(patches), ShouldEqual, 1) 452 }) 453 454 Convey("Adding a module to the patch should still work as designed even with empty patch", func() { 455 err = ac.UpdatePatchModule(newPatch.Id.Hex(), "render-module", emptyPatch, "1e5232709595db427893826ce19289461cba3f75") 456 So(err, ShouldBeNil) 457 patches, err := ac.GetPatches(0) 458 So(err, ShouldBeNil) 459 So(patches[0].Patches[0].ModuleName, ShouldEqual, "") 460 So(patches[0].Patches[1].ModuleName, ShouldEqual, "render-module") 461 Convey("Removing the module from the patch should work as designed even with empty patch", func() { 462 So(ac.DeletePatchModule(newPatch.Id.Hex(), "render-module"), ShouldBeNil) 463 patches, err := ac.GetPatches(0) 464 So(err, ShouldBeNil) 465 So(len(patches[0].Patches), ShouldEqual, 1) 466 Convey("Finalizing the patch should start with no version field and then be populated", func() { 467 So(patches[0].Version, ShouldEqual, "") 468 So(ac.FinalizePatch(newPatch.Id.Hex()), ShouldBeNil) 469 patches, err := ac.GetPatches(0) 470 So(err, ShouldBeNil) 471 So(patches[0].Version, ShouldNotEqual, "") 472 Convey("Canceling the patch should work and the version should be deactivated", func() { 473 So(ac.CancelPatch(newPatch.Id.Hex()), ShouldBeNil) 474 patches, err := ac.GetPatches(0) 475 So(err, ShouldBeNil) 476 tasks, err := task.Find(task.ByVersion(patches[0].Version)) 477 So(err, ShouldBeNil) 478 for _, t := range tasks { 479 So(t.Activated, ShouldBeFalse) 480 } 481 }) 482 }) 483 }) 484 }) 485 }) 486 Convey("Listing variants or tasks for a project should list all variants", func() { 487 tasks, err := ac.ListTasks("sample") 488 So(err, ShouldBeNil) 489 So(tasks, ShouldNotBeEmpty) 490 So(len(tasks), ShouldEqual, 4) 491 }) 492 Convey("Listing variants for a project should list all variants", func() { 493 494 variants, err := ac.ListVariants("sample") 495 So(err, ShouldBeNil) 496 So(variants, ShouldNotBeEmpty) 497 So(len(variants), ShouldEqual, 2) 498 }) 499 Convey("Creating a patch using 'all' as variants should schedule all variants", func() { 500 patchSub := patchSubmission{"sample", 501 testPatch, 502 "sample patch #2", 503 "3c7bfeb82d492dc453e7431be664539c35b5db4b", 504 "all", 505 []string{"failing_test"}, 506 false} 507 508 _, err := ac.PutPatch(patchSub) 509 So(err, ShouldBeNil) 510 511 Convey("Newly created patch should be fetchable via API", func() { 512 patches, err := ac.GetPatches(1) 513 So(err, ShouldBeNil) 514 So(len(patches), ShouldEqual, 1) 515 So(len(patches[0].BuildVariants), ShouldEqual, 2) 516 So(patches[0].BuildVariants, ShouldContain, "osx-108") 517 So(patches[0].BuildVariants, ShouldContain, "ubuntu") 518 So(len(patches[0].Tasks), ShouldEqual, 2) 519 So(patches[0].Tasks, ShouldContain, "failing_test") 520 Convey("and have expanded dependencies", func() { 521 So(patches[0].Tasks, ShouldContain, "compile") 522 }) 523 }) 524 }) 525 526 Convey("Creating a patch using 'all' as tasks should schedule all tasks", func() { 527 patchSub := patchSubmission{"sample", 528 testPatch, 529 "sample patch #2", 530 "3c7bfeb82d492dc453e7431be664539c35b5db4b", 531 "osx-108", 532 []string{"all"}, 533 false} 534 535 _, err := ac.PutPatch(patchSub) 536 So(err, ShouldBeNil) 537 538 Convey("Newly created patch should be fetchable via API", func() { 539 patches, err := ac.GetPatches(1) 540 So(err, ShouldBeNil) 541 So(len(patches), ShouldEqual, 1) 542 So(len(patches[0].BuildVariants), ShouldEqual, 1) 543 So(patches[0].BuildVariants[0], ShouldEqual, "osx-108") 544 So(len(patches[0].Tasks), ShouldEqual, 4) 545 So(patches[0].Tasks, ShouldContain, "compile") 546 So(patches[0].Tasks, ShouldContain, "passing_test") 547 So(patches[0].Tasks, ShouldContain, "failing_test") 548 So(patches[0].Tasks, ShouldContain, "timeout_test") 549 }) 550 }) 551 552 }) 553 }) 554 }