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  }