github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/scheduler/deficit_based_host_allocator_test.go (about) 1 package scheduler 2 3 import ( 4 "testing" 5 6 "github.com/evergreen-ci/evergreen/db" 7 "github.com/evergreen-ci/evergreen/model" 8 "github.com/evergreen-ci/evergreen/model/distro" 9 "github.com/evergreen-ci/evergreen/model/host" 10 "github.com/evergreen-ci/evergreen/testutil" 11 "github.com/mongodb/grip" 12 . "github.com/smartystreets/goconvey/convey" 13 ) 14 15 func init() { 16 db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(hostAllocatorTestConf)) 17 grip.CatchError(grip.SetSender(testutil.SetupTestSender(hostAllocatorTestConf.Scheduler.LogFile))) 18 } 19 20 func TestDeficitBasedHostAllocator(t *testing.T) { 21 var taskIds []string 22 var runningTaskIds []string 23 var hostIds []string 24 var dist distro.Distro 25 var hostAllocator *DeficitBasedHostAllocator 26 27 Convey("With a deficit based host allocator,"+ 28 " determining the number of new hosts to spin up...", t, func() { 29 30 hostAllocator = &DeficitBasedHostAllocator{} 31 taskIds = []string{"t1", "t2", "t3", "t4", "t5"} 32 runningTaskIds = []string{"t1", "t2", "t3", "t4", "t5"} 33 hostIds = []string{"h1", "h2", "h3", "h4", "h5"} 34 dist = distro.Distro{Provider: "ec2"} 35 36 Convey("if there are no tasks to run, no new hosts should be needed", 37 func() { 38 hosts := []host.Host{ 39 {Id: hostIds[0]}, 40 {Id: hostIds[1]}, 41 {Id: hostIds[2]}, 42 } 43 dist.PoolSize = len(hosts) + 5 44 45 hostAllocatorData := &HostAllocatorData{ 46 existingDistroHosts: map[string][]host.Host{ 47 "": hosts, 48 }, 49 distros: map[string]distro.Distro{ 50 "": dist, 51 }, 52 } 53 54 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, 55 dist, hostAllocatorTestConf), ShouldEqual, 0) 56 }) 57 58 Convey("if the number of existing hosts equals the max hosts, no new"+ 59 " hosts can be spawned", func() { 60 taskQueueItems := []model.TaskQueueItem{ 61 {Id: taskIds[0]}, 62 {Id: taskIds[1]}, 63 {Id: taskIds[2]}, 64 {Id: taskIds[3]}, 65 } 66 dist.PoolSize = 0 67 68 hostAllocatorData := &HostAllocatorData{ 69 existingDistroHosts: map[string][]host.Host{}, 70 distros: map[string]distro.Distro{ 71 "": dist, 72 }, 73 } 74 75 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 76 ShouldEqual, 0) 77 hosts := []host.Host{ 78 {Id: hostIds[0]}, 79 } 80 dist.PoolSize = len(hosts) 81 82 hostAllocatorData = &HostAllocatorData{ 83 taskQueueItems: map[string][]model.TaskQueueItem{ 84 "": taskQueueItems, 85 }, 86 existingDistroHosts: map[string][]host.Host{ 87 "": hosts, 88 }, 89 distros: map[string]distro.Distro{ 90 "": dist, 91 }, 92 } 93 94 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 95 ShouldEqual, 0) 96 }) 97 98 Convey("if the number of existing hosts exceeds the max hosts, no new"+ 99 " hosts can be spawned", func() { 100 101 taskQueueItems := []model.TaskQueueItem{ 102 {Id: taskIds[0]}, 103 {Id: taskIds[1]}, 104 {Id: taskIds[2]}, 105 {Id: taskIds[3]}, 106 } 107 hosts := []host.Host{ 108 {Id: hostIds[0]}, 109 {Id: hostIds[1]}, 110 } 111 dist.PoolSize = 1 112 113 hostAllocatorData := &HostAllocatorData{ 114 taskQueueItems: map[string][]model.TaskQueueItem{ 115 "": taskQueueItems, 116 }, 117 existingDistroHosts: map[string][]host.Host{ 118 "": hosts, 119 }, 120 distros: map[string]distro.Distro{ 121 "": dist, 122 }, 123 } 124 125 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 126 ShouldEqual, 0) 127 }) 128 129 Convey("if the number of tasks to run is less than the number of free"+ 130 " hosts, no new hosts are needed", func() { 131 taskQueueItems := []model.TaskQueueItem{ 132 {Id: taskIds[0]}, 133 {Id: taskIds[1]}, 134 } 135 hosts := []host.Host{ 136 {Id: hostIds[0]}, 137 {Id: hostIds[1], RunningTask: runningTaskIds[0]}, 138 {Id: hostIds[2]}, 139 {Id: hostIds[3]}, 140 } 141 dist.PoolSize = len(hosts) + 5 142 143 hostAllocatorData := &HostAllocatorData{ 144 taskQueueItems: map[string][]model.TaskQueueItem{ 145 "": taskQueueItems, 146 }, 147 existingDistroHosts: map[string][]host.Host{ 148 "": hosts, 149 }, 150 distros: map[string]distro.Distro{ 151 "": dist, 152 }, 153 } 154 155 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 156 ShouldEqual, 0) 157 158 }) 159 160 Convey("if the number of tasks to run is equal to the number of free"+ 161 " hosts, no new hosts are needed", func() { 162 taskQueueItems := []model.TaskQueueItem{ 163 {Id: taskIds[0]}, 164 {Id: taskIds[1]}, 165 } 166 hosts := []host.Host{ 167 {Id: hostIds[0]}, 168 {Id: hostIds[1], RunningTask: runningTaskIds[0]}, 169 {Id: hostIds[2], RunningTask: runningTaskIds[1]}, 170 {Id: hostIds[3]}, 171 } 172 dist.PoolSize = len(hosts) + 5 173 174 hostAllocatorData := &HostAllocatorData{ 175 taskQueueItems: map[string][]model.TaskQueueItem{ 176 "": taskQueueItems, 177 }, 178 existingDistroHosts: map[string][]host.Host{ 179 "": hosts, 180 }, 181 distros: map[string]distro.Distro{ 182 "": dist, 183 }, 184 } 185 186 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 187 ShouldEqual, 0) 188 }) 189 190 Convey("if the number of tasks to run exceeds the number of free"+ 191 " hosts, new hosts are needed up to the maximum allowed for the"+ 192 " distro", func() { 193 taskQueueItems := []model.TaskQueueItem{ 194 {Id: taskIds[0]}, 195 {Id: taskIds[1]}, 196 {Id: taskIds[2]}, 197 {Id: taskIds[3]}, 198 {Id: taskIds[4]}, 199 } 200 hosts := []host.Host{ 201 {Id: hostIds[0]}, 202 {Id: hostIds[1], RunningTask: runningTaskIds[0]}, 203 {Id: hostIds[2], RunningTask: runningTaskIds[1]}, 204 {Id: hostIds[3]}, 205 {Id: hostIds[4], RunningTask: runningTaskIds[2]}, 206 } 207 dist.PoolSize = 9 208 209 hostAllocatorData := &HostAllocatorData{ 210 taskQueueItems: map[string][]model.TaskQueueItem{ 211 "": taskQueueItems, 212 }, 213 existingDistroHosts: map[string][]host.Host{ 214 "": hosts, 215 }, 216 distros: map[string]distro.Distro{ 217 "": dist, 218 }, 219 } 220 221 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 222 ShouldEqual, 3) 223 224 dist.PoolSize = 8 225 hostAllocatorData = &HostAllocatorData{ 226 taskQueueItems: map[string][]model.TaskQueueItem{ 227 "": taskQueueItems, 228 }, 229 existingDistroHosts: map[string][]host.Host{ 230 "": hosts, 231 }, 232 distros: map[string]distro.Distro{ 233 "": dist, 234 }, 235 } 236 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 237 ShouldEqual, 3) 238 dist.PoolSize = 7 239 hostAllocatorData = &HostAllocatorData{ 240 taskQueueItems: map[string][]model.TaskQueueItem{ 241 "": taskQueueItems, 242 }, 243 existingDistroHosts: map[string][]host.Host{ 244 "": hosts, 245 }, 246 distros: map[string]distro.Distro{ 247 "": dist, 248 }, 249 } 250 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 251 ShouldEqual, 2) 252 dist.PoolSize = 6 253 hostAllocatorData = &HostAllocatorData{ 254 taskQueueItems: map[string][]model.TaskQueueItem{ 255 "": taskQueueItems, 256 }, 257 existingDistroHosts: map[string][]host.Host{ 258 "": hosts, 259 }, 260 distros: map[string]distro.Distro{ 261 "": dist, 262 }, 263 } 264 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 265 ShouldEqual, 1) 266 }) 267 268 Convey("if the distro cannot be used to spawn hosts, then no new hosts"+ 269 " can be spawned", func() { 270 hosts := []host.Host{ 271 {Id: hostIds[0]}, 272 } 273 taskQueueItems := []model.TaskQueueItem{ 274 {Id: taskIds[0]}, 275 {Id: taskIds[1]}, 276 {Id: taskIds[2]}, 277 } 278 dist.PoolSize = 20 279 dist.Provider = "static" 280 hostAllocatorData := &HostAllocatorData{ 281 taskQueueItems: map[string][]model.TaskQueueItem{ 282 "": taskQueueItems, 283 }, 284 existingDistroHosts: map[string][]host.Host{ 285 "": hosts, 286 }, 287 distros: map[string]distro.Distro{ 288 "": dist, 289 }, 290 } 291 So(hostAllocator.numNewHostsForDistro(hostAllocatorData, dist, hostAllocatorTestConf), 292 ShouldEqual, 0) 293 }) 294 295 }) 296 297 }