122 lines
2.3 KiB
Go
122 lines
2.3 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package tasklifecycle
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/nomad/ci"
|
|
"github.com/hashicorp/nomad/helper"
|
|
)
|
|
|
|
func TestGate(t *testing.T) {
|
|
ci.Parallel(t)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
test func(*testing.T, *Gate)
|
|
}{
|
|
{
|
|
name: "starts blocked",
|
|
test: func(t *testing.T, g *Gate) {
|
|
requireChannelBlocking(t, g.WaitCh(), "wait")
|
|
},
|
|
},
|
|
{
|
|
name: "block",
|
|
test: func(t *testing.T, g *Gate) {
|
|
g.Close()
|
|
requireChannelBlocking(t, g.WaitCh(), "wait")
|
|
},
|
|
},
|
|
{
|
|
name: "allow",
|
|
test: func(t *testing.T, g *Gate) {
|
|
g.Open()
|
|
requireChannelPassing(t, g.WaitCh(), "wait")
|
|
},
|
|
},
|
|
{
|
|
name: "block twice",
|
|
test: func(t *testing.T, g *Gate) {
|
|
g.Close()
|
|
g.Close()
|
|
requireChannelBlocking(t, g.WaitCh(), "wait")
|
|
},
|
|
},
|
|
{
|
|
name: "allow twice",
|
|
test: func(t *testing.T, g *Gate) {
|
|
g.Open()
|
|
g.Open()
|
|
requireChannelPassing(t, g.WaitCh(), "wait")
|
|
},
|
|
},
|
|
{
|
|
name: "allow block allow",
|
|
test: func(t *testing.T, g *Gate) {
|
|
g.Open()
|
|
requireChannelPassing(t, g.WaitCh(), "first allow")
|
|
g.Close()
|
|
requireChannelBlocking(t, g.WaitCh(), "block")
|
|
g.Open()
|
|
requireChannelPassing(t, g.WaitCh(), "second allow")
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
shutdownCh := make(chan struct{})
|
|
defer close(shutdownCh)
|
|
|
|
g := NewGate(shutdownCh)
|
|
tc.test(t, g)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestGate_shutdown tests a gate with a closed shutdown channel.
|
|
func TestGate_shutdown(t *testing.T) {
|
|
ci.Parallel(t)
|
|
|
|
// Create a Gate with a closed shutdownCh.
|
|
shutdownCh := make(chan struct{})
|
|
close(shutdownCh)
|
|
|
|
g := NewGate(shutdownCh)
|
|
|
|
// Test that Open() and Close() doesn't block forever.
|
|
openCh := make(chan struct{})
|
|
closeCh := make(chan struct{})
|
|
|
|
go func() {
|
|
g.Open()
|
|
close(openCh)
|
|
}()
|
|
go func() {
|
|
g.Close()
|
|
close(closeCh)
|
|
}()
|
|
|
|
timer, stop := helper.NewSafeTimer(time.Second)
|
|
defer stop()
|
|
|
|
select {
|
|
case <-openCh:
|
|
case <-timer.C:
|
|
t.Fatalf("timeout waiting for gate operations")
|
|
}
|
|
|
|
select {
|
|
case <-closeCh:
|
|
case <-timer.C:
|
|
t.Fatalf("timeout waiting for gate operations")
|
|
}
|
|
|
|
// A Gate with a shutdownCh should be closed.
|
|
requireChannelBlocking(t, g.WaitCh(), "gate should be closed")
|
|
}
|