Files
nomad/client/heartbeatstop_test.go
Michael Schurter 92de40b00d tests: fixes a few data races in tests (#25455)
* test: use statedb factory

Swapping fields on Client after it has been created is a race.

* test: lock before checking heartbeat state

Fixes races

* test: fix races by copying fsm objects

A common source of data races in tests is when they insert a fixture
directly into memdb and then later mutate the object. Since objects in
the state store are readonly, any later mutation is a data race.

* test: lock when peeking at eval stats

* test: lock when peeking at serf state

* test: lock when looking at stats

* test: fix default eval broker state test

The test was not applying the config callback. In addition the test
raced against the configuration being applied. Waiting for the keyring
to be initialized resolved the race in my testing, but given the high
concurrency of the various leadership subsystems it's possible it may
still flake.
2025-03-20 10:56:17 -07:00

74 lines
1.6 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package client
import (
"testing"
"time"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/helper/uuid"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
)
func TestHeartbeatStop_allocHook(t *testing.T) {
ci.Parallel(t)
server, _, cleanupS1 := testServer(t, nil)
defer cleanupS1()
testutil.WaitForLeader(t, server.RPC)
client, cleanupC1 := TestClient(t, func(c *config.Config) {
c.RPCHandler = server
})
defer cleanupC1()
// an allocation, with a tiny lease
d := 1 * time.Microsecond
alloc := &structs.Allocation{
ID: uuid.Generate(),
TaskGroup: "foo",
Job: &structs.Job{
TaskGroups: []*structs.TaskGroup{
{
Name: "foo",
Disconnect: &structs.DisconnectStrategy{
StopOnClientAfter: &d,
},
},
},
},
Resources: &structs.Resources{
CPU: 100,
MemoryMB: 100,
DiskMB: 0,
},
}
// alloc added to heartbeatStop.allocs
err := client.addAlloc(alloc, "")
must.NoError(t, err)
testutil.WaitForResult(func() (bool, error) {
client.heartbeatLock.Lock()
_, ok := client.heartbeatStop.allocInterval[alloc.ID]
client.heartbeatLock.Unlock()
return ok, nil
}, func(err error) {
must.NoError(t, err)
})
// the tiny lease causes the watch loop to destroy it
testutil.WaitForResult(func() (bool, error) {
_, ok := client.heartbeatStop.allocInterval[alloc.ID]
return !ok, nil
}, func(err error) {
must.NoError(t, err)
})
must.Nil(t, client.allocs[alloc.ID])
}