github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/model/host/host_test.go (about) 1 package host 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/evergreen-ci/evergreen" 9 "github.com/evergreen-ci/evergreen/db" 10 "github.com/evergreen-ci/evergreen/model/distro" 11 "github.com/evergreen-ci/evergreen/testutil" 12 . "github.com/smartystreets/goconvey/convey" 13 "gopkg.in/mgo.v2/bson" 14 ) 15 16 func init() { 17 db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(testutil.TestConfig())) 18 } 19 20 func hostIdInSlice(hosts []Host, id string) bool { 21 for _, host := range hosts { 22 if host.Id == id { 23 return true 24 } 25 } 26 return false 27 } 28 29 func TestGenericHostFinding(t *testing.T) { 30 31 Convey("When finding hosts", t, func() { 32 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 33 " '%v' collection", Collection) 34 35 Convey("when finding one host", func() { 36 Convey("the matching host should be returned", func() { 37 matchingHost := &Host{ 38 Id: "matches", 39 } 40 So(matchingHost.Insert(), ShouldBeNil) 41 42 nonMatchingHost := &Host{ 43 Id: "nonMatches", 44 } 45 So(nonMatchingHost.Insert(), ShouldBeNil) 46 47 found, err := FindOne(ById(matchingHost.Id)) 48 So(err, ShouldBeNil) 49 So(found.Id, ShouldEqual, matchingHost.Id) 50 51 }) 52 }) 53 54 Convey("when finding multiple hosts", func() { 55 dId := fmt.Sprintf("%v.%v", DistroKey, distro.IdKey) 56 57 Convey("the hosts matching the query should be returned", func() { 58 matchingHostOne := &Host{ 59 Id: "matches", 60 Distro: distro.Distro{Id: "d1"}, 61 } 62 So(matchingHostOne.Insert(), ShouldBeNil) 63 64 matchingHostTwo := &Host{ 65 Id: "matchesAlso", 66 Distro: distro.Distro{Id: "d1"}, 67 } 68 So(matchingHostTwo.Insert(), ShouldBeNil) 69 70 nonMatchingHost := &Host{ 71 Id: "nonMatches", 72 Distro: distro.Distro{Id: "d2"}, 73 } 74 So(nonMatchingHost.Insert(), ShouldBeNil) 75 76 found, err := Find(db.Query(bson.M{dId: "d1"})) 77 So(err, ShouldBeNil) 78 So(len(found), ShouldEqual, 2) 79 So(hostIdInSlice(found, matchingHostOne.Id), ShouldBeTrue) 80 So(hostIdInSlice(found, matchingHostTwo.Id), ShouldBeTrue) 81 82 }) 83 84 Convey("when querying two hosts for running tasks", func() { 85 matchingHost := &Host{Id: "task", Status: evergreen.HostRunning, RunningTask: "t1"} 86 So(matchingHost.Insert(), ShouldBeNil) 87 nonMatchingHost := &Host{Id: "nope", Status: evergreen.HostRunning} 88 So(nonMatchingHost.Insert(), ShouldBeNil) 89 Convey("the host with the running task should be returned", func() { 90 found, err := Find(IsRunningTask) 91 So(err, ShouldBeNil) 92 So(len(found), ShouldEqual, 1) 93 So(found[0].Id, ShouldEqual, matchingHost.Id) 94 }) 95 }) 96 97 Convey("the specified projection, sort, skip, and limit should be used", func() { 98 matchingHostOne := &Host{ 99 Id: "matches", 100 Host: "hostOne", 101 Distro: distro.Distro{Id: "d1"}, 102 Tag: "2", 103 } 104 So(matchingHostOne.Insert(), ShouldBeNil) 105 106 matchingHostTwo := &Host{ 107 Id: "matchesAlso", 108 Host: "hostTwo", 109 Distro: distro.Distro{Id: "d1"}, 110 Tag: "1", 111 } 112 So(matchingHostTwo.Insert(), ShouldBeNil) 113 114 matchingHostThree := &Host{ 115 Id: "stillMatches", 116 Host: "hostThree", 117 Distro: distro.Distro{Id: "d1"}, 118 Tag: "3", 119 } 120 So(matchingHostThree.Insert(), ShouldBeNil) 121 122 // find the hosts, removing the host field from the projection, 123 // sorting by tag, skipping one, and limiting to one 124 125 found, err := Find(db.Query(bson.M{dId: "d1"}). 126 WithoutFields(DNSKey). 127 Sort([]string{TagKey}). 128 Skip(1).Limit(1)) 129 So(err, ShouldBeNil) 130 So(len(found), ShouldEqual, 1) 131 So(found[0].Id, ShouldEqual, matchingHostOne.Id) 132 So(found[0].Host, ShouldEqual, "") // filtered out in projection 133 }) 134 }) 135 }) 136 } 137 138 func TestFindingHostsWithRunningTasks(t *testing.T) { 139 Convey("With a host with no running task that is not terminated", t, func() { 140 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 141 " '%v' collection", Collection) 142 h := Host{ 143 Id: "sample_host", 144 Status: evergreen.HostRunning, 145 } 146 So(h.Insert(), ShouldBeNil) 147 found, err := Find(IsRunningTask) 148 So(err, ShouldBeNil) 149 So(len(found), ShouldEqual, 0) 150 Convey("with a host that is terminated with no running task", func() { 151 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 152 " '%v' collection", Collection) 153 h1 := Host{ 154 Id: "another", 155 Status: evergreen.HostTerminated, 156 } 157 So(h1.Insert(), ShouldBeNil) 158 found, err = Find(IsRunningTask) 159 So(err, ShouldBeNil) 160 So(len(found), ShouldEqual, 0) 161 }) 162 }) 163 164 } 165 166 func TestMonitorHosts(t *testing.T) { 167 Convey("With a host with no reachability check", t, func() { 168 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 169 " '%v' collection", Collection) 170 now := time.Now() 171 h := Host{ 172 Id: "sample_host", 173 Status: evergreen.HostRunning, 174 StartedBy: evergreen.User, 175 } 176 So(h.Insert(), ShouldBeNil) 177 found, err := Find(ByNotMonitoredSince(now)) 178 So(err, ShouldBeNil) 179 So(len(found), ShouldEqual, 1) 180 Convey("a host that has a running task and no reachability check should not return", func() { 181 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 182 " '%v' collection", Collection) 183 anotherHost := Host{ 184 Id: "anotherHost", 185 Status: evergreen.HostRunning, 186 StartedBy: evergreen.User, 187 RunningTask: "id", 188 } 189 So(anotherHost.Insert(), ShouldBeNil) 190 found, err := Find(ByNotMonitoredSince(now)) 191 So(err, ShouldBeNil) 192 So(len(found), ShouldEqual, 0) 193 }) 194 }) 195 } 196 197 func TestUpdatingHostStatus(t *testing.T) { 198 199 Convey("With a host", t, func() { 200 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 201 " clearing '%v' collection", Collection) 202 203 var err error 204 205 host := &Host{ 206 Id: "hostOne", 207 } 208 209 So(host.Insert(), ShouldBeNil) 210 211 Convey("setting the host's status should update both the in-memory"+ 212 " and database versions of the host", func() { 213 214 So(host.SetStatus(evergreen.HostRunning), ShouldBeNil) 215 So(host.Status, ShouldEqual, evergreen.HostRunning) 216 217 host, err = FindOne(ById(host.Id)) 218 So(err, ShouldBeNil) 219 So(host.Status, ShouldEqual, evergreen.HostRunning) 220 221 }) 222 223 Convey("if the host is terminated, the status update should fail"+ 224 " with an error", func() { 225 226 So(host.SetStatus(evergreen.HostTerminated), ShouldBeNil) 227 So(host.SetStatus(evergreen.HostRunning), ShouldNotBeNil) 228 So(host.Status, ShouldEqual, evergreen.HostTerminated) 229 230 host, err = FindOne(ById(host.Id)) 231 So(err, ShouldBeNil) 232 So(host.Status, ShouldEqual, evergreen.HostTerminated) 233 234 }) 235 236 }) 237 238 } 239 240 func TestSetHostTerminated(t *testing.T) { 241 242 Convey("With a host", t, func() { 243 244 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 245 " clearing '%v' collection", Collection) 246 247 var err error 248 249 host := &Host{ 250 Id: "hostOne", 251 } 252 253 So(host.Insert(), ShouldBeNil) 254 255 Convey("setting the host as terminated should set the status and the"+ 256 " termination time in both the in-memory and database copies of"+ 257 " the host", func() { 258 259 So(host.Terminate(), ShouldBeNil) 260 So(host.Status, ShouldEqual, evergreen.HostTerminated) 261 So(host.TerminationTime.IsZero(), ShouldBeFalse) 262 263 host, err = FindOne(ById(host.Id)) 264 So(err, ShouldBeNil) 265 So(host.Status, ShouldEqual, evergreen.HostTerminated) 266 So(host.TerminationTime.IsZero(), ShouldBeFalse) 267 268 }) 269 270 }) 271 } 272 273 func TestHostSetDNSName(t *testing.T) { 274 var err error 275 276 Convey("With a host", t, func() { 277 278 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 279 " clearing '%v' collection", Collection) 280 281 host := &Host{ 282 Id: "hostOne", 283 } 284 285 So(host.Insert(), ShouldBeNil) 286 287 Convey("setting the hostname should update both the in-memory and"+ 288 " database copies of the host", func() { 289 290 So(host.SetDNSName("hostname"), ShouldBeNil) 291 So(host.Host, ShouldEqual, "hostname") 292 host, err = FindOne(ById(host.Id)) 293 So(err, ShouldBeNil) 294 So(host.Host, ShouldEqual, "hostname") 295 296 // if the host is already updated, no new updates should work 297 So(host.SetDNSName("hostname2"), ShouldBeNil) 298 So(host.Host, ShouldEqual, "hostname") 299 300 host, err = FindOne(ById(host.Id)) 301 So(err, ShouldBeNil) 302 So(host.Host, ShouldEqual, "hostname") 303 304 }) 305 306 }) 307 } 308 309 func TestMarkAsProvisioned(t *testing.T) { 310 311 Convey("With a host", t, func() { 312 313 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 314 " clearing '%v' collection", Collection) 315 316 var err error 317 318 host := &Host{ 319 Id: "hostOne", 320 } 321 322 So(host.Insert(), ShouldBeNil) 323 324 Convey("marking the host as provisioned should update the status,"+ 325 " provisioned, and host name fields in both the in-memory and"+ 326 " database copies of the host", func() { 327 328 So(host.MarkAsProvisioned(), ShouldBeNil) 329 So(host.Status, ShouldEqual, evergreen.HostRunning) 330 So(host.Provisioned, ShouldEqual, true) 331 332 host, err = FindOne(ById(host.Id)) 333 So(err, ShouldBeNil) 334 So(host.Status, ShouldEqual, evergreen.HostRunning) 335 So(host.Provisioned, ShouldEqual, true) 336 337 }) 338 339 }) 340 } 341 342 func TestHostCreateSecret(t *testing.T) { 343 Convey("With a host with no secret", t, func() { 344 345 testutil.HandleTestingErr(db.Clear(Collection), t, 346 "Error clearing '%v' collection", Collection) 347 348 host := &Host{Id: "hostOne"} 349 So(host.Insert(), ShouldBeNil) 350 351 Convey("creating a secret", func() { 352 So(host.Secret, ShouldEqual, "") 353 So(host.CreateSecret(), ShouldBeNil) 354 355 Convey("should update the host in memory", func() { 356 So(host.Secret, ShouldNotEqual, "") 357 358 Convey("and in the database", func() { 359 dbHost, err := FindOne(ById(host.Id)) 360 So(err, ShouldBeNil) 361 So(dbHost.Secret, ShouldEqual, host.Secret) 362 }) 363 }) 364 }) 365 }) 366 } 367 368 func TestHostSetExpirationTime(t *testing.T) { 369 370 Convey("With a host", t, func() { 371 372 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 373 " clearing '%v' collection", Collection) 374 375 initialExpirationTime := time.Now() 376 notifications := make(map[string]bool) 377 notifications["2h"] = true 378 379 memHost := &Host{ 380 Id: "hostOne", 381 ExpirationTime: initialExpirationTime, 382 Notifications: notifications, 383 } 384 So(memHost.Insert(), ShouldBeNil) 385 386 Convey("setting the expiration time for the host should change the "+ 387 " expiration time for both the in-memory and database"+ 388 " copies of the host and unset the notifications", func() { 389 390 dbHost, err := FindOne(ById(memHost.Id)) 391 392 // ensure the db entries are as expected 393 So(err, ShouldBeNil) 394 So(memHost.ExpirationTime.Round(time.Second).Equal( 395 initialExpirationTime.Round(time.Second)), ShouldBeTrue) 396 So(dbHost.ExpirationTime.Round(time.Second).Equal( 397 initialExpirationTime.Round(time.Second)), ShouldBeTrue) 398 So(memHost.Notifications, ShouldResemble, notifications) 399 So(dbHost.Notifications, ShouldResemble, notifications) 400 401 // now update the expiration time 402 newExpirationTime := time.Now() 403 So(memHost.SetExpirationTime(newExpirationTime), ShouldBeNil) 404 405 dbHost, err = FindOne(ById(memHost.Id)) 406 407 // ensure the db entries are as expected 408 So(err, ShouldBeNil) 409 So(memHost.ExpirationTime.Round(time.Second).Equal( 410 newExpirationTime.Round(time.Second)), ShouldBeTrue) 411 So(dbHost.ExpirationTime.Round(time.Second).Equal( 412 newExpirationTime.Round(time.Second)), ShouldBeTrue) 413 So(memHost.Notifications, ShouldResemble, make(map[string]bool)) 414 So(dbHost.Notifications, ShouldEqual, nil) 415 }) 416 }) 417 } 418 419 func TestFindRunningSpawnedHosts(t *testing.T) { 420 testConfig := testutil.TestConfig() 421 db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(testConfig)) 422 423 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 424 " clearing '%v' collection", Collection) 425 426 Convey("With calling FindRunningSpawnedHosts...", t, func() { 427 Convey("if there are no spawned hosts, nothing should be returned", 428 func() { 429 spawnedHosts, err := Find(IsRunningAndSpawned) 430 So(err, ShouldBeNil) 431 // make sure we only returned no document 432 So(len(spawnedHosts), ShouldEqual, 0) 433 434 }) 435 436 Convey("if there are spawned hosts, they should be returned", func() { 437 host := &Host{} 438 host.Id = "spawned-1" 439 host.Status = "running" 440 host.StartedBy = "user1" 441 testutil.HandleTestingErr(host.Insert(), t, "error from "+ 442 "FindRunningSpawnedHosts") 443 spawnedHosts, err := Find(IsRunningAndSpawned) 444 testutil.HandleTestingErr(err, t, "error from "+ 445 "FindRunningSpawnedHosts: %v", err) 446 // make sure we only returned no document 447 So(len(spawnedHosts), ShouldEqual, 1) 448 449 }) 450 }) 451 } 452 func TestSetExpirationNotification(t *testing.T) { 453 454 Convey("With a host", t, func() { 455 456 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 457 " clearing '%v' collection", Collection) 458 459 notifications := make(map[string]bool) 460 notifications["2h"] = true 461 462 memHost := &Host{ 463 Id: "hostOne", 464 Notifications: notifications, 465 } 466 So(memHost.Insert(), ShouldBeNil) 467 468 Convey("setting the expiration notification for the host should change "+ 469 " the expiration notification for both the in-memory and database"+ 470 " copies of the host and unset the notifications", func() { 471 472 dbHost, err := FindOne(ById(memHost.Id)) 473 474 // ensure the db entries are as expected 475 So(err, ShouldBeNil) 476 So(memHost.Notifications, ShouldResemble, notifications) 477 So(dbHost.Notifications, ShouldResemble, notifications) 478 479 // now update the expiration notification 480 notifications["4h"] = true 481 So(memHost.SetExpirationNotification("4h"), ShouldBeNil) 482 dbHost, err = FindOne(ById(memHost.Id)) 483 // ensure the db entries are as expected 484 So(err, ShouldBeNil) 485 So(memHost.Notifications, ShouldResemble, notifications) 486 So(dbHost.Notifications, ShouldResemble, notifications) 487 }) 488 }) 489 } 490 491 func TestHostClearRunningTask(t *testing.T) { 492 493 Convey("With a host", t, func() { 494 495 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 496 " clearing '%v' collection", Collection) 497 498 var err error 499 var count int 500 501 host := &Host{ 502 Id: "hostOne", 503 RunningTask: "taskId", 504 StartedBy: evergreen.User, 505 Status: evergreen.HostRunning, 506 Pid: "12345", 507 } 508 509 So(host.Insert(), ShouldBeNil) 510 511 Convey("host statistics should properly count this host as active"+ 512 " but not idle", func() { 513 count, err = Count(IsActive) 514 So(err, ShouldBeNil) 515 So(count, ShouldEqual, 1) 516 count, err = Count(IsIdle) 517 So(err, ShouldBeNil) 518 So(count, ShouldEqual, 0) 519 }) 520 521 Convey("clearing the running task should clear the running task, pid,"+ 522 " and task dispatch time fields from both the in-memory and"+ 523 " database copies of the host", func() { 524 525 So(host.ClearRunningTask("prevTask", time.Now()), ShouldBeNil) 526 So(host.RunningTask, ShouldEqual, "") 527 So(host.LastTaskCompleted, ShouldEqual, "prevTask") 528 529 host, err = FindOne(ById(host.Id)) 530 So(err, ShouldBeNil) 531 532 So(host.RunningTask, ShouldEqual, "") 533 So(host.LastTaskCompleted, ShouldEqual, "prevTask") 534 535 Convey("the count of idle hosts should go up", func() { 536 count, err := Count(IsIdle) 537 So(err, ShouldBeNil) 538 So(count, ShouldEqual, 1) 539 540 Convey("but the active host count should remain the same", func() { 541 count, err = Count(IsActive) 542 So(err, ShouldBeNil) 543 So(count, ShouldEqual, 1) 544 }) 545 }) 546 547 }) 548 549 }) 550 } 551 552 func TestUpdateHostRunningTask(t *testing.T) { 553 Convey("With a host", t, func() { 554 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 555 " clearing '%v' collection", Collection) 556 oldTaskId := "oldId" 557 newTaskId := "newId" 558 h := Host{ 559 Id: "test", 560 RunningTask: oldTaskId, 561 Status: evergreen.HostRunning, 562 } 563 So(h.Insert(), ShouldBeNil) 564 Convey("updating the running task id should set proper fields", func() { 565 _, err := h.UpdateRunningTask(oldTaskId, newTaskId, time.Now()) 566 So(err, ShouldBeNil) 567 found, err := FindOne(ById(h.Id)) 568 So(err, ShouldBeNil) 569 So(found.RunningTask, ShouldEqual, newTaskId) 570 So(found.LastTaskCompleted, ShouldEqual, oldTaskId) 571 runningTaskHosts, err := Find(IsRunningTask) 572 So(err, ShouldBeNil) 573 So(len(runningTaskHosts), ShouldEqual, 1) 574 }) 575 Convey("updating the running task to an empty string should error out", func() { 576 _, err := h.UpdateRunningTask(newTaskId, "", time.Now()) 577 So(err, ShouldNotBeNil) 578 }) 579 }) 580 } 581 582 func TestUpsert(t *testing.T) { 583 584 Convey("With a host", t, func() { 585 586 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 587 " clearing '%v' collection", Collection) 588 589 host := &Host{ 590 Id: "hostOne", 591 Host: "host", 592 User: "user", 593 Distro: distro.Distro{Id: "distro"}, 594 Status: evergreen.HostRunning, 595 } 596 597 var err error 598 599 Convey("Performing a host upsert should upsert correctly", func() { 600 _, err = host.Upsert() 601 So(err, ShouldBeNil) 602 So(host.Status, ShouldEqual, evergreen.HostRunning) 603 604 host, err = FindOne(ById(host.Id)) 605 So(err, ShouldBeNil) 606 So(host.Status, ShouldEqual, evergreen.HostRunning) 607 608 }) 609 610 Convey("Updating some fields of an already inserted host should cause "+ 611 "those fields to be updated but should leave status unchanged", 612 func() { 613 _, err := host.Upsert() 614 So(err, ShouldBeNil) 615 So(host.Status, ShouldEqual, evergreen.HostRunning) 616 617 host, err = FindOne(ById(host.Id)) 618 So(err, ShouldBeNil) 619 So(host.Status, ShouldEqual, evergreen.HostRunning) 620 So(host.Host, ShouldEqual, "host") 621 622 err = UpdateOne( 623 bson.M{ 624 IdKey: host.Id, 625 }, 626 bson.M{ 627 "$set": bson.M{ 628 StatusKey: evergreen.HostDecommissioned, 629 }, 630 }, 631 ) 632 So(err, ShouldBeNil) 633 634 // update the hostname and status 635 host.Host = "host2" 636 host.Status = evergreen.HostRunning 637 _, err = host.Upsert() 638 So(err, ShouldBeNil) 639 640 // host db status should remain unchanged 641 host, err = FindOne(ById(host.Id)) 642 So(err, ShouldBeNil) 643 So(host.Status, ShouldEqual, evergreen.HostDecommissioned) 644 So(host.Host, ShouldEqual, "host2") 645 646 }) 647 }) 648 } 649 650 func TestDecommissionHostsWithDistroId(t *testing.T) { 651 652 Convey("With a multiple hosts of different distros", t, func() { 653 654 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 655 " clearing '%v' collection", Collection) 656 657 distroA := "distro_a" 658 distroB := "distro_b" 659 660 // Insert 10 of distro a and 10 of distro b 661 662 for i := 0; i < 10; i++ { 663 hostWithDistroA := &Host{ 664 Id: fmt.Sprintf("hostA%v", i), 665 Host: "host", 666 User: "user", 667 Distro: distro.Distro{Id: distroA}, 668 Status: evergreen.HostRunning, 669 } 670 hostWithDistroB := &Host{ 671 Id: fmt.Sprintf("hostB%v", i), 672 Host: "host", 673 User: "user", 674 Distro: distro.Distro{Id: distroB}, 675 Status: evergreen.HostRunning, 676 } 677 678 testutil.HandleTestingErr(hostWithDistroA.Insert(), t, "Error inserting"+ 679 "host into database") 680 testutil.HandleTestingErr(hostWithDistroB.Insert(), t, "Error inserting"+ 681 "host into database") 682 } 683 684 Convey("When decommissioning hosts of type distro_a", func() { 685 err := DecommissionHostsWithDistroId(distroA) 686 So(err, ShouldBeNil) 687 688 Convey("Distro should be marked as decommissioned accordingly", func() { 689 hostsTypeA, err := Find(ByDistroId(distroA)) 690 So(err, ShouldBeNil) 691 692 hostsTypeB, err := Find(ByDistroId(distroB)) 693 So(err, ShouldBeNil) 694 for _, host := range hostsTypeA { 695 696 So(host.Status, ShouldEqual, evergreen.HostDecommissioned) 697 } 698 699 for _, host := range hostsTypeB { 700 So(host.Status, ShouldEqual, evergreen.HostRunning) 701 702 } 703 }) 704 705 }) 706 707 }) 708 } 709 710 func TestFindByLCT(t *testing.T) { 711 Convey("with the a given time for checking and an empty hosts collection", t, func() { 712 testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+ 713 " clearing '%v' collection", Collection) 714 now := time.Now() 715 Convey("with a host that has no last communication time", func() { 716 h := Host{ 717 Id: "id", 718 Status: evergreen.HostRunning, 719 StartedBy: evergreen.User, 720 } 721 So(h.Insert(), ShouldBeNil) 722 hosts, err := Find(ByRunningWithTimedOutLCT(time.Now())) 723 So(err, ShouldBeNil) 724 So(len(hosts), ShouldEqual, 1) 725 So(hosts[0].Id, ShouldEqual, "id") 726 Convey("after unsetting the host's lct", func() { 727 err := UpdateOne(bson.M{IdKey: h.Id}, 728 bson.M{ 729 "$unset": bson.M{LastCommunicationTimeKey: 0}, 730 }) 731 So(err, ShouldBeNil) 732 foundHost, err := FindOne(ById(h.Id)) 733 So(err, ShouldBeNil) 734 So(foundHost, ShouldNotBeNil) 735 hosts, err := Find(ByRunningWithTimedOutLCT(time.Now())) 736 So(err, ShouldBeNil) 737 So(len(hosts), ShouldEqual, 1) 738 So(hosts[0].Id, ShouldEqual, h.Id) 739 }) 740 }) 741 742 Convey("with a host with a last communication time > 10 mins", func() { 743 anotherHost := Host{ 744 Id: "anotherID", 745 LastCommunicationTime: now.Add(-time.Duration(20) * time.Minute), 746 Status: evergreen.HostRunning, 747 StartedBy: evergreen.User, 748 } 749 So(anotherHost.Insert(), ShouldBeNil) 750 hosts, err := Find(ByRunningWithTimedOutLCT(now)) 751 So(err, ShouldBeNil) 752 So(len(hosts), ShouldEqual, 1) 753 So(hosts[0].Id, ShouldEqual, anotherHost.Id) 754 }) 755 756 Convey("with a host with a normal LCT", func() { 757 anotherHost := Host{ 758 Id: "testhost", 759 LastCommunicationTime: now.Add(time.Duration(5) * time.Minute), 760 Status: evergreen.HostRunning, 761 StartedBy: evergreen.User, 762 } 763 So(anotherHost.Insert(), ShouldBeNil) 764 hosts, err := Find(ByRunningWithTimedOutLCT(now)) 765 So(err, ShouldBeNil) 766 So(len(hosts), ShouldEqual, 0) 767 Convey("after resetting the LCT", func() { 768 So(anotherHost.ResetLastCommunicated(), ShouldBeNil) 769 So(anotherHost.LastCommunicationTime, ShouldResemble, time.Unix(0, 0)) 770 h, err := Find(ByRunningWithTimedOutLCT(now)) 771 So(err, ShouldBeNil) 772 So(len(h), ShouldEqual, 1) 773 So(h[0].Id, ShouldEqual, "testhost") 774 }) 775 }) 776 Convey("with a terminated host that has no LCT", func() { 777 h := Host{ 778 Id: "h", 779 Status: evergreen.HostTerminated, 780 StartedBy: evergreen.User, 781 } 782 So(h.Insert(), ShouldBeNil) 783 hosts, err := Find(ByRunningWithTimedOutLCT(now)) 784 So(err, ShouldBeNil) 785 So(len(hosts), ShouldEqual, 0) 786 }) 787 Convey("with a host with that does not have a user", func() { 788 h := Host{ 789 Id: "h", 790 Status: evergreen.HostRunning, 791 StartedBy: "anotherUser", 792 } 793 So(h.Insert(), ShouldBeNil) 794 hosts, err := Find(ByRunningWithTimedOutLCT(now)) 795 So(err, ShouldBeNil) 796 So(len(hosts), ShouldEqual, 0) 797 798 }) 799 800 }) 801 }