github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/model/audit_test.go (about)

     1  package model
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/evergreen-ci/evergreen"
     8  	"github.com/evergreen-ci/evergreen/db"
     9  	"github.com/evergreen-ci/evergreen/model/host"
    10  	"github.com/evergreen-ci/evergreen/model/task"
    11  	"github.com/evergreen-ci/evergreen/testutil"
    12  	. "github.com/smartystreets/goconvey/convey"
    13  )
    14  
    15  func TestHostTaskAuditing(t *testing.T) {
    16  	Convey("With pre-made sets of mappings", t, func() {
    17  		Convey("a valid mapping should return no inconsistencies", func() {
    18  			h2t := map[string]string{"h1": "t1", "h2": "t2", "h3": "t3"}
    19  			t2h := map[string]string{"t1": "h1", "t2": "h2", "t3": "h3"}
    20  			So(len(auditHostTaskMapping(h2t, t2h)), ShouldEqual, 0)
    21  		})
    22  		Convey("a mismapped host should return one inconsistency", func() {
    23  			h2t := map[string]string{"h1": "t1", "h2": "t2", "h3": "t3", "h4": "t1"}
    24  			t2h := map[string]string{"t1": "h4", "t2": "h2", "t3": "h3"}
    25  			out := auditHostTaskMapping(h2t, t2h)
    26  			So(len(out), ShouldEqual, 1)
    27  			So(out[0], ShouldResemble, HostTaskInconsistency{
    28  				Host: "h1", HostTaskCache: "t1", Task: "t1", TaskHostCache: "h4",
    29  			})
    30  		})
    31  		Convey("a swapped host and task should return four inconsistencies", func() {
    32  			h2t := map[string]string{"h1": "t3", "h2": "t2", "h3": "t1"}
    33  			t2h := map[string]string{"t1": "h1", "t2": "h2", "t3": "h3"}
    34  			out := auditHostTaskMapping(h2t, t2h)
    35  			So(len(out), ShouldEqual, 4)
    36  		})
    37  		Convey("one empty mapping should return inconsistencies", func() {
    38  			h2t := map[string]string{"h1": "t1", "h2": "t2", "h3": "t3"}
    39  			out := auditHostTaskMapping(h2t, nil)
    40  			So(len(out), ShouldEqual, 3)
    41  			Convey("with reasonable error language", func() {
    42  				So(out[0].Error(), ShouldContainSubstring, "does not exist")
    43  				So(out[1].Error(), ShouldContainSubstring, "does not exist")
    44  				So(out[2].Error(), ShouldContainSubstring, "does not exist")
    45  			})
    46  		})
    47  		Convey("two empty mappings should not return inconsistencies", func() {
    48  			out := auditHostTaskMapping(nil, nil)
    49  			So(len(out), ShouldEqual, 0)
    50  		})
    51  	})
    52  
    53  	Convey("With tasks and hosts stored in the db", t, func() {
    54  		testutil.HandleTestingErr(db.Clear(host.Collection), t,
    55  			"Error clearing '%v' collection", host.Collection)
    56  		testutil.HandleTestingErr(db.Clear(task.Collection), t,
    57  			"Error clearing '%v' collection", task.Collection)
    58  		Convey("no mappings should load with an empty db", func() {
    59  			h2t, t2h, err := loadHostTaskMapping()
    60  			So(err, ShouldBeNil)
    61  			So(len(h2t), ShouldEqual, 0)
    62  			So(len(t2h), ShouldEqual, 0)
    63  		})
    64  		Convey("with 3 hosts, one with a running task", func() {
    65  			h1 := host.Host{Id: "h1", Status: evergreen.HostRunning, RunningTask: "t1"}
    66  			h2 := host.Host{Id: "h2", Status: evergreen.HostRunning}
    67  			h3 := host.Host{Id: "h3", Status: evergreen.HostRunning}
    68  			So(h1.Insert(), ShouldBeNil)
    69  			So(h2.Insert(), ShouldBeNil)
    70  			So(h3.Insert(), ShouldBeNil)
    71  			Convey("only mappings should return for the task-running host", func() {
    72  				h2t, t2h, err := loadHostTaskMapping()
    73  				So(err, ShouldBeNil)
    74  				So(len(h2t), ShouldEqual, 1)
    75  				So(h2t["h1"], ShouldEqual, "t1")
    76  				So(len(t2h), ShouldEqual, 0)
    77  			})
    78  		})
    79  		Convey("with 3 hosts and 3 tasks", func() {
    80  			h1 := host.Host{Id: "h1", Status: evergreen.HostRunning, RunningTask: "t1"}
    81  			h2 := host.Host{Id: "h2", Status: evergreen.HostRunning, RunningTask: "t2"}
    82  			h3 := host.Host{Id: "h3", Status: evergreen.HostRunning}
    83  			t1 := task.Task{Id: "t1", Status: evergreen.TaskStarted, HostId: "h1"}
    84  			t2 := task.Task{Id: "t2", Status: evergreen.TaskDispatched, HostId: "h2"}
    85  			t3 := task.Task{Id: "t3"}
    86  			So(h1.Insert(), ShouldBeNil)
    87  			So(h2.Insert(), ShouldBeNil)
    88  			So(h3.Insert(), ShouldBeNil)
    89  			So(t1.Insert(), ShouldBeNil)
    90  			So(t2.Insert(), ShouldBeNil)
    91  			So(t3.Insert(), ShouldBeNil)
    92  			Convey("mappings should return for the task-running hosts and running tasks", func() {
    93  				h2t, t2h, err := loadHostTaskMapping()
    94  				So(err, ShouldBeNil)
    95  				So(len(h2t), ShouldEqual, 2)
    96  				So(h2t["h1"], ShouldEqual, "t1")
    97  				So(h2t["h2"], ShouldEqual, "t2")
    98  				So(len(t2h), ShouldEqual, 2)
    99  				So(t2h["t1"], ShouldEqual, "h1")
   100  				So(t2h["t2"], ShouldEqual, "h2")
   101  			})
   102  		})
   103  		Convey("with a task that has a host but a host that does not have a task", func() {
   104  			testutil.HandleTestingErr(db.Clear(host.Collection), t,
   105  				"Error clearing '%v' collection", host.Collection)
   106  			testutil.HandleTestingErr(db.Clear(task.Collection), t,
   107  				"Error clearing '%v' collection", task.Collection)
   108  			h := host.Host{
   109  				Id:     "host1",
   110  				Status: evergreen.HostRunning,
   111  			}
   112  			So(h.Insert(), ShouldBeNil)
   113  			t := task.Task{
   114  				Id:     "task1",
   115  				HostId: "host1",
   116  				Status: evergreen.TaskStarted,
   117  			}
   118  			So(t.Insert(), ShouldBeNil)
   119  			h2t, t2h, err := loadHostTaskMapping()
   120  			So(err, ShouldBeNil)
   121  			So(len(h2t), ShouldEqual, 0)
   122  			So(len(t2h), ShouldEqual, 1)
   123  			So(t2h["task1"], ShouldEqual, "host1")
   124  
   125  		})
   126  		Convey("with a host that has a task but a task that does not have a host", func() {
   127  			testutil.HandleTestingErr(db.Clear(host.Collection), t,
   128  				"Error clearing '%v' collection", host.Collection)
   129  			testutil.HandleTestingErr(db.Clear(task.Collection), t,
   130  				"Error clearing '%v' collection", task.Collection)
   131  			h := host.Host{
   132  				Id:          "host1",
   133  				Status:      evergreen.HostRunning,
   134  				RunningTask: "task1",
   135  			}
   136  			So(h.Insert(), ShouldBeNil)
   137  			t := task.Task{
   138  				Id:     "task1",
   139  				Status: evergreen.TaskStarted,
   140  			}
   141  			So(t.Insert(), ShouldBeNil)
   142  			h2t, t2h, err := loadHostTaskMapping()
   143  			So(err, ShouldBeNil)
   144  			So(len(h2t), ShouldEqual, 1)
   145  			So(len(t2h), ShouldEqual, 1)
   146  			So(t2h["task1"], ShouldEqual, "")
   147  			So(h2t["host1"], ShouldEqual, "task1")
   148  
   149  		})
   150  	})
   151  }
   152  
   153  func TestStuckHostAuditing(t *testing.T) {
   154  	Convey("With tasks and hosts inserted into the db", t, func() {
   155  		testutil.HandleTestingErr(db.Clear(host.Collection), t,
   156  			"Error clearing '%v' collection", host.Collection)
   157  		testutil.HandleTestingErr(db.Clear(task.Collection), t,
   158  			"Error clearing '%v' collection", task.Collection)
   159  		h1 := host.Host{Id: "h1", Status: evergreen.HostRunning, RunningTask: "t1"}
   160  		h2 := host.Host{Id: "h2", Status: evergreen.HostRunning, RunningTask: "t2"}
   161  		h3 := host.Host{Id: "h3", Status: evergreen.HostRunning}
   162  
   163  		So(h1.Insert(), ShouldBeNil)
   164  		So(h2.Insert(), ShouldBeNil)
   165  		So(h3.Insert(), ShouldBeNil)
   166  
   167  		t1 := task.Task{Id: "t1", Status: evergreen.TaskDispatched, HostId: h1.Id}
   168  		t2 := task.Task{Id: "t2", Status: evergreen.TaskFailed, HostId: h2.Id}
   169  		So(t1.Insert(), ShouldBeNil)
   170  		So(t2.Insert(), ShouldBeNil)
   171  
   172  		Convey("hosts with running tasks that are completed should be returned", func() {
   173  			stuckHosts, err := CheckStuckHosts()
   174  			So(err, ShouldBeNil)
   175  			So(len(stuckHosts), ShouldEqual, 1)
   176  			So(stuckHosts[0].Host, ShouldEqual, h2.Id)
   177  			So(stuckHosts[0].RunningTask, ShouldEqual, t2.Id)
   178  			So(stuckHosts[0].TaskStatus, ShouldEqual, evergreen.TaskFailed)
   179  			So(stuckHosts[0].Error(), ShouldEqual,
   180  				fmt.Sprintf("host h2 has a running task t2 with complete status %s", evergreen.TaskFailed))
   181  		})
   182  
   183  	})
   184  }