Skip to content

Commit

Permalink
libcontainer/state_linux_test: Add a testTransitions helper
Browse files Browse the repository at this point in the history
The helper DRYs up the transition tests and makes it easy to get
complete coverage for invalid transitions.

I'm also using t.Run() for subtests.  Run() is new in Go 1.7 [1], but
runc dropped support for 1.6 back in e773f96 (update go version at
travis-ci, 2017-02-20, #1335).

[1]: https://blog.golang.org/subtests

Signed-off-by: W. Trevor King <wking@tremily.us>
  • Loading branch information
wking committed Jan 25, 2018
1 parent c4e4bb0 commit be16b13
Showing 1 changed file with 83 additions and 84 deletions.
167 changes: 83 additions & 84 deletions libcontainer/state_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@

package libcontainer

import "testing"
import (
"reflect"
"testing"
)

var states = map[containerState]Status{
&createdState{}: Created,
&runningState{}: Running,
&restoredState{}: Running,
&pausedState{}: Paused,
&stoppedState{}: Stopped,
&loadedState{s: Running}: Running,
}

func TestStateStatus(t *testing.T) {
states := map[containerState]Status{
&stoppedState{}: Stopped,
&runningState{}: Running,
&restoredState{}: Running,
&pausedState{}: Paused,
&createdState{}: Created,
}
for s, status := range states {
if s.status() != status {
t.Fatalf("state returned %s but expected %s", s.status(), status)
Expand All @@ -24,94 +29,88 @@ func isStateTransitionError(err error) bool {
return ok
}

func TestStoppedStateTransition(t *testing.T) {
s := &stoppedState{c: &linuxContainer{}}
valid := []containerState{
&stoppedState{},
&runningState{},
&restoredState{},
}
for _, v := range valid {
if err := s.transition(v); err != nil {
t.Fatal(err)
func testTransitions(t *testing.T, initialState containerState, valid []containerState) {
validMap := map[reflect.Type]interface{}{}
for _, validState := range valid {
validMap[reflect.TypeOf(validState)] = nil
t.Run(validState.status().String(), func(t *testing.T) {
if err := initialState.transition(validState); err != nil {
t.Fatal(err)
}
})
}
for state := range states {
if _, ok := validMap[reflect.TypeOf(state)]; ok {
continue
}
}
err := s.transition(&pausedState{})
if err == nil {
t.Fatal("transition to paused state should fail")
}
if !isStateTransitionError(err) {
t.Fatal("expected stateTransitionError")
t.Run(state.status().String(), func(t *testing.T) {
err := initialState.transition(state)
if err == nil {
t.Fatal("transition should fail")
}
if !isStateTransitionError(err) {
t.Fatal("expected stateTransitionError")
}
})
}
}

func TestStoppedStateTransition(t *testing.T) {
testTransitions(
t,
&stoppedState{c: &linuxContainer{}},
[]containerState{
&stoppedState{},
&runningState{},
&restoredState{},
},
)
}

func TestPausedStateTransition(t *testing.T) {
s := &pausedState{c: &linuxContainer{}}
valid := []containerState{
&pausedState{},
&runningState{},
&stoppedState{},
}
for _, v := range valid {
if err := s.transition(v); err != nil {
t.Fatal(err)
}
}
testTransitions(
t,
&pausedState{c: &linuxContainer{}},
[]containerState{
&pausedState{},
&runningState{},
&stoppedState{},
},
)
}

func TestRestoredStateTransition(t *testing.T) {
s := &restoredState{c: &linuxContainer{}}
valid := []containerState{
&stoppedState{},
&runningState{},
}
for _, v := range valid {
if err := s.transition(v); err != nil {
t.Fatal(err)
}
}
err := s.transition(&createdState{})
if err == nil {
t.Fatal("transition to created state should fail")
}
if !isStateTransitionError(err) {
t.Fatal("expected stateTransitionError")
}
testTransitions(
t,
&restoredState{c: &linuxContainer{}},
[]containerState{
&stoppedState{},
&runningState{},
},
)
}

func TestRunningStateTransition(t *testing.T) {
s := &runningState{c: &linuxContainer{}}
valid := []containerState{
&stoppedState{},
&pausedState{},
&runningState{},
}
for _, v := range valid {
if err := s.transition(v); err != nil {
t.Fatal(err)
}
}

err := s.transition(&createdState{})
if err == nil {
t.Fatal("transition to created state should fail")
}
if !isStateTransitionError(err) {
t.Fatal("expected stateTransitionError")
}
testTransitions(
t,
&runningState{c: &linuxContainer{}},
[]containerState{
&stoppedState{},
&pausedState{},
&runningState{},
},
)
}

func TestCreatedStateTransition(t *testing.T) {
s := &createdState{c: &linuxContainer{}}
valid := []containerState{
&stoppedState{},
&pausedState{},
&runningState{},
&createdState{},
}
for _, v := range valid {
if err := s.transition(v); err != nil {
t.Fatal(err)
}
}
testTransitions(
t,
&createdState{c: &linuxContainer{}},
[]containerState{
&stoppedState{},
&pausedState{},
&runningState{},
&createdState{},
},
)
}

0 comments on commit be16b13

Please sign in to comment.