testing: migrate nomad/scheduler off of testify (#25968)

In the spirit of #25909, this PR removes testify dependencies from the scheduler
package, along with reflect.DeepEqual removal. This is again a combination of
semgrep and hx editing magic.

---------

Co-authored-by: Tim Gross <tgross@hashicorp.com>
This commit is contained in:
Piotr Kazmierczak
2025-06-04 09:29:28 +02:00
committed by GitHub
parent 34e96932a1
commit 648bacda77
18 changed files with 1306 additions and 1443 deletions

View File

@@ -29,3 +29,4 @@ rules:
paths: paths:
include: include:
- "nomad/state/*_test.go" - "nomad/state/*_test.go"
- "nomad/scheduler/*_test.go"

View File

@@ -4,11 +4,11 @@
package scheduler package scheduler
import ( import (
"reflect"
"testing" "testing"
"github.com/hashicorp/nomad/ci" "github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/test/must"
) )
func TestAnnotateTaskGroup_Updates(t *testing.T) { func TestAnnotateTaskGroup_Updates(t *testing.T) {
@@ -50,9 +50,8 @@ func TestAnnotateTaskGroup_Updates(t *testing.T) {
t.Fatalf("annotateTaskGroup(%#v, %#v) failed: %#v", tgDiff, annotations, err) t.Fatalf("annotateTaskGroup(%#v, %#v) failed: %#v", tgDiff, annotations, err)
} }
if !reflect.DeepEqual(tgDiff, expected) { must.Eq(t, expected, tgDiff)
t.Fatalf("got %#v, want %#v", tgDiff, expected)
}
} }
func TestAnnotateCountChange_NonEdited(t *testing.T) { func TestAnnotateCountChange_NonEdited(t *testing.T) {
@@ -61,9 +60,8 @@ func TestAnnotateCountChange_NonEdited(t *testing.T) {
tg := &structs.TaskGroupDiff{} tg := &structs.TaskGroupDiff{}
tgOrig := &structs.TaskGroupDiff{} tgOrig := &structs.TaskGroupDiff{}
annotateCountChange(tg) annotateCountChange(tg)
if !reflect.DeepEqual(tgOrig, tg) { must.Eq(t, tgOrig, tg)
t.Fatalf("annotateCountChange(%#v) should not have caused any annotation: %#v", tgOrig, tg)
}
} }
func TestAnnotateCountChange(t *testing.T) { func TestAnnotateCountChange(t *testing.T) {
@@ -116,9 +114,8 @@ func TestAnnotateTask_NonEdited(t *testing.T) {
td := &structs.TaskDiff{Type: structs.DiffTypeNone} td := &structs.TaskDiff{Type: structs.DiffTypeNone}
tdOrig := &structs.TaskDiff{Type: structs.DiffTypeNone} tdOrig := &structs.TaskDiff{Type: structs.DiffTypeNone}
annotateTask(td, tgd) annotateTask(td, tgd)
if !reflect.DeepEqual(tdOrig, td) { must.Eq(t, tdOrig, td)
t.Fatalf("annotateTask(%#v) should not have caused any annotation: %#v", tdOrig, td)
}
} }
func TestAnnotateTask(t *testing.T) { func TestAnnotateTask(t *testing.T) {

View File

@@ -16,7 +16,7 @@ import (
"github.com/hashicorp/nomad/helper/raftutil" "github.com/hashicorp/nomad/helper/raftutil"
"github.com/hashicorp/nomad/scheduler" "github.com/hashicorp/nomad/scheduler"
"github.com/stretchr/testify/require" "github.com/shoenig/test/must"
) )
// NewBenchmarkingHarness creates a starting test harness with state // NewBenchmarkingHarness creates a starting test harness with state
@@ -30,13 +30,13 @@ func NewBenchmarkingHarness(t testing.TB) *scheduler.Harness {
datadir := os.Getenv("NOMAD_BENCHMARK_DATADIR") datadir := os.Getenv("NOMAD_BENCHMARK_DATADIR")
if datadir != "" { if datadir != "" {
h, err := NewHarnessFromDataDir(t, datadir) h, err := NewHarnessFromDataDir(t, datadir)
require.NoError(t, err) must.NoError(t, err)
return h return h
} else { } else {
snapshotPath := os.Getenv("NOMAD_BENCHMARK_SNAPSHOT") snapshotPath := os.Getenv("NOMAD_BENCHMARK_SNAPSHOT")
if snapshotPath != "" { if snapshotPath != "" {
h, err := NewHarnessFromSnapshot(t, snapshotPath) h, err := NewHarnessFromSnapshot(t, snapshotPath)
require.NoError(t, err) must.NoError(t, err)
return h return h
} }
} }

View File

@@ -16,7 +16,6 @@ import (
"github.com/hashicorp/nomad/nomad/state" "github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/test/must" "github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
) )
func testContext(t testing.TB) (*state.StateStore, *EvalContext) { func testContext(t testing.TB) (*state.StateStore, *EvalContext) {
@@ -160,9 +159,9 @@ func TestEvalContext_ProposedAlloc(t *testing.T) {
ClientStatus: structs.AllocClientStatusPending, ClientStatus: structs.AllocClientStatusPending,
TaskGroup: "web", TaskGroup: "web",
} }
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID))) must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
// Add a planned eviction to alloc1 // Add a planned eviction to alloc1
plan := ctx.Plan() plan := ctx.Plan()
@@ -299,10 +298,10 @@ func TestEvalContext_ProposedAlloc_EvictPreempt(t *testing.T) {
ClientStatus: structs.AllocClientStatusPending, ClientStatus: structs.AllocClientStatusPending,
TaskGroup: "web", TaskGroup: "web",
} }
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(allocEvict.JobID))) must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(allocEvict.JobID)))
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPreempt.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPreempt.JobID)))
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPropose.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(allocPropose.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{allocEvict, allocPreempt, allocPropose})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{allocEvict, allocPreempt, allocPropose}))
// Plan to evict one alloc and preempt another // Plan to evict one alloc and preempt another
plan := ctx.Plan() plan := ctx.Plan()
@@ -310,8 +309,8 @@ func TestEvalContext_ProposedAlloc_EvictPreempt(t *testing.T) {
plan.NodeUpdate[nodes[0].Node.ID] = []*structs.Allocation{allocPreempt} plan.NodeUpdate[nodes[0].Node.ID] = []*structs.Allocation{allocPreempt}
proposed, err := ctx.ProposedAllocs(nodes[0].Node.ID) proposed, err := ctx.ProposedAllocs(nodes[0].Node.ID)
require.NoError(t, err) must.NoError(t, err)
require.Len(t, proposed, 1) must.SliceLen(t, 1, proposed)
} }
func TestEvalEligibility_JobStatus(t *testing.T) { func TestEvalEligibility_JobStatus(t *testing.T) {
@@ -431,7 +430,7 @@ func TestEvalEligibility_GetClasses(t *testing.T) {
} }
actClasses := e.GetClasses() actClasses := e.GetClasses()
require.Equal(t, expClasses, actClasses) must.Eq(t, expClasses, actClasses)
} }
func TestEvalEligibility_GetClasses_JobEligible_TaskGroupIneligible(t *testing.T) { func TestEvalEligibility_GetClasses_JobEligible_TaskGroupIneligible(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
@@ -455,7 +454,7 @@ func TestEvalEligibility_GetClasses_JobEligible_TaskGroupIneligible(t *testing.T
} }
actClasses := e.GetClasses() actClasses := e.GetClasses()
require.Equal(t, expClasses, actClasses) must.Eq(t, expClasses, actClasses)
} }
func TestPortCollisionEvent_Copy(t *testing.T) { func TestPortCollisionEvent_Copy(t *testing.T) {
@@ -503,6 +502,6 @@ func TestPortCollisionEvent_Sanitize(t *testing.T) {
} }
cleanEv := ev.Sanitize() cleanEv := ev.Sanitize()
require.Empty(t, cleanEv.Node.SecretID) must.Eq(t, "", cleanEv.Node.SecretID)
require.Nil(t, cleanEv.Allocations[0].Job) must.Nil(t, cleanEv.Allocations[0].Job)
} }

View File

@@ -14,7 +14,6 @@ import (
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
psstructs "github.com/hashicorp/nomad/plugins/shared/structs" psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
"github.com/shoenig/test/must" "github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
) )
func anyMemoryNodeMatcher() *memoryNodeMatcher { func anyMemoryNodeMatcher() *memoryNodeMatcher {
@@ -103,68 +102,64 @@ func collectInstanceIDs(devices ...*structs.NodeDeviceResource) []string {
func TestDeviceAllocator_Allocate_GenericRequest(t *testing.T) { func TestDeviceAllocator_Allocate_GenericRequest(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
require := require.New(t)
_, ctx := testContext(t) _, ctx := testContext(t)
n := devNode() n := devNode()
d := newDeviceAllocator(ctx, n) d := newDeviceAllocator(ctx, n)
require.NotNil(d) must.NotNil(t, d)
// Build the request // Build the request
ask := deviceRequest("gpu", 1, nil, nil) ask := deviceRequest("gpu", 1, nil, nil)
mem := anyMemoryNodeMatcher() mem := anyMemoryNodeMatcher()
out, score, err := d.createOffer(mem, ask) out, score, err := d.createOffer(mem, ask)
require.NotNil(out) must.NotNil(t, out)
require.Zero(score) must.Zero(t, score)
require.NoError(err) must.NoError(t, err)
// Check that we got the nvidia device // Check that we got the nvidia device
require.Len(out.DeviceIDs, 1) must.SliceLen(t, 1, out.DeviceIDs)
require.Contains(collectInstanceIDs(n.NodeResources.Devices[0]), out.DeviceIDs[0]) must.SliceContains(t, collectInstanceIDs(n.NodeResources.Devices[0]), out.DeviceIDs[0])
} }
// Test that asking for a device that is fully specified works. // Test that asking for a device that is fully specified works.
func TestDeviceAllocator_Allocate_FullyQualifiedRequest(t *testing.T) { func TestDeviceAllocator_Allocate_FullyQualifiedRequest(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
require := require.New(t)
_, ctx := testContext(t) _, ctx := testContext(t)
n := devNode() n := devNode()
d := newDeviceAllocator(ctx, n) d := newDeviceAllocator(ctx, n)
require.NotNil(d) must.NotNil(t, d)
// Build the request // Build the request
ask := deviceRequest("intel/fpga/F100", 1, nil, nil) ask := deviceRequest("intel/fpga/F100", 1, nil, nil)
mem := anyMemoryNodeMatcher() mem := anyMemoryNodeMatcher()
out, score, err := d.createOffer(mem, ask) out, score, err := d.createOffer(mem, ask)
require.NotNil(out) must.NotNil(t, out)
require.Zero(score) must.Zero(t, score)
require.NoError(err) must.NoError(t, err)
// Check that we got the nvidia device // Check that we got the nvidia device
require.Len(out.DeviceIDs, 1) must.SliceLen(t, 1, out.DeviceIDs)
require.Contains(collectInstanceIDs(n.NodeResources.Devices[1]), out.DeviceIDs[0]) must.SliceContains(t, collectInstanceIDs(n.NodeResources.Devices[1]), out.DeviceIDs[0])
} }
// Test that asking for a device with too much count doesn't place // Test that asking for a device with too much count doesn't place
func TestDeviceAllocator_Allocate_NotEnoughInstances(t *testing.T) { func TestDeviceAllocator_Allocate_NotEnoughInstances(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
require := require.New(t)
_, ctx := testContext(t) _, ctx := testContext(t)
n := devNode() n := devNode()
d := newDeviceAllocator(ctx, n) d := newDeviceAllocator(ctx, n)
require.NotNil(d) must.NotNil(t, d)
// Build the request // Build the request
ask := deviceRequest("gpu", 4, nil, nil) ask := deviceRequest("gpu", 4, nil, nil)
mem := anyMemoryNodeMatcher() mem := anyMemoryNodeMatcher()
out, _, err := d.createOffer(mem, ask) out, _, err := d.createOffer(mem, ask)
require.Nil(out) must.Nil(t, out)
require.Error(err) must.ErrorContains(t, err, "no devices match request")
require.Contains(err.Error(), "no devices match request")
} }
func TestDeviceAllocator_Allocate_NUMA_available(t *testing.T) { func TestDeviceAllocator_Allocate_NUMA_available(t *testing.T) {
@@ -338,14 +333,14 @@ func TestDeviceAllocator_Allocate_Constraints(t *testing.T) {
mem := anyMemoryNodeMatcher() mem := anyMemoryNodeMatcher()
out, score, err := d.createOffer(mem, ask) out, score, err := d.createOffer(mem, ask)
if c.NoPlacement { if c.NoPlacement {
require.Nil(t, out) must.Nil(t, out)
} else { } else {
must.NotNil(t, out) must.NotNil(t, out)
must.Zero(t, score) must.Zero(t, score)
must.NoError(t, err) must.NoError(t, err)
// Check that we got the right nvidia device instance, and // Check that we got the right nvidia device instance, and
// specific device instance IDs if required // specific device instance IDs if mustd
must.Len(t, 1, out.DeviceIDs) must.Len(t, 1, out.DeviceIDs)
must.SliceContains(t, collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0]) must.SliceContains(t, collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0])
must.SliceContainsSubset(t, c.ExpectedDeviceIDs, out.DeviceIDs) must.SliceContainsSubset(t, c.ExpectedDeviceIDs, out.DeviceIDs)
@@ -434,27 +429,26 @@ func TestDeviceAllocator_Allocate_Affinities(t *testing.T) {
for _, c := range cases { for _, c := range cases {
t.Run(c.Name, func(t *testing.T) { t.Run(c.Name, func(t *testing.T) {
require := require.New(t)
_, ctx := testContext(t) _, ctx := testContext(t)
d := newDeviceAllocator(ctx, n) d := newDeviceAllocator(ctx, n)
require.NotNil(d) must.NotNil(t, d)
// Build the request // Build the request
ask := deviceRequest(c.Name, 1, nil, c.Affinities) ask := deviceRequest(c.Name, 1, nil, c.Affinities)
mem := anyMemoryNodeMatcher() mem := anyMemoryNodeMatcher()
out, score, err := d.createOffer(mem, ask) out, score, err := d.createOffer(mem, ask)
require.NotNil(out) must.NotNil(t, out)
require.NoError(err) must.NoError(t, err)
if c.ZeroScore { if c.ZeroScore {
require.Zero(score) must.Zero(t, score)
} else { } else {
require.NotZero(score) must.NonZero(t, score)
} }
// Check that we got the nvidia device // Check that we got the nvidia device
require.Len(out.DeviceIDs, 1) must.SliceLen(t, 1, out.DeviceIDs)
require.Contains(collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0]) must.SliceContains(t, collectInstanceIDs(c.ExpectedDevice), out.DeviceIDs[0])
}) })
} }
} }

View File

@@ -5,7 +5,6 @@ package scheduler
import ( import (
"fmt" "fmt"
"reflect"
"testing" "testing"
"time" "time"
@@ -64,9 +63,8 @@ func TestStaticIterator_SetNodes(t *testing.T) {
static.SetNodes(newNodes) static.SetNodes(newNodes)
out := collectFeasible(static) out := collectFeasible(static)
if !reflect.DeepEqual(out, newNodes) { must.Eq(t, newNodes, out)
t.Fatalf("bad: %#v", out)
}
} }
func TestRandomIterator(t *testing.T) { func TestRandomIterator(t *testing.T) {
@@ -86,9 +84,8 @@ func TestRandomIterator(t *testing.T) {
if len(out) != len(nodes) { if len(out) != len(nodes) {
t.Fatalf("missing nodes") t.Fatalf("missing nodes")
} }
if reflect.DeepEqual(out, nodes) { must.NotEq(t, nodes, out)
t.Fatalf("same order")
}
} }
func TestHostVolumeChecker_Static(t *testing.T) { func TestHostVolumeChecker_Static(t *testing.T) {
@@ -1360,7 +1357,7 @@ func TestResolveConstraintTarget(t *testing.T) {
type tcase struct { type tcase struct {
target string target string
node *structs.Node node *structs.Node
val interface{} val string
result bool result bool
} }
node := mock.Node() node := mock.Node()
@@ -1422,11 +1419,9 @@ func TestResolveConstraintTarget(t *testing.T) {
for _, tc := range cases { for _, tc := range cases {
res, ok := resolveTarget(tc.target, tc.node) res, ok := resolveTarget(tc.target, tc.node)
if ok != tc.result { must.Eq(t, ok, tc.result)
t.Fatalf("TC: %#v, Result: %v %v", tc, res, ok) if ok {
} must.Eq(t, res, tc.val)
if ok && !reflect.DeepEqual(res, tc.val) {
t.Fatalf("TC: %#v, Result: %v %v", tc, res, ok)
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ import (
"github.com/hashicorp/nomad/client/lib/numalib" "github.com/hashicorp/nomad/client/lib/numalib"
"github.com/hashicorp/nomad/client/lib/numalib/hw" "github.com/hashicorp/nomad/client/lib/numalib/hw"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/stretchr/testify/require" "github.com/shoenig/test/must"
) )
func TestCoreSelectorSelect(t *testing.T) { func TestCoreSelectorSelect(t *testing.T) {
@@ -46,7 +46,7 @@ func TestCoreSelectorSelect(t *testing.T) {
GuessSpeed: 0, GuessSpeed: 0,
} }
} }
require.Equal(t, coreIds, []uint16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}) must.Eq(t, []uint16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}, coreIds)
selector := &coreSelector{ selector := &coreSelector{
topology: &numalib.Topology{ topology: &numalib.Topology{
@@ -88,8 +88,8 @@ func TestCoreSelectorSelect(t *testing.T) {
} { } {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
ids, mhz := selector.Select(test.resources) ids, mhz := selector.Select(test.resources)
require.Equal(t, test.expectedIds, ids) must.Eq(t, test.expectedIds, ids)
require.Equal(t, test.expectedMhz, mhz) must.Eq(t, test.expectedMhz, mhz)
}) })
} }
} }

View File

@@ -5,18 +5,15 @@ package scheduler
import ( import (
"fmt" "fmt"
"maps"
"strconv" "strconv"
"testing" "testing"
"github.com/hashicorp/nomad/ci" "github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/lib/numalib"
"github.com/hashicorp/nomad/client/lib/numalib/hw"
"github.com/hashicorp/nomad/helper/uuid" "github.com/hashicorp/nomad/helper/uuid"
"github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
psstructs "github.com/hashicorp/nomad/plugins/shared/structs" psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
"github.com/stretchr/testify/require" "github.com/shoenig/test/must"
) )
func TestResourceDistance(t *testing.T) { func TestResourceDistance(t *testing.T) {
@@ -140,80 +137,14 @@ func TestResourceDistance(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run("", func(t *testing.T) { t.Run("", func(t *testing.T) {
require := require.New(t)
actualDistance := fmt.Sprintf("%3.3f", basicResourceDistance(resourceAsk, tc.allocResource)) actualDistance := fmt.Sprintf("%3.3f", basicResourceDistance(resourceAsk, tc.allocResource))
require.Equal(tc.expectedDistance, actualDistance) must.Eq(t, tc.expectedDistance, actualDistance)
}) })
} }
} }
func makeNodeResources(devices []*structs.NodeDeviceResource, busAssociativity map[string]hw.NodeID) *structs.NodeResources {
makeCore := func(node hw.NodeID, id hw.CoreID) numalib.Core {
sockets := map[hw.NodeID]hw.SocketID{
0: 0,
1: 0,
2: 1,
3: 1,
}
return numalib.Core{
NodeID: node,
SocketID: sockets[node],
ID: id,
Grade: numalib.Performance,
BaseSpeed: 4000,
}
}
// 2 socket, 4 numa node system, 2 cores per node
processors := structs.NodeProcessorResources{
Topology: &numalib.Topology{
Nodes: []uint8{0, 1, 2, 3},
Distances: numalib.SLIT{
[]numalib.Cost{10, 12, 32, 32},
[]numalib.Cost{12, 10, 32, 32},
[]numalib.Cost{32, 32, 10, 12},
[]numalib.Cost{32, 32, 12, 10},
},
Cores: []numalib.Core{
makeCore(0, 0),
makeCore(0, 1),
makeCore(1, 2),
makeCore(1, 3),
makeCore(2, 4),
makeCore(2, 5),
makeCore(3, 6),
makeCore(3, 7),
},
},
}
defaultNodeResources := &structs.NodeResources{
Processors: processors,
Memory: structs.NodeMemoryResources{
MemoryMB: 8192,
},
Disk: structs.NodeDiskResources{
DiskMB: 100 * 1024,
},
Networks: []*structs.NetworkResource{
{
Device: "eth0",
CIDR: "192.168.0.100/32",
MBits: 1000,
},
},
Devices: devices,
}
defaultNodeResources.Compatibility()
defaultNodeResources.Processors.Topology.BusAssociativity = maps.Clone(busAssociativity)
return defaultNodeResources
}
func makeDeviceInstance(instanceID, busID string) *structs.NodeDevice { func makeDeviceInstance(instanceID, busID string) *structs.NodeDevice {
return &structs.NodeDevice{ return &structs.NodeDevice{
ID: instanceID, ID: instanceID,
@@ -1395,10 +1326,9 @@ func TestPreemption_Normal(t *testing.T) {
for _, alloc := range tc.currentAllocations { for _, alloc := range tc.currentAllocations {
alloc.NodeID = node.ID alloc.NodeID = node.ID
} }
require := require.New(t)
err := state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, tc.currentAllocations) err := state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, tc.currentAllocations)
require.Nil(err) must.NoError(t, err)
if tc.currentPreemptions != nil { if tc.currentPreemptions != nil {
ctx.plan.NodePreemptions[node.ID] = tc.currentPreemptions ctx.plan.NodePreemptions[node.ID] = tc.currentPreemptions
} }
@@ -1422,14 +1352,14 @@ func TestPreemption_Normal(t *testing.T) {
binPackIter.SetTaskGroup(taskGroup) binPackIter.SetTaskGroup(taskGroup)
option := binPackIter.Next() option := binPackIter.Next()
if tc.preemptedAllocIDs == nil { if tc.preemptedAllocIDs == nil {
require.Nil(option) must.Nil(t, option)
} else { } else {
require.NotNil(option) must.NotNil(t, option)
preemptedAllocs := option.PreemptedAllocs preemptedAllocs := option.PreemptedAllocs
require.Equal(len(tc.preemptedAllocIDs), len(preemptedAllocs)) must.Eq(t, len(tc.preemptedAllocIDs), len(preemptedAllocs))
for _, alloc := range preemptedAllocs { for _, alloc := range preemptedAllocs {
_, ok := tc.preemptedAllocIDs[alloc.ID] _, ok := tc.preemptedAllocIDs[alloc.ID]
require.Truef(ok, "alloc %s was preempted unexpectedly", alloc.ID) must.True(t, ok, must.Sprintf("alloc %s was preempted unexpectedly", alloc.ID))
} }
} }
}) })
@@ -1502,7 +1432,7 @@ func TestPreemptionMultiple(t *testing.T) {
}, },
} }
require.NoError(t, h.State.UpsertNode(structs.MsgTypeTestSetup, h.NextIndex(), node)) must.NoError(t, h.State.UpsertNode(structs.MsgTypeTestSetup, h.NextIndex(), node))
// low priority job with 4 allocs using all 4 GPUs // low priority job with 4 allocs using all 4 GPUs
lowPrioJob := mock.Job() lowPrioJob := mock.Job()
@@ -1515,7 +1445,7 @@ func TestPreemptionMultiple(t *testing.T) {
Name: "gpu", Name: "gpu",
Count: 1, Count: 1,
}} }}
require.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, lowPrioJob)) must.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, lowPrioJob))
allocs := []*structs.Allocation{} allocs := []*structs.Allocation{}
allocIDs := map[string]struct{}{} allocIDs := map[string]struct{}{}
@@ -1531,7 +1461,7 @@ func TestPreemptionMultiple(t *testing.T) {
allocs = append(allocs, alloc) allocs = append(allocs, alloc)
allocIDs[alloc.ID] = struct{}{} allocIDs[alloc.ID] = struct{}{}
} }
require.NoError(t, h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs)) must.NoError(t, h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs))
// new high priority job with 2 allocs, each using 2 GPUs // new high priority job with 2 allocs, each using 2 GPUs
highPrioJob := mock.Job() highPrioJob := mock.Job()
@@ -1544,7 +1474,7 @@ func TestPreemptionMultiple(t *testing.T) {
Name: "gpu", Name: "gpu",
Count: 2, Count: 2,
}} }}
require.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, highPrioJob)) must.NoError(t, h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, highPrioJob))
// schedule // schedule
eval := &structs.Evaluation{ eval := &structs.Evaluation{
@@ -1555,18 +1485,18 @@ func TestPreemptionMultiple(t *testing.T) {
JobID: highPrioJob.ID, JobID: highPrioJob.ID,
Status: structs.EvalStatusPending, Status: structs.EvalStatusPending,
} }
require.NoError(t, h.State.UpsertEvals(structs.MsgTypeTestSetup, h.NextIndex(), []*structs.Evaluation{eval})) must.NoError(t, h.State.UpsertEvals(structs.MsgTypeTestSetup, h.NextIndex(), []*structs.Evaluation{eval}))
// Process the evaluation // Process the evaluation
require.NoError(t, h.Process(NewServiceScheduler, eval)) must.NoError(t, h.Process(NewServiceScheduler, eval))
require.Len(t, h.Plans, 1) must.Len(t, 1, h.Plans)
require.Contains(t, h.Plans[0].NodePreemptions, node.ID) must.MapContainsKey(t, h.Plans[0].NodePreemptions, node.ID)
preempted := map[string]struct{}{} preempted := map[string]struct{}{}
for _, alloc := range h.Plans[0].NodePreemptions[node.ID] { for _, alloc := range h.Plans[0].NodePreemptions[node.ID] {
preempted[alloc.ID] = struct{}{} preempted[alloc.ID] = struct{}{}
} }
require.Equal(t, allocIDs, preempted) must.Eq(t, allocIDs, preempted)
} }
// helper method to create allocations with given jobs and resources // helper method to create allocations with given jobs and resources

View File

@@ -16,7 +16,6 @@ import (
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/test" "github.com/shoenig/test"
"github.com/shoenig/test/must" "github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
) )
var testSchedulerConfig = &structs.SchedulerConfiguration{ var testSchedulerConfig = &structs.SchedulerConfiguration{
@@ -255,15 +254,15 @@ func TestBinPackIterator_NoExistingAlloc_MixedReserve(t *testing.T) {
} }
// 3 nodes should be feasible // 3 nodes should be feasible
require.Len(t, out, 3) must.Len(t, 3, out)
// Node without reservations is the best fit // Node without reservations is the best fit
require.Equal(t, nodes[0].Node.Name, out[0].Node.Name) must.Eq(t, nodes[0].Node.Name, out[0].Node.Name)
// Node with smallest remaining resources ("best fit") should get a // Node with smallest remaining resources ("best fit") should get a
// higher score than node with more remaining resources ("worse fit") // higher score than node with more remaining resources ("worse fit")
require.Equal(t, nodes[1].Node.Name, out[1].Node.Name) must.Eq(t, nodes[1].Node.Name, out[1].Node.Name)
require.Equal(t, nodes[2].Node.Name, out[2].Node.Name) must.Eq(t, nodes[2].Node.Name, out[2].Node.Name)
} }
// Tests bin packing iterator with network resources at task and task group level // Tests bin packing iterator with network resources at task and task group level
@@ -367,27 +366,26 @@ func TestBinPackIterator_Network_Success(t *testing.T) {
scoreNorm := NewScoreNormalizationIterator(ctx, binp) scoreNorm := NewScoreNormalizationIterator(ctx, binp)
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t)
// We expect both nodes to be eligible to place // We expect both nodes to be eligible to place
require.Len(out, 2) must.Len(t, 2, out)
require.Equal(out[0], nodes[0]) must.Eq(t, nodes[0], out[0])
require.Equal(out[1], nodes[1]) must.Eq(t, nodes[1], out[1])
// First node should have a perfect score // First node should have a perfect score
require.Equal(1.0, out[0].FinalScore) must.Eq(t, 1.0, out[0].FinalScore)
if out[1].FinalScore < 0.50 || out[1].FinalScore > 0.60 { if out[1].FinalScore < 0.50 || out[1].FinalScore > 0.60 {
t.Fatalf("Bad Score: %v", out[1].FinalScore) t.Fatalf("Bad Score: %v", out[1].FinalScore)
} }
// Verify network information at taskgroup level // Verify network information at taskgroup level
require.Equal(500, out[0].AllocResources.Networks[0].MBits) must.Eq(t, 500, out[0].AllocResources.Networks[0].MBits)
require.Equal(500, out[1].AllocResources.Networks[0].MBits) must.Eq(t, 500, out[1].AllocResources.Networks[0].MBits)
// Verify network information at task level // Verify network information at task level
require.Equal(300, out[0].TaskResources["web"].Networks[0].MBits) must.Eq(t, 300, out[0].TaskResources["web"].Networks[0].MBits)
require.Equal(300, out[1].TaskResources["web"].Networks[0].MBits) must.Eq(t, 300, out[1].TaskResources["web"].Networks[0].MBits)
} }
// Tests that bin packing iterator fails due to overprovisioning of network // Tests that bin packing iterator fails due to overprovisioning of network
@@ -499,12 +497,11 @@ func TestBinPackIterator_Network_Failure(t *testing.T) {
scoreNorm := NewScoreNormalizationIterator(ctx, binp) scoreNorm := NewScoreNormalizationIterator(ctx, binp)
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t)
// We expect a placement failure because we need 800 mbits of network // We expect a placement failure because we need 800 mbits of network
// and only 300 is free // and only 300 is free
require.Len(out, 0) must.Len(t, 0, out)
require.Equal(1, ctx.metrics.DimensionExhausted["network: bandwidth exceeded"]) must.Eq(t, 1, ctx.metrics.DimensionExhausted["network: bandwidth exceeded"])
} }
func TestBinPackIterator_Network_NoCollision_Node(t *testing.T) { func TestBinPackIterator_Network_NoCollision_Node(t *testing.T) {
@@ -595,7 +592,7 @@ func TestBinPackIterator_Network_NoCollision_Node(t *testing.T) {
// Placement should succeed since reserved ports are merged instead of // Placement should succeed since reserved ports are merged instead of
// treating them as a collision // treating them as a collision
require.Len(t, out, 1) must.Len(t, 1, out)
} }
// TestBinPackIterator_Network_NodeError asserts that NetworkIndex.SetNode can // TestBinPackIterator_Network_NodeError asserts that NetworkIndex.SetNode can
@@ -694,9 +691,9 @@ func TestBinPackIterator_Network_NodeError(t *testing.T) {
// We expect a placement failure because the node has invalid reserved // We expect a placement failure because the node has invalid reserved
// ports // ports
require.Len(t, out, 0) must.Len(t, 0, out)
require.Equal(t, 1, ctx.metrics.DimensionExhausted["network: invalid node"], must.Eq(t, 1, ctx.metrics.DimensionExhausted["network: invalid node"],
ctx.metrics.DimensionExhausted) must.Sprint(ctx.metrics.DimensionExhausted))
} }
func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) { func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) {
@@ -786,9 +783,9 @@ func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) {
ClientStatus: structs.AllocClientStatusPending, ClientStatus: structs.AllocClientStatusPending,
TaskGroup: "web", TaskGroup: "web",
} }
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID))) must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
taskGroup := &structs.TaskGroup{ taskGroup := &structs.TaskGroup{
EphemeralDisk: &structs.EphemeralDisk{}, EphemeralDisk: &structs.EphemeralDisk{},
@@ -820,8 +817,8 @@ func TestBinPackIterator_Network_PortCollision_Alloc(t *testing.T) {
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
// We expect a placement failure due to port collision. // We expect a placement failure due to port collision.
require.Len(t, out, 0) must.Len(t, 0, out)
require.Equal(t, 1, ctx.metrics.DimensionExhausted["network: port collision"]) must.Eq(t, 1, ctx.metrics.DimensionExhausted["network: port collision"])
} }
// Tests bin packing iterator with host network interpolation of task group level ports configuration // Tests bin packing iterator with host network interpolation of task group level ports configuration
@@ -961,18 +958,17 @@ func TestBinPackIterator_Network_Interpolation_Success(t *testing.T) {
scoreNorm := NewScoreNormalizationIterator(ctx, binp) scoreNorm := NewScoreNormalizationIterator(ctx, binp)
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t)
// We expect both nodes to be eligible to place // We expect both nodes to be eligible to place
require.Len(out, 2) must.Len(t, 2, out)
require.Equal(out[0], nodes[0]) must.Eq(t, out[0], nodes[0])
require.Equal(out[1], nodes[1]) must.Eq(t, out[1], nodes[1])
// Verify network information at taskgroup level // Verify network information at taskgroup level
require.Contains([]string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[0].HostNetwork) must.SliceContains(t, []string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[0].HostNetwork)
require.Contains([]string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[1].HostNetwork) must.SliceContains(t, []string{"public", "private"}, out[0].AllocResources.Networks[0].DynamicPorts[1].HostNetwork)
require.Contains([]string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[0].HostNetwork) must.SliceContains(t, []string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[0].HostNetwork)
require.Contains([]string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[1].HostNetwork) must.SliceContains(t, []string{"first", "second"}, out[1].AllocResources.Networks[0].DynamicPorts[1].HostNetwork)
} }
// Tests that bin packing iterator fails due to absence of meta value // Tests that bin packing iterator fails due to absence of meta value
@@ -1072,8 +1068,7 @@ func TestBinPackIterator_Host_Network_Interpolation_Absent_Value(t *testing.T) {
scoreNorm := NewScoreNormalizationIterator(ctx, binp) scoreNorm := NewScoreNormalizationIterator(ctx, binp)
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t) must.Len(t, 0, out)
require.Len(out, 0)
} }
// Tests that bin packing iterator fails due to absence of meta value // Tests that bin packing iterator fails due to absence of meta value
@@ -1173,8 +1168,7 @@ func TestBinPackIterator_Host_Network_Interpolation_Interface_Not_Exists(t *test
scoreNorm := NewScoreNormalizationIterator(ctx, binp) scoreNorm := NewScoreNormalizationIterator(ctx, binp)
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t) must.Len(t, 0, out)
require.Len(out, 0)
} }
func TestBinPackIterator_PlannedAlloc(t *testing.T) { func TestBinPackIterator_PlannedAlloc(t *testing.T) {
@@ -1377,9 +1371,9 @@ func TestBinPackIterator_ReservedCores(t *testing.T) {
ClientStatus: structs.AllocClientStatusPending, ClientStatus: structs.AllocClientStatusPending,
TaskGroup: "web", TaskGroup: "web",
} }
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID))) must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
taskGroup := &structs.TaskGroup{ taskGroup := &structs.TaskGroup{
EphemeralDisk: &structs.EphemeralDisk{}, EphemeralDisk: &structs.EphemeralDisk{},
@@ -1403,10 +1397,9 @@ func TestBinPackIterator_ReservedCores(t *testing.T) {
scoreNorm := NewScoreNormalizationIterator(ctx, binp) scoreNorm := NewScoreNormalizationIterator(ctx, binp)
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t) must.Len(t, 1, out)
require.Len(out, 1) must.Eq(t, nodes[1].Node.ID, out[0].Node.ID)
require.Equal(nodes[1].Node.ID, out[0].Node.ID) must.Eq(t, []uint16{1}, out[0].TaskResources["web"].Cpu.ReservedCores)
require.Equal([]uint16{1}, out[0].TaskResources["web"].Cpu.ReservedCores)
} }
func TestBinPackIterator_ExistingAlloc(t *testing.T) { func TestBinPackIterator_ExistingAlloc(t *testing.T) {
@@ -1489,9 +1482,9 @@ func TestBinPackIterator_ExistingAlloc(t *testing.T) {
ClientStatus: structs.AllocClientStatusPending, ClientStatus: structs.AllocClientStatusPending,
TaskGroup: "web", TaskGroup: "web",
} }
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID))) must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
taskGroup := &structs.TaskGroup{ taskGroup := &structs.TaskGroup{
EphemeralDisk: &structs.EphemeralDisk{}, EphemeralDisk: &structs.EphemeralDisk{},
@@ -1603,9 +1596,9 @@ func TestBinPackIterator_ExistingAlloc_PlannedEvict(t *testing.T) {
ClientStatus: structs.AllocClientStatusPending, ClientStatus: structs.AllocClientStatusPending,
TaskGroup: "web", TaskGroup: "web",
} }
require.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID))) must.NoError(t, state.UpsertJobSummary(998, mock.JobSummary(alloc1.JobID)))
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc2.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1000, []*structs.Allocation{alloc1, alloc2}))
// Add a planned eviction to alloc1 // Add a planned eviction to alloc1
plan := ctx.Plan() plan := ctx.Plan()
@@ -2319,13 +2312,12 @@ func TestNodeAntiAffinity_PenaltyNodes(t *testing.T) {
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t) must.Eq(t, 2, len(out))
require.Equal(2, len(out)) must.Eq(t, node1.ID, out[0].Node.ID)
require.Equal(node1.ID, out[0].Node.ID) must.Eq(t, -1.0, out[0].FinalScore)
require.Equal(-1.0, out[0].FinalScore)
require.Equal(node2.ID, out[1].Node.ID) must.Eq(t, node2.ID, out[1].Node.ID)
require.Equal(0.0, out[1].FinalScore) must.Eq(t, 0.0, out[1].FinalScore)
} }
@@ -2383,15 +2375,14 @@ func TestScoreNormalizationIterator(t *testing.T) {
scoreNorm := NewScoreNormalizationIterator(ctx, nodeReschedulePenaltyIter) scoreNorm := NewScoreNormalizationIterator(ctx, nodeReschedulePenaltyIter)
out := collectRanked(scoreNorm) out := collectRanked(scoreNorm)
require := require.New(t)
require.Equal(2, len(out)) must.Eq(t, 2, len(out))
require.Equal(out[0], nodes[0]) must.Eq(t, nodes[0], out[0])
// Score should be averaged between both scorers // Score should be averaged between both scorers
// -0.75 from job anti affinity and -1 from node rescheduling penalty // -0.75 from job anti affinity and -1 from node rescheduling penalty
require.Equal(-0.875, out[0].FinalScore) must.Eq(t, -0.875, out[0].FinalScore)
require.Equal(out[1], nodes[1]) must.Eq(t, nodes[1], out[1])
require.Equal(out[1].FinalScore, 0.0) must.Eq(t, 0.0, out[1].FinalScore)
} }
func TestNodeAffinityIterator(t *testing.T) { func TestNodeAffinityIterator(t *testing.T) {

View File

@@ -5,7 +5,6 @@ package scheduler
import ( import (
"fmt" "fmt"
"reflect"
"regexp" "regexp"
"strconv" "strconv"
"testing" "testing"
@@ -277,10 +276,9 @@ func assertResults(t *testing.T, r *reconcileResults, exp *resultExpectation) {
} else if exp.createDeployment != nil && r.deployment != nil { } else if exp.createDeployment != nil && r.deployment != nil {
// Clear the deployment ID // Clear the deployment ID
r.deployment.ID, exp.createDeployment.ID = "", "" r.deployment.ID, exp.createDeployment.ID = "", ""
if !reflect.DeepEqual(r.deployment, exp.createDeployment) { must.Eq(t, exp.createDeployment, r.deployment, must.Sprintf(
t.Errorf("Unexpected createdDeployment; got\n %#v\nwant\n%#v\nDiff: %v", "Unexpected createdDeployment; got\n %#v\nwant\n%#v\nDiff: %v",
r.deployment, exp.createDeployment, pretty.Diff(r.deployment, exp.createDeployment)) r.deployment, exp.createDeployment, pretty.Diff(r.deployment, exp.createDeployment)))
}
} }
test.Eq(t, exp.deploymentUpdates, r.deploymentUpdates, test.Sprint("Expected Deployment Updates")) test.Eq(t, exp.deploymentUpdates, r.deploymentUpdates, test.Sprint("Expected Deployment Updates"))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ import (
"github.com/hashicorp/nomad/ci" "github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/nomad/mock" "github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/stretchr/testify/require" "github.com/shoenig/test/must"
) )
func TestLimitIterator(t *testing.T) { func TestLimitIterator(t *testing.T) {
@@ -313,12 +313,11 @@ func TestLimitIterator_ScoreThreshold(t *testing.T) {
limit := NewLimitIterator(ctx, static, 1, 0, 2) limit := NewLimitIterator(ctx, static, 1, 0, 2)
limit.SetLimit(2) limit.SetLimit(2)
out := collectRanked(limit) out := collectRanked(limit)
require := require.New(t) must.Eq(t, tc.expectedOut, out)
require.Equal(tc.expectedOut, out)
limit.Reset() limit.Reset()
require.Equal(0, limit.skippedNodeIndex) must.Eq(t, 0, limit.skippedNodeIndex)
require.Equal(0, len(limit.skippedNodes)) must.Eq(t, 0, len(limit.skippedNodes))
}) })
} }

View File

@@ -13,7 +13,6 @@ import (
"github.com/shoenig/test" "github.com/shoenig/test"
"github.com/shoenig/test/must" "github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
"github.com/hashicorp/go-set/v3" "github.com/hashicorp/go-set/v3"
"github.com/hashicorp/nomad/ci" "github.com/hashicorp/nomad/ci"
@@ -100,7 +99,7 @@ func TestSpreadIterator_SingleAttribute(t *testing.T) {
"dc2": 0.5, "dc2": 0.5,
} }
for _, rn := range out { for _, rn := range out {
require.Equal(t, expectedScores[rn.Node.Datacenter], rn.FinalScore) must.Eq(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
} }
// Update the plan to add more allocs to nodes in dc1 // Update the plan to add more allocs to nodes in dc1
@@ -179,7 +178,7 @@ func TestSpreadIterator_SingleAttribute(t *testing.T) {
"dc2": 0.5, "dc2": 0.5,
} }
for _, rn := range out { for _, rn := range out {
require.Equal(t, expectedScores[rn.Node.Datacenter], rn.FinalScore) must.Eq(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
} }
} }
@@ -281,7 +280,7 @@ func TestSpreadIterator_MultipleAttributes(t *testing.T) {
nodes[3].Node.ID: 0.556, nodes[3].Node.ID: 0.556,
} }
for _, rn := range out { for _, rn := range out {
require.Equal(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.ID]), fmt.Sprintf("%.3f", rn.FinalScore)) must.Eq(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.ID]), fmt.Sprintf("%.3f", rn.FinalScore))
} }
} }
@@ -328,7 +327,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
"dc2": 0, "dc2": 0,
} }
for _, rn := range out { for _, rn := range out {
require.Equal(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore)) must.Eq(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore))
} }
@@ -374,7 +373,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
"dc2": 1, "dc2": 1,
} }
for _, rn := range out { for _, rn := range out {
require.Equal(t, expectedScores[rn.Node.Datacenter], rn.FinalScore) must.Eq(t, expectedScores[rn.Node.Datacenter], rn.FinalScore)
} }
// Update the plan to add more allocs to nodes in dc2 // Update the plan to add more allocs to nodes in dc2
@@ -427,7 +426,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
"dc2": -0.5, "dc2": -0.5,
} }
for _, rn := range out { for _, rn := range out {
require.Equal(t, fmt.Sprintf("%3.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%3.3f", rn.FinalScore)) must.Eq(t, fmt.Sprintf("%3.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%3.3f", rn.FinalScore))
} }
// Add another node in dc3 // Add another node in dc3
@@ -470,7 +469,7 @@ func TestSpreadIterator_EvenSpread(t *testing.T) {
"dc3": 1, "dc3": 1,
} }
for _, rn := range out { for _, rn := range out {
require.Equal(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore)) must.Eq(t, fmt.Sprintf("%.3f", expectedScores[rn.Node.Datacenter]), fmt.Sprintf("%.3f", rn.FinalScore))
} }
} }
@@ -525,7 +524,7 @@ func TestSpreadIterator_MaxPenalty(t *testing.T) {
// All nodes are in dc3 so score should be -1 // All nodes are in dc3 so score should be -1
for _, rn := range out { for _, rn := range out {
require.Equal(t, -1.0, rn.FinalScore) must.Eq(t, -1.0, rn.FinalScore)
} }
// Reset scores // Reset scores
@@ -560,7 +559,7 @@ func TestSpreadIterator_MaxPenalty(t *testing.T) {
// All nodes don't have the spread attribute so score should be -1 // All nodes don't have the spread attribute so score should be -1
for _, rn := range out { for _, rn := range out {
require.Equal(t, -1.0, rn.FinalScore) must.Eq(t, -1.0, rn.FinalScore)
} }
} }
@@ -685,8 +684,8 @@ func Test_evenSpreadScoreBoost(t *testing.T) {
Datacenter: "dc2", Datacenter: "dc2",
} }
boost := evenSpreadScoreBoost(pset, opt) boost := evenSpreadScoreBoost(pset, opt)
require.False(t, math.IsInf(boost, 1)) must.False(t, math.IsInf(boost, 1))
require.Equal(t, 1.0, boost) must.Eq(t, 1.0, boost)
} }
// TestSpreadOnLargeCluster exercises potentially quadratic // TestSpreadOnLargeCluster exercises potentially quadratic
@@ -759,20 +758,20 @@ func TestSpreadOnLargeCluster(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
h := NewHarness(t) h := NewHarness(t)
err := upsertNodes(h, tc.nodeCount, tc.racks) err := upsertNodes(h, tc.nodeCount, tc.racks)
require.NoError(t, err) must.NoError(t, err)
job := generateJob(tc.allocs) job := generateJob(tc.allocs)
eval, err := upsertJob(h, job) eval, err := upsertJob(h, job)
require.NoError(t, err) must.NoError(t, err)
start := time.Now() start := time.Now()
err = h.Process(NewServiceScheduler, eval) err = h.Process(NewServiceScheduler, eval)
require.NoError(t, err) must.NoError(t, err)
require.LessOrEqual(t, time.Since(start), time.Duration(60*time.Second), must.LessEq(t, time.Duration(60*time.Second), time.Since(start),
"time to evaluate exceeded EvalNackTimeout") must.Sprint("time to evaluate exceeded EvalNackTimeout"))
require.Len(t, h.Plans, 1) must.Len(t, 1, h.Plans)
require.False(t, h.Plans[0].IsNoOp()) must.False(t, h.Plans[0].IsNoOp())
require.NoError(t, validateEqualSpread(h)) must.NoError(t, validateEqualSpread(h))
}) })
} }
} }
@@ -940,7 +939,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
nodes = append(nodes, node) nodes = append(nodes, node)
err := h.State.UpsertNode(structs.MsgTypeTestSetup, err := h.State.UpsertNode(structs.MsgTypeTestSetup,
h.NextIndex(), node) h.NextIndex(), node)
require.NoError(t, err) must.NoError(t, err)
} }
// job version 1 // job version 1
@@ -974,7 +973,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
job1.Version = 1 job1.Version = 1
job1.TaskGroups[0].Count = 5 job1.TaskGroups[0].Count = 5
err := h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job1) err := h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job1)
require.NoError(t, err) must.NoError(t, err)
allocs := []*structs.Allocation{} allocs := []*structs.Allocation{}
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
@@ -997,7 +996,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
allocs = append(allocs, alloc) allocs = append(allocs, alloc)
} }
err = h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs) err = h.State.UpsertAllocs(structs.MsgTypeTestSetup, h.NextIndex(), allocs)
require.NoError(t, err) must.NoError(t, err)
// job version 2 // job version 2
// max_parallel = 0, canary = 1, spread == nil // max_parallel = 0, canary = 1, spread == nil
@@ -1006,7 +1005,7 @@ func TestSpreadPanicDowngrade(t *testing.T) {
job2.Version = 2 job2.Version = 2
job2.Spreads = nil job2.Spreads = nil
err = h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job2) err = h.State.UpsertJob(structs.MsgTypeTestSetup, h.NextIndex(), nil, job2)
require.NoError(t, err) must.NoError(t, err)
eval := &structs.Evaluation{ eval := &structs.Evaluation{
Namespace: job2.Namespace, Namespace: job2.Namespace,
@@ -1018,11 +1017,11 @@ func TestSpreadPanicDowngrade(t *testing.T) {
} }
err = h.State.UpsertEvals(structs.MsgTypeTestSetup, err = h.State.UpsertEvals(structs.MsgTypeTestSetup,
h.NextIndex(), []*structs.Evaluation{eval}) h.NextIndex(), []*structs.Evaluation{eval})
require.NoError(t, err) must.NoError(t, err)
processErr := h.Process(NewServiceScheduler, eval) processErr := h.Process(NewServiceScheduler, eval)
require.NoError(t, processErr, "failed to process eval") must.NoError(t, processErr, must.Sprintf("..."))
require.Len(t, h.Plans, 1) must.Len(t, 1, h.Plans)
} }
func TestSpread_ImplicitTargets(t *testing.T) { func TestSpread_ImplicitTargets(t *testing.T) {

View File

@@ -5,7 +5,6 @@ package scheduler
import ( import (
"fmt" "fmt"
"reflect"
"runtime" "runtime"
"testing" "testing"
@@ -82,9 +81,8 @@ func TestServiceStack_SetNodes(t *testing.T) {
} }
out := collectFeasible(stack.source) out := collectFeasible(stack.source)
if !reflect.DeepEqual(out, nodes) { must.Eq(t, nodes, out)
t.Fatalf("bad: %#v", out)
}
} }
func TestServiceStack_SetJob(t *testing.T) { func TestServiceStack_SetJob(t *testing.T) {
@@ -99,9 +97,7 @@ func TestServiceStack_SetJob(t *testing.T) {
if stack.binPack.priority != job.Priority { if stack.binPack.priority != job.Priority {
t.Fatalf("bad") t.Fatalf("bad")
} }
if !reflect.DeepEqual(stack.jobConstraint.constraints, job.Constraints) { must.Eq(t, stack.jobConstraint.constraints, job.Constraints)
t.Fatalf("bad")
}
} }
func TestServiceStack_Select_Size(t *testing.T) { func TestServiceStack_Select_Size(t *testing.T) {

View File

@@ -9,13 +9,12 @@ import (
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require"
"github.com/hashicorp/go-memdb" "github.com/hashicorp/go-memdb"
"github.com/hashicorp/go-version" "github.com/hashicorp/go-version"
"github.com/hashicorp/nomad/helper/testlog" "github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/nomad/state" "github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/test/must"
) )
// RejectPlan is used to always reject the entire plan and force a state refresh // RejectPlan is used to always reject the entire plan and force a state refresh
@@ -306,9 +305,9 @@ func (h *Harness) Process(factory Factory, eval *structs.Evaluation) error {
} }
func (h *Harness) AssertEvalStatus(t testing.TB, state string) { func (h *Harness) AssertEvalStatus(t testing.TB, state string) {
require.Len(t, h.Evals, 1) must.Len(t, 1, h.Evals)
update := h.Evals[0] update := h.Evals[0]
require.Equal(t, state, update.Status) must.Eq(t, state, update.Status)
} }
func (h *Harness) SetNoSubmit() { func (h *Harness) SetNoSubmit() {

View File

@@ -4,7 +4,6 @@
package scheduler package scheduler
import ( import (
"reflect"
"testing" "testing"
"time" "time"
@@ -16,7 +15,6 @@ import (
"github.com/hashicorp/nomad/nomad/state" "github.com/hashicorp/nomad/nomad/state"
"github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/test/must" "github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
) )
func BenchmarkTasksUpdated(b *testing.B) { func BenchmarkTasksUpdated(b *testing.B) {
@@ -136,8 +134,8 @@ func TestRetryMax(t *testing.T) {
return false, nil return false, nil
} }
err := retryMax(3, bad, nil) err := retryMax(3, bad, nil)
require.Error(t, err) must.Error(t, err)
require.Equal(t, 3, calls, "mis match") must.Eq(t, 3, calls)
calls = 0 calls = 0
first := true first := true
@@ -149,8 +147,8 @@ func TestRetryMax(t *testing.T) {
return false return false
} }
err = retryMax(3, bad, reset) err = retryMax(3, bad, reset)
require.Error(t, err) must.Error(t, err)
require.Equal(t, 6, calls, "mis match") must.Eq(t, 6, calls)
calls = 0 calls = 0
good := func() (bool, error) { good := func() (bool, error) {
@@ -158,8 +156,8 @@ func TestRetryMax(t *testing.T) {
return true, nil return true, nil
} }
err = retryMax(3, good, nil) err = retryMax(3, good, nil)
require.NoError(t, err) must.NoError(t, err)
require.Equal(t, 1, calls, "mis match") must.Eq(t, 1, calls)
} }
func TestTaintedNodes(t *testing.T) { func TestTaintedNodes(t *testing.T) {
@@ -173,10 +171,10 @@ func TestTaintedNodes(t *testing.T) {
node3.Datacenter = "dc2" node3.Datacenter = "dc2"
node3.Status = structs.NodeStatusDown node3.Status = structs.NodeStatusDown
node4 := mock.DrainNode() node4 := mock.DrainNode()
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1000, node1)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1000, node1))
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1001, node2)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1001, node2))
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1002, node3)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1002, node3))
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1003, node4)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 1003, node4))
allocs := []*structs.Allocation{ allocs := []*structs.Allocation{
{NodeID: node1.ID}, {NodeID: node1.ID},
@@ -186,19 +184,19 @@ func TestTaintedNodes(t *testing.T) {
{NodeID: "12345678-abcd-efab-cdef-123456789abc"}, {NodeID: "12345678-abcd-efab-cdef-123456789abc"},
} }
tainted, err := taintedNodes(state, allocs) tainted, err := taintedNodes(state, allocs)
require.NoError(t, err) must.NoError(t, err)
require.Equal(t, 3, len(tainted)) must.Eq(t, 3, len(tainted))
require.NotContains(t, tainted, node1.ID) must.MapNotContainsKey(t, tainted, node1.ID)
require.NotContains(t, tainted, node2.ID) must.MapNotContainsKey(t, tainted, node2.ID)
require.Contains(t, tainted, node3.ID) must.MapContainsKey(t, tainted, node3.ID)
require.NotNil(t, tainted[node3.ID]) must.NotNil(t, tainted[node3.ID])
require.Contains(t, tainted, node4.ID) must.MapContainsKey(t, tainted, node4.ID)
require.NotNil(t, tainted[node4.ID]) must.NotNil(t, tainted[node4.ID])
require.Contains(t, tainted, "12345678-abcd-efab-cdef-123456789abc") must.MapContainsKey(t, tainted, "12345678-abcd-efab-cdef-123456789abc")
require.Nil(t, tainted["12345678-abcd-efab-cdef-123456789abc"]) must.Nil(t, tainted["12345678-abcd-efab-cdef-123456789abc"])
} }
func TestShuffleNodes(t *testing.T) { func TestShuffleNodes(t *testing.T) {
@@ -223,13 +221,13 @@ func TestShuffleNodes(t *testing.T) {
eval := mock.Eval() // will have random EvalID eval := mock.Eval() // will have random EvalID
plan := eval.MakePlan(mock.Job()) plan := eval.MakePlan(mock.Job())
shuffleNodes(plan, 1000, nodes) shuffleNodes(plan, 1000, nodes)
require.False(t, reflect.DeepEqual(nodes, orig)) must.NotEq(t, nodes, orig)
nodes2 := make([]*structs.Node, len(nodes)) nodes2 := make([]*structs.Node, len(nodes))
copy(nodes2, orig) copy(nodes2, orig)
shuffleNodes(plan, 1000, nodes2) shuffleNodes(plan, 1000, nodes2)
require.True(t, reflect.DeepEqual(nodes, nodes2)) must.Eq(t, nodes, nodes2)
} }
@@ -602,58 +600,58 @@ func TestSetStatus(t *testing.T) {
eval := mock.Eval() eval := mock.Eval()
status := "a" status := "a"
desc := "b" desc := "b"
require.NoError(t, setStatus(logger, h, eval, nil, nil, nil, status, desc, nil, "")) must.NoError(t, setStatus(logger, h, eval, nil, nil, nil, status, desc, nil, ""))
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals) must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
newEval := h.Evals[0] newEval := h.Evals[0]
require.True(t, newEval.ID == eval.ID && newEval.Status == status && newEval.StatusDescription == desc, must.True(t, newEval.ID == eval.ID && newEval.Status == status && newEval.StatusDescription == desc,
"setStatus() submited invalid eval: %v", newEval) must.Sprintf("setStatus() submited invalid eval: %v", newEval))
// Test next evals // Test next evals
h = NewHarness(t) h = NewHarness(t)
next := mock.Eval() next := mock.Eval()
require.NoError(t, setStatus(logger, h, eval, next, nil, nil, status, desc, nil, "")) must.NoError(t, setStatus(logger, h, eval, next, nil, nil, status, desc, nil, ""))
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals) must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
newEval = h.Evals[0] newEval = h.Evals[0]
require.Equal(t, next.ID, newEval.NextEval, "setStatus() didn't set nextEval correctly: %v", newEval) must.Eq(t, next.ID, newEval.NextEval, must.Sprintf("setStatus() didn't set nextEval correctly: %v", newEval))
// Test blocked evals // Test blocked evals
h = NewHarness(t) h = NewHarness(t)
blocked := mock.Eval() blocked := mock.Eval()
require.NoError(t, setStatus(logger, h, eval, nil, blocked, nil, status, desc, nil, "")) must.NoError(t, setStatus(logger, h, eval, nil, blocked, nil, status, desc, nil, ""))
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals) must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
newEval = h.Evals[0] newEval = h.Evals[0]
require.Equal(t, blocked.ID, newEval.BlockedEval, "setStatus() didn't set BlockedEval correctly: %v", newEval) must.Eq(t, blocked.ID, newEval.BlockedEval, must.Sprintf("setStatus() didn't set BlockedEval correctly: %v", newEval))
// Test metrics // Test metrics
h = NewHarness(t) h = NewHarness(t)
metrics := map[string]*structs.AllocMetric{"foo": nil} metrics := map[string]*structs.AllocMetric{"foo": nil}
require.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, nil, "")) must.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, nil, ""))
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals) must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
newEval = h.Evals[0] newEval = h.Evals[0]
require.True(t, reflect.DeepEqual(newEval.FailedTGAllocs, metrics), must.Eq(t, newEval.FailedTGAllocs, metrics,
"setStatus() didn't set failed task group metrics correctly: %v", newEval) must.Sprintf("setStatus() didn't set failed task group metrics correctly: %v", newEval))
// Test queued allocations // Test queued allocations
h = NewHarness(t) h = NewHarness(t)
queuedAllocs := map[string]int{"web": 1} queuedAllocs := map[string]int{"web": 1}
require.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, "")) must.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, ""))
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals) must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
newEval = h.Evals[0] newEval = h.Evals[0]
require.True(t, reflect.DeepEqual(newEval.QueuedAllocations, queuedAllocs), "setStatus() didn't set failed task group metrics correctly: %v", newEval) must.Eq(t, newEval.QueuedAllocations, queuedAllocs, must.Sprintf("setStatus() didn't set failed task group metrics correctly: %v", newEval))
h = NewHarness(t) h = NewHarness(t)
dID := uuid.Generate() dID := uuid.Generate()
require.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, dID)) must.NoError(t, setStatus(logger, h, eval, nil, nil, metrics, status, desc, queuedAllocs, dID))
require.Equal(t, 1, len(h.Evals), "setStatus() didn't update plan: %v", h.Evals) must.Eq(t, 1, len(h.Evals), must.Sprintf("setStatus() didn't update plan: %v", h.Evals))
newEval = h.Evals[0] newEval = h.Evals[0]
require.Equal(t, dID, newEval.DeploymentID, "setStatus() didn't set deployment id correctly: %v", newEval) must.Eq(t, dID, newEval.DeploymentID, must.Sprintf("setStatus() didn't set deployment id correctly: %v", newEval))
} }
func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) { func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
@@ -664,7 +662,7 @@ func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
job := mock.Job() job := mock.Job()
node := mock.Node() node := mock.Node()
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
// Register an alloc // Register an alloc
alloc := &structs.Allocation{ alloc := &structs.Allocation{
@@ -690,8 +688,8 @@ func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
TaskGroup: "web", TaskGroup: "web",
} }
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources} alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
require.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID))) must.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
// Create a new task group that prevents in-place updates. // Create a new task group that prevents in-place updates.
tg := &structs.TaskGroup{} tg := &structs.TaskGroup{}
@@ -709,8 +707,8 @@ func TestInplaceUpdate_ChangedTaskGroup(t *testing.T) {
// Do the inplace update. // Do the inplace update.
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates) unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
require.True(t, len(unplaced) == 1 && len(inplace) == 0, "inplaceUpdate incorrectly did an inplace update") must.True(t, len(unplaced) == 1 && len(inplace) == 0, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
require.Empty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update") must.MapEmpty(t, ctx.plan.NodeAllocation, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
} }
func TestInplaceUpdate_AllocatedResources(t *testing.T) { func TestInplaceUpdate_AllocatedResources(t *testing.T) {
@@ -721,7 +719,7 @@ func TestInplaceUpdate_AllocatedResources(t *testing.T) {
job := mock.Job() job := mock.Job()
node := mock.Node() node := mock.Node()
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
// Register an alloc // Register an alloc
alloc := &structs.Allocation{ alloc := &structs.Allocation{
@@ -746,8 +744,8 @@ func TestInplaceUpdate_AllocatedResources(t *testing.T) {
TaskGroup: "web", TaskGroup: "web",
} }
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources} alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
require.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID))) must.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
// Update TG to add a new service (inplace) // Update TG to add a new service (inplace)
tg := job.TaskGroups[0] tg := job.TaskGroups[0]
@@ -763,13 +761,13 @@ func TestInplaceUpdate_AllocatedResources(t *testing.T) {
// Do the inplace update. // Do the inplace update.
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates) unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
require.True(t, len(unplaced) == 0 && len(inplace) == 1, "inplaceUpdate incorrectly did not perform an inplace update") must.True(t, len(unplaced) == 0 && len(inplace) == 1, must.Sprint("inplaceUpdate incorrectly did not perform an inplace update"))
require.NotEmpty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update") must.MapNotEmpty(t, ctx.plan.NodeAllocation, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
require.NotEmpty(t, ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports) must.SliceNotEmpty(t, ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports)
port, ok := ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports.Get("api-port") port, ok := ctx.plan.NodeAllocation[node.ID][0].AllocatedResources.Shared.Ports.Get("api-port")
require.True(t, ok) must.True(t, ok)
require.Equal(t, 19910, port.Value) must.Eq(t, 19910, port.Value)
} }
func TestInplaceUpdate_NoMatch(t *testing.T) { func TestInplaceUpdate_NoMatch(t *testing.T) {
@@ -780,7 +778,7 @@ func TestInplaceUpdate_NoMatch(t *testing.T) {
job := mock.Job() job := mock.Job()
node := mock.Node() node := mock.Node()
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
// Register an alloc // Register an alloc
alloc := &structs.Allocation{ alloc := &structs.Allocation{
@@ -806,8 +804,8 @@ func TestInplaceUpdate_NoMatch(t *testing.T) {
TaskGroup: "web", TaskGroup: "web",
} }
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources} alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
require.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID))) must.NoError(t, state.UpsertJobSummary(1000, mock.JobSummary(alloc.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
// Create a new task group that requires too much resources. // Create a new task group that requires too much resources.
tg := &structs.TaskGroup{} tg := &structs.TaskGroup{}
@@ -821,8 +819,8 @@ func TestInplaceUpdate_NoMatch(t *testing.T) {
// Do the inplace update. // Do the inplace update.
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates) unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
require.True(t, len(unplaced) == 1 && len(inplace) == 0, "inplaceUpdate incorrectly did an inplace update") must.True(t, len(unplaced) == 1 && len(inplace) == 0, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
require.Empty(t, ctx.plan.NodeAllocation, "inplaceUpdate incorrectly did an inplace update") must.MapEmpty(t, ctx.plan.NodeAllocation, must.Sprint("inplaceUpdate incorrectly did an inplace update"))
} }
func TestInplaceUpdate_Success(t *testing.T) { func TestInplaceUpdate_Success(t *testing.T) {
@@ -833,7 +831,7 @@ func TestInplaceUpdate_Success(t *testing.T) {
job := mock.Job() job := mock.Job()
node := mock.Node() node := mock.Node()
require.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node)) must.NoError(t, state.UpsertNode(structs.MsgTypeTestSetup, 900, node))
// Register an alloc // Register an alloc
alloc := &structs.Allocation{ alloc := &structs.Allocation{
@@ -859,8 +857,8 @@ func TestInplaceUpdate_Success(t *testing.T) {
DesiredStatus: structs.AllocDesiredStatusRun, DesiredStatus: structs.AllocDesiredStatusRun,
} }
alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources} alloc.TaskResources = map[string]*structs.Resources{"web": alloc.Resources}
require.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID))) must.NoError(t, state.UpsertJobSummary(999, mock.JobSummary(alloc.JobID)))
require.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc})) must.NoError(t, state.UpsertAllocs(structs.MsgTypeTestSetup, 1001, []*structs.Allocation{alloc}))
// Create a new task group that updates the resources. // Create a new task group that updates the resources.
tg := &structs.TaskGroup{} tg := &structs.TaskGroup{}
@@ -891,23 +889,23 @@ func TestInplaceUpdate_Success(t *testing.T) {
// Do the inplace update. // Do the inplace update.
unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates) unplaced, inplace := inplaceUpdate(ctx, eval, job, stack, updates)
require.True(t, len(unplaced) == 0 && len(inplace) == 1, "inplaceUpdate did not do an inplace update") must.True(t, len(unplaced) == 0 && len(inplace) == 1, must.Sprint("inplaceUpdate did not do an inplace update"))
require.Equal(t, 1, len(ctx.plan.NodeAllocation), "inplaceUpdate did not do an inplace update") must.Eq(t, 1, len(ctx.plan.NodeAllocation), must.Sprint("inplaceUpdate did not do an inplace update"))
require.Equal(t, alloc.ID, inplace[0].Alloc.ID, "inplaceUpdate returned the wrong, inplace updated alloc: %#v", inplace) must.Eq(t, alloc.ID, inplace[0].Alloc.ID, must.Sprintf("inplaceUpdate returned the wrong, inplace updated alloc: %#v", inplace))
// Get the alloc we inserted. // Get the alloc we inserted.
a := inplace[0].Alloc // TODO(sean@): Verify this is correct vs: ctx.plan.NodeAllocation[alloc.NodeID][0] a := inplace[0].Alloc // TODO(sean@): Verify this is correct vs: ctx.plan.NodeAllocation[alloc.NodeID][0]
require.NotNil(t, a.Job) must.NotNil(t, a.Job)
require.Equal(t, 1, len(a.Job.TaskGroups)) must.Eq(t, 1, len(a.Job.TaskGroups))
require.Equal(t, 1, len(a.Job.TaskGroups[0].Tasks)) must.Eq(t, 1, len(a.Job.TaskGroups[0].Tasks))
require.Equal(t, 3, len(a.Job.TaskGroups[0].Tasks[0].Services), must.Eq(t, 3, len(a.Job.TaskGroups[0].Tasks[0].Services), must.Sprintf(
"Expected number of services: %v, Actual: %v", 3, len(a.Job.TaskGroups[0].Tasks[0].Services)) "Expected number of services: %v, Actual: %v", 3, len(a.Job.TaskGroups[0].Tasks[0].Services)))
serviceNames := make(map[string]struct{}, 3) serviceNames := make(map[string]struct{}, 3)
for _, consulService := range a.Job.TaskGroups[0].Tasks[0].Services { for _, consulService := range a.Job.TaskGroups[0].Tasks[0].Services {
serviceNames[consulService.Name] = struct{}{} serviceNames[consulService.Name] = struct{}{}
} }
require.Equal(t, 3, len(serviceNames)) must.Eq(t, 3, len(serviceNames))
for _, name := range []string{"dummy-service", "dummy-service2", "web-frontend"} { for _, name := range []string{"dummy-service", "dummy-service2", "web-frontend"} {
if _, found := serviceNames[name]; !found { if _, found := serviceNames[name]; !found {
@@ -1051,23 +1049,23 @@ func TestUtil_connectSidecarServiceUpdated(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
t.Run("both nil", func(t *testing.T) { t.Run("both nil", func(t *testing.T) {
require.False(t, connectSidecarServiceUpdated(nil, nil).modified) must.False(t, connectSidecarServiceUpdated(nil, nil).modified)
}) })
t.Run("one nil", func(t *testing.T) { t.Run("one nil", func(t *testing.T) {
require.True(t, connectSidecarServiceUpdated(nil, new(structs.ConsulSidecarService)).modified) must.True(t, connectSidecarServiceUpdated(nil, new(structs.ConsulSidecarService)).modified)
}) })
t.Run("ports differ", func(t *testing.T) { t.Run("ports differ", func(t *testing.T) {
a := &structs.ConsulSidecarService{Port: "1111"} a := &structs.ConsulSidecarService{Port: "1111"}
b := &structs.ConsulSidecarService{Port: "2222"} b := &structs.ConsulSidecarService{Port: "2222"}
require.True(t, connectSidecarServiceUpdated(a, b).modified) must.True(t, connectSidecarServiceUpdated(a, b).modified)
}) })
t.Run("same", func(t *testing.T) { t.Run("same", func(t *testing.T) {
a := &structs.ConsulSidecarService{Port: "1111"} a := &structs.ConsulSidecarService{Port: "1111"}
b := &structs.ConsulSidecarService{Port: "1111"} b := &structs.ConsulSidecarService{Port: "1111"}
require.False(t, connectSidecarServiceUpdated(a, b).modified) must.False(t, connectSidecarServiceUpdated(a, b).modified)
}) })
} }
@@ -1144,17 +1142,17 @@ func TestTaskGroupConstraints(t *testing.T) {
expDrivers := map[string]struct{}{"exec": {}, "docker": {}} expDrivers := map[string]struct{}{"exec": {}, "docker": {}}
actConstrains := taskGroupConstraints(tg) actConstrains := taskGroupConstraints(tg)
require.True(t, reflect.DeepEqual(actConstrains.constraints, expConstr), must.Eq(t, actConstrains.constraints, expConstr, must.Sprintf(
"taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.constraints, expConstr) "taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.constraints, expConstr))
require.True(t, reflect.DeepEqual(actConstrains.drivers, expDrivers), must.Eq(t, actConstrains.drivers, expDrivers, must.Sprintf(
"taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.drivers, expDrivers) "taskGroupConstraints(%v) returned %v; want %v", tg, actConstrains.drivers, expDrivers))
} }
func TestProgressMade(t *testing.T) { func TestProgressMade(t *testing.T) {
ci.Parallel(t) ci.Parallel(t)
noopPlan := &structs.PlanResult{} noopPlan := &structs.PlanResult{}
require.False(t, progressMade(nil) || progressMade(noopPlan), "no progress plan marked as making progress") must.False(t, progressMade(nil) || progressMade(noopPlan), must.Sprint("no progress plan marked as making progress"))
m := map[string][]*structs.Allocation{ m := map[string][]*structs.Allocation{
"foo": {mock.Alloc()}, "foo": {mock.Alloc()},
@@ -1172,7 +1170,7 @@ func TestProgressMade(t *testing.T) {
}, },
} }
require.True(t, progressMade(both) && progressMade(update) && progressMade(alloc) && must.True(t, progressMade(both) && progressMade(update) && progressMade(alloc) &&
progressMade(deployment) && progressMade(deploymentUpdates)) progressMade(deployment) && progressMade(deploymentUpdates))
} }
@@ -1231,7 +1229,7 @@ func TestDesiredUpdates(t *testing.T) {
} }
desired := desiredUpdates(diff, inplace, destructive) desired := desiredUpdates(diff, inplace, destructive)
require.True(t, reflect.DeepEqual(desired, expected), "desiredUpdates() returned %#v; want %#v", desired, expected) must.Eq(t, desired, expected, must.Sprintf("desiredUpdates() returned %#v; want %#v", desired, expected))
} }
func TestUtil_AdjustQueuedAllocations(t *testing.T) { func TestUtil_AdjustQueuedAllocations(t *testing.T) {
@@ -1268,7 +1266,7 @@ func TestUtil_AdjustQueuedAllocations(t *testing.T) {
queuedAllocs := map[string]int{"web": 2} queuedAllocs := map[string]int{"web": 2}
adjustQueuedAllocations(logger, &planResult, queuedAllocs) adjustQueuedAllocations(logger, &planResult, queuedAllocs)
require.Equal(t, 1, queuedAllocs["web"]) must.Eq(t, 1, queuedAllocs["web"])
} }
func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) { func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) {
@@ -1308,7 +1306,7 @@ func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) {
allocsLost = append(allocsLost, alloc.ID) allocsLost = append(allocsLost, alloc.ID)
} }
expected := []string{alloc1.ID, alloc2.ID} expected := []string{alloc1.ID, alloc2.ID}
require.True(t, reflect.DeepEqual(allocsLost, expected), "actual: %v, expected: %v", allocsLost, expected) must.Eq(t, allocsLost, expected, must.Sprintf("actual: %v, expected: %v", allocsLost, expected))
// Update the node status to ready and try again // Update the node status to ready and try again
plan = structs.Plan{ plan = structs.Plan{
@@ -1322,7 +1320,7 @@ func TestUtil_UpdateNonTerminalAllocsToLost(t *testing.T) {
allocsLost = append(allocsLost, alloc.ID) allocsLost = append(allocsLost, alloc.ID)
} }
expected = []string{} expected = []string{}
require.True(t, reflect.DeepEqual(allocsLost, expected), "actual: %v, expected: %v", allocsLost, expected) must.Eq(t, allocsLost, expected, must.Sprintf("actual: %v, expected: %v", allocsLost, expected))
} }
func TestTaskGroupUpdated_Restart(t *testing.T) { func TestTaskGroupUpdated_Restart(t *testing.T) {