open-nomad/client/allocrunner/tasklifecycle/gate_test.go
2023-04-10 15:36:59 +00:00

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")
}