github.com/banmanh482/nomad@v0.11.8/scheduler/select_test.go (about)

     1  package scheduler
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/hashicorp/nomad/nomad/mock"
     7  	"github.com/hashicorp/nomad/nomad/structs"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  func TestLimitIterator(t *testing.T) {
    12  	_, ctx := testContext(t)
    13  	nodes := []*RankedNode{
    14  		{
    15  			Node:       mock.Node(),
    16  			FinalScore: 1,
    17  		},
    18  		{
    19  			Node:       mock.Node(),
    20  			FinalScore: 2,
    21  		},
    22  		{
    23  			Node:       mock.Node(),
    24  			FinalScore: 3,
    25  		},
    26  	}
    27  	static := NewStaticRankIterator(ctx, nodes)
    28  
    29  	limit := NewLimitIterator(ctx, static, 1, 0, 2)
    30  	limit.SetLimit(2)
    31  
    32  	out := collectRanked(limit)
    33  	if len(out) != 2 {
    34  		t.Fatalf("bad: %v", out)
    35  	}
    36  	if out[0] != nodes[0] && out[1] != nodes[1] {
    37  		t.Fatalf("bad: %v", out)
    38  	}
    39  
    40  	out = collectRanked(limit)
    41  	if len(out) != 0 {
    42  		t.Fatalf("bad: %v", out)
    43  	}
    44  	limit.Reset()
    45  
    46  	out = collectRanked(limit)
    47  	if len(out) != 2 {
    48  		t.Fatalf("bad: %v", out)
    49  	}
    50  	if out[0] != nodes[2] && out[1] != nodes[0] {
    51  		t.Fatalf("bad: %v", out)
    52  	}
    53  }
    54  
    55  func TestLimitIterator_ScoreThreshold(t *testing.T) {
    56  	_, ctx := testContext(t)
    57  	type testCase struct {
    58  		desc        string
    59  		nodes       []*RankedNode
    60  		expectedOut []*RankedNode
    61  		threshold   float64
    62  		limit       int
    63  		maxSkip     int
    64  	}
    65  
    66  	var nodes []*structs.Node
    67  	for i := 0; i < 5; i++ {
    68  		nodes = append(nodes, mock.Node())
    69  	}
    70  
    71  	testCases := []testCase{
    72  		{
    73  			desc: "Skips one low scoring node",
    74  			nodes: []*RankedNode{
    75  				{
    76  					Node:       nodes[0],
    77  					FinalScore: -1,
    78  				},
    79  				{
    80  					Node:       nodes[1],
    81  					FinalScore: 2,
    82  				},
    83  				{
    84  					Node:       nodes[2],
    85  					FinalScore: 3,
    86  				},
    87  			},
    88  			expectedOut: []*RankedNode{
    89  				{
    90  					Node:       nodes[1],
    91  					FinalScore: 2,
    92  				},
    93  				{
    94  					Node:       nodes[2],
    95  					FinalScore: 3,
    96  				},
    97  			},
    98  			threshold: -1,
    99  			limit:     2,
   100  			maxSkip:   2,
   101  		},
   102  		{
   103  			desc: "Skips maxSkip scoring nodes",
   104  			nodes: []*RankedNode{
   105  				{
   106  					Node:       nodes[0],
   107  					FinalScore: -1,
   108  				},
   109  				{
   110  					Node:       nodes[1],
   111  					FinalScore: -2,
   112  				},
   113  				{
   114  					Node:       nodes[2],
   115  					FinalScore: 3,
   116  				},
   117  				{
   118  					Node:       nodes[3],
   119  					FinalScore: 4,
   120  				},
   121  			},
   122  			expectedOut: []*RankedNode{
   123  				{
   124  					Node:       nodes[2],
   125  					FinalScore: 3,
   126  				},
   127  				{
   128  					Node:       nodes[3],
   129  					FinalScore: 4,
   130  				},
   131  			},
   132  			threshold: -1,
   133  			limit:     2,
   134  			maxSkip:   2,
   135  		},
   136  		{
   137  			desc: "maxSkip limit reached",
   138  			nodes: []*RankedNode{
   139  				{
   140  					Node:       nodes[0],
   141  					FinalScore: -1,
   142  				},
   143  				{
   144  					Node:       nodes[1],
   145  					FinalScore: -6,
   146  				},
   147  				{
   148  					Node:       nodes[2],
   149  					FinalScore: -3,
   150  				},
   151  				{
   152  					Node:       nodes[3],
   153  					FinalScore: -4,
   154  				},
   155  			},
   156  			expectedOut: []*RankedNode{
   157  				{
   158  					Node:       nodes[2],
   159  					FinalScore: -3,
   160  				},
   161  				{
   162  					Node:       nodes[3],
   163  					FinalScore: -4,
   164  				},
   165  			},
   166  			threshold: -1,
   167  			limit:     2,
   168  			maxSkip:   2,
   169  		},
   170  		{
   171  			desc: "draw both from skipped nodes",
   172  			nodes: []*RankedNode{
   173  				{
   174  					Node:       nodes[0],
   175  					FinalScore: -1,
   176  				},
   177  				{
   178  					Node:       nodes[1],
   179  					FinalScore: -6,
   180  				},
   181  			},
   182  			expectedOut: []*RankedNode{
   183  				{
   184  					Node:       nodes[0],
   185  					FinalScore: -1,
   186  				},
   187  				{
   188  					Node:       nodes[1],
   189  					FinalScore: -6,
   190  				},
   191  			},
   192  			threshold: -1,
   193  			limit:     2,
   194  			maxSkip:   2,
   195  		}, {
   196  			desc: "one node above threshold, one skipped node",
   197  			nodes: []*RankedNode{
   198  				{
   199  					Node:       nodes[0],
   200  					FinalScore: -1,
   201  				},
   202  				{
   203  					Node:       nodes[1],
   204  					FinalScore: 5,
   205  				},
   206  			},
   207  			expectedOut: []*RankedNode{
   208  				{
   209  					Node:       nodes[1],
   210  					FinalScore: 5,
   211  				},
   212  				{
   213  					Node:       nodes[0],
   214  					FinalScore: -1,
   215  				},
   216  			},
   217  			threshold: -1,
   218  			limit:     2,
   219  			maxSkip:   2,
   220  		},
   221  		{
   222  			desc: "low scoring nodes interspersed",
   223  			nodes: []*RankedNode{
   224  				{
   225  					Node:       nodes[0],
   226  					FinalScore: -1,
   227  				},
   228  				{
   229  					Node:       nodes[1],
   230  					FinalScore: 5,
   231  				},
   232  				{
   233  					Node:       nodes[2],
   234  					FinalScore: -2,
   235  				},
   236  				{
   237  					Node:       nodes[3],
   238  					FinalScore: 2,
   239  				},
   240  			},
   241  			expectedOut: []*RankedNode{
   242  				{
   243  					Node:       nodes[1],
   244  					FinalScore: 5,
   245  				},
   246  				{
   247  					Node:       nodes[3],
   248  					FinalScore: 2,
   249  				},
   250  			},
   251  			threshold: -1,
   252  			limit:     2,
   253  			maxSkip:   2,
   254  		},
   255  		{
   256  			desc: "only one node, score below threshold",
   257  			nodes: []*RankedNode{
   258  				{
   259  					Node:       nodes[0],
   260  					FinalScore: -1,
   261  				},
   262  			},
   263  			expectedOut: []*RankedNode{
   264  				{
   265  					Node:       nodes[0],
   266  					FinalScore: -1,
   267  				},
   268  			},
   269  			threshold: -1,
   270  			limit:     2,
   271  			maxSkip:   2,
   272  		},
   273  		{
   274  			desc: "maxSkip is more than available nodes",
   275  			nodes: []*RankedNode{
   276  				{
   277  					Node:       nodes[0],
   278  					FinalScore: -2,
   279  				},
   280  				{
   281  					Node:       nodes[1],
   282  					FinalScore: 1,
   283  				},
   284  			},
   285  			expectedOut: []*RankedNode{
   286  				{
   287  					Node:       nodes[1],
   288  					FinalScore: 1,
   289  				},
   290  				{
   291  					Node:       nodes[0],
   292  					FinalScore: -2,
   293  				},
   294  			},
   295  			threshold: -1,
   296  			limit:     2,
   297  			maxSkip:   10,
   298  		},
   299  	}
   300  
   301  	for _, tc := range testCases {
   302  		t.Run(tc.desc, func(t *testing.T) {
   303  			static := NewStaticRankIterator(ctx, tc.nodes)
   304  
   305  			limit := NewLimitIterator(ctx, static, 1, 0, 2)
   306  			limit.SetLimit(2)
   307  			out := collectRanked(limit)
   308  			require := require.New(t)
   309  			require.Equal(tc.expectedOut, out)
   310  
   311  			limit.Reset()
   312  			require.Equal(0, limit.skippedNodeIndex)
   313  			require.Equal(0, len(limit.skippedNodes))
   314  		})
   315  	}
   316  
   317  }
   318  
   319  func TestMaxScoreIterator(t *testing.T) {
   320  	_, ctx := testContext(t)
   321  	nodes := []*RankedNode{
   322  		{
   323  			Node:       mock.Node(),
   324  			FinalScore: 1,
   325  		},
   326  		{
   327  			Node:       mock.Node(),
   328  			FinalScore: 2,
   329  		},
   330  		{
   331  			Node:       mock.Node(),
   332  			FinalScore: 3,
   333  		},
   334  	}
   335  	static := NewStaticRankIterator(ctx, nodes)
   336  
   337  	max := NewMaxScoreIterator(ctx, static)
   338  
   339  	out := collectRanked(max)
   340  	if len(out) != 1 {
   341  		t.Fatalf("bad: %v", out)
   342  	}
   343  	if out[0] != nodes[2] {
   344  		t.Fatalf("bad: %v", out)
   345  	}
   346  
   347  	out = collectRanked(max)
   348  	if len(out) != 0 {
   349  		t.Fatalf("bad: %v", out)
   350  	}
   351  	max.Reset()
   352  
   353  	out = collectRanked(max)
   354  	if len(out) != 1 {
   355  		t.Fatalf("bad: %v", out)
   356  	}
   357  	if out[0] != nodes[2] {
   358  		t.Fatalf("bad: %v", out)
   359  	}
   360  }