open-nomad/client/allocrunner/tasklifecycle/testing.go
Luiz Aoqui 7a8cacc9ec
allocrunner: refactor task coordinator (#14009)
The current implementation for the task coordinator unblocks tasks by
performing destructive operations over its internal state (like closing
channels and deleting maps from keys).

This presents a problem in situations where we would like to revert the
state of a task, such as when restarting an allocation with tasks that
have already exited.

With this new implementation the task coordinator behaves more like a
finite state machine where task may be blocked/unblocked multiple times
by performing a state transition.

This initial part of the work only refactors the task coordinator and
is functionally equivalent to the previous implementation. Future work
will build upon this to provide bug fixes and enhancements.
2022-08-22 18:38:49 -04:00

57 lines
1.4 KiB
Go

package tasklifecycle
import (
"time"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
testing "github.com/mitchellh/go-testing-interface"
)
func RequireTaskBlocked(t testing.T, c *Coordinator, task *structs.Task) {
ch := c.StartConditionForTask(task)
requireChannelBlocking(t, ch, task.Name)
}
func RequireTaskAllowed(t testing.T, c *Coordinator, task *structs.Task) {
ch := c.StartConditionForTask(task)
requireChannelPassing(t, ch, task.Name)
}
func WaitNotInitUntil(c *Coordinator, until time.Duration, errorFunc func()) {
testutil.WaitForResultUntil(until,
func() (bool, error) {
c.currentStateLock.RLock()
defer c.currentStateLock.RUnlock()
return c.currentState != coordinatorStateInit, nil
},
func(_ error) {
errorFunc()
})
}
func requireChannelPassing(t testing.T, ch <-chan struct{}, name string) {
testutil.WaitForResult(func() (bool, error) {
return !isChannelBlocking(ch), nil
}, func(_ error) {
t.Fatalf("%s channel was blocking, should be passing", name)
})
}
func requireChannelBlocking(t testing.T, ch <-chan struct{}, name string) {
testutil.WaitForResult(func() (bool, error) {
return isChannelBlocking(ch), nil
}, func(_ error) {
t.Fatalf("%s channel was passing, should be blocking", name)
})
}
func isChannelBlocking(ch <-chan struct{}) bool {
select {
case <-ch:
return false
default:
return true
}
}