1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
10 "github.com/sirupsen/logrus"
14 var _ = Suite(&SqueueSuite{})
16 type SqueueSuite struct{}
18 func (s *SqueueSuite) TestReleasePending(c *C) {
20 "zzzzz-dz642-fake0fake0fake0",
21 "zzzzz-dz642-fake1fake1fake1",
22 "zzzzz-dz642-fake2fake2fake2",
25 queue: uuids[0] + " 10000 4294000000 PENDING Resources\n" + uuids[1] + " 10000 4294000111 PENDING Resources\n" + uuids[2] + " 10000 0 PENDING BadConstraints\n",
27 sqc := &SqueueChecker{
28 Logger: logrus.StandardLogger(),
32 sqc.startOnce.Do(sqc.start)
35 done := make(chan struct{})
37 for _, u := range uuids {
42 callUntilReady(sqc.check, done)
44 slurm.didRelease = nil
46 c.Check(slurm.didRelease, DeepEquals, []string{uuids[2]})
49 func (s *SqueueSuite) TestReniceAll(c *C) {
50 uuids := []string{"zzzzz-dz642-fake0fake0fake0", "zzzzz-dz642-fake1fake1fake1", "zzzzz-dz642-fake2fake2fake2"}
51 for _, test := range []struct {
59 squeue: uuids[0] + " 10000 4294000000 PENDING Resources\n",
60 want: map[string]int64{uuids[0]: 1},
61 expect: [][]string{{uuids[0], "0"}},
63 { // fake0 priority is too high
65 squeue: uuids[0] + " 10000 4294000777 PENDING Resources\n" + uuids[1] + " 10000 4294000444 PENDING Resources\n",
66 want: map[string]int64{uuids[0]: 1, uuids[1]: 999},
67 expect: [][]string{{uuids[1], "0"}, {uuids[0], "334"}},
71 squeue: uuids[0] + " 10000 4294000777 PENDING Resources\n" + uuids[1] + " 10000 4294000444 PENDING Resources\n",
72 want: map[string]int64{uuids[0]: 1, uuids[1]: 999},
73 expect: [][]string{{uuids[1], "0"}, {uuids[0], "433"}},
75 { // ignore fake2 because SetPriority() not called
77 squeue: uuids[0] + " 10000 4294000000 PENDING Resources\n" + uuids[1] + " 10000 4294000111 PENDING Resources\n" + uuids[2] + " 10000 4294000222 PENDING Resources\n",
78 want: map[string]int64{uuids[0]: 999, uuids[1]: 1},
79 expect: [][]string{{uuids[0], "0"}, {uuids[1], "112"}},
81 { // ignore fake2 because slurm priority=0
83 squeue: uuids[0] + " 10000 4294000000 PENDING Resources\n" + uuids[1] + " 10000 4294000111 PENDING Resources\n" + uuids[2] + " 10000 0 PENDING Resources\n",
84 want: map[string]int64{uuids[0]: 999, uuids[1]: 1, uuids[2]: 997},
85 expect: [][]string{{uuids[0], "0"}, {uuids[1], "112"}},
88 c.Logf("spread=%d squeue=%q want=%v -> expect=%v", test.spread, test.squeue, test.want, test.expect)
92 sqc := &SqueueChecker{
93 Logger: logrus.StandardLogger(),
95 PrioritySpread: test.spread,
98 sqc.startOnce.Do(sqc.start)
100 for uuid, pri := range test.want {
101 sqc.SetPriority(uuid, pri)
104 c.Check(slurm.didRenice, DeepEquals, test.expect)
109 // If a limited nice range prevents desired priority adjustments, give
110 // up and clamp nice to 10K.
111 func (s *SqueueSuite) TestReniceInvalidNiceValue(c *C) {
112 uuids := []string{"zzzzz-dz642-fake0fake0fake0", "zzzzz-dz642-fake1fake1fake1", "zzzzz-dz642-fake2fake2fake2"}
114 queue: uuids[0] + " 0 4294000222 PENDING Resources\n" + uuids[1] + " 0 4294555222 PENDING Resources\n",
117 sqc := &SqueueChecker{
118 Logger: logrus.StandardLogger(),
123 sqc.startOnce.Do(sqc.start)
125 sqc.SetPriority(uuids[0], 2)
126 sqc.SetPriority(uuids[1], 1)
128 // First attempt should renice to 555001, which will fail
130 c.Check(slurm.didRenice, DeepEquals, [][]string{{uuids[1], "555001"}})
132 // Next attempt should renice to 10K, which will succeed
134 c.Check(slurm.didRenice, DeepEquals, [][]string{{uuids[1], "555001"}, {uuids[1], "10000"}})
135 // ...so we'll change the squeue response to reflect the
136 // updated priority+nice, and make sure sqc sees that...
137 slurm.queue = uuids[0] + " 0 4294000222 PENDING Resources\n" + uuids[1] + " 10000 4294545222 PENDING Resources\n"
140 // Next attempt should leave nice alone because it's already
143 c.Check(slurm.didRenice, DeepEquals, [][]string{{uuids[1], "555001"}, {uuids[1], "10000"}})
145 // Back to normal if desired nice value falls below 10K
146 slurm.queue = uuids[0] + " 0 4294000222 PENDING Resources\n" + uuids[1] + " 10000 4294000111 PENDING Resources\n"
149 c.Check(slurm.didRenice, DeepEquals, [][]string{{uuids[1], "555001"}, {uuids[1], "10000"}, {uuids[1], "9890"}})
154 // If the given UUID isn't in the slurm queue yet, SetPriority()
155 // should wait for it to appear on the very next poll, then give up.
156 func (s *SqueueSuite) TestSetPriorityBeforeQueued(c *C) {
157 uuidGood := "zzzzz-dz642-fake0fake0fake0"
158 uuidBad := "zzzzz-dz642-fake1fake1fake1"
160 slurm := &slurmFake{}
161 sqc := &SqueueChecker{
162 Logger: logrus.StandardLogger(),
166 sqc.startOnce.Do(sqc.start)
170 done := make(chan struct{})
172 sqc.SetPriority(uuidGood, 123)
173 sqc.SetPriority(uuidBad, 345)
176 c.Check(sqc.queue[uuidGood], IsNil)
177 c.Check(sqc.queue[uuidBad], IsNil)
178 timeout := time.NewTimer(time.Second)
180 tick := time.NewTicker(time.Millisecond)
185 slurm.queue = uuidGood + " 0 12345 PENDING Resources\n"
188 // Avoid immediately selecting this case again
189 // on the next iteration if check() took
190 // longer than one tick.
198 c.Assert(sqc.queue[uuidGood], NotNil)
199 c.Check(sqc.queue[uuidGood].wantPriority, Equals, int64(123))
200 c.Check(sqc.queue[uuidBad], IsNil)
206 func callUntilReady(fn func(), done <-chan struct{}) {
207 tick := time.NewTicker(time.Millisecond)