mirror of
https://github.com/containers/podman.git
synced 2025-06-19 00:06:43 +08:00
Modify unit tests for state to run on all state implementations
Signed-off-by: Matthew Heon <matthew.heon@gmail.com> Closes: #229 Approved by: rhatdan
This commit is contained in:
@ -182,6 +182,18 @@ func (s *InMemoryState) RemoveContainer(ctr *Container) error {
|
|||||||
// As all state is in-memory, no update will be required
|
// As all state is in-memory, no update will be required
|
||||||
// As such this is a no-op
|
// As such this is a no-op
|
||||||
func (s *InMemoryState) UpdateContainer(ctr *Container) error {
|
func (s *InMemoryState) UpdateContainer(ctr *Container) error {
|
||||||
|
// If the container is invalid, return error
|
||||||
|
if !ctr.valid {
|
||||||
|
return errors.Wrapf(ErrCtrRemoved, "container with ID %s is not valid", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the container does not exist, return error
|
||||||
|
_, ok := s.containers[ctr.ID()]
|
||||||
|
if !ok {
|
||||||
|
ctr.valid = false
|
||||||
|
return errors.Wrapf(ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +202,18 @@ func (s *InMemoryState) UpdateContainer(ctr *Container) error {
|
|||||||
// are made
|
// are made
|
||||||
// As such this is a no-op
|
// As such this is a no-op
|
||||||
func (s *InMemoryState) SaveContainer(ctr *Container) error {
|
func (s *InMemoryState) SaveContainer(ctr *Container) error {
|
||||||
|
// If the container is invalid, return error
|
||||||
|
if !ctr.valid {
|
||||||
|
return errors.Wrapf(ErrCtrRemoved, "container with ID %s is not valid", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the container does not exist, return error
|
||||||
|
_, ok := s.containers[ctr.ID()]
|
||||||
|
if !ok {
|
||||||
|
ctr.valid = false
|
||||||
|
return errors.Wrapf(ErrNoSuchCtr, "container with ID %s not found in state", ctr.ID())
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,6 +651,8 @@ func (s *SQLState) SaveContainer(ctr *Container) error {
|
|||||||
return errors.Wrapf(err, "error retrieving number of rows modified by update of container %s", ctr.ID())
|
return errors.Wrapf(err, "error retrieving number of rows modified by update of container %s", ctr.ID())
|
||||||
}
|
}
|
||||||
if rows == 0 {
|
if rows == 0 {
|
||||||
|
// Container was probably removed elsewhere
|
||||||
|
ctr.valid = false
|
||||||
return ErrNoSuchCtr
|
return ErrNoSuchCtr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,126 +1,59 @@
|
|||||||
package libpod
|
package libpod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
|
||||||
"github.com/opencontainers/runtime-tools/generate"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getTestContainer(id, name, locksDir string) (*Container, error) {
|
// Returns state, tmp directory containing all state files, locks directory
|
||||||
ctr := &Container{
|
// (subdirectory of tmp dir), and error
|
||||||
config: &ContainerConfig{
|
// Closing the state and removing the given tmp directory should be sufficient
|
||||||
ID: id,
|
// to clean up
|
||||||
Name: name,
|
type emptyStateFunc func() (State, string, string, error)
|
||||||
RootfsImageID: id,
|
|
||||||
RootfsImageName: "testimg",
|
const (
|
||||||
ImageVolumes: true,
|
tmpDirPrefix = "libpod_state_test_"
|
||||||
ReadOnly: true,
|
)
|
||||||
StaticDir: "/does/not/exist/",
|
|
||||||
Stdin: true,
|
var (
|
||||||
Labels: make(map[string]string),
|
testedStates = map[string]emptyStateFunc{
|
||||||
StopSignal: 0,
|
"sql": getEmptySQLState,
|
||||||
StopTimeout: 0,
|
"in-memory": getEmptyInMemoryState,
|
||||||
CreatedTime: time.Now(),
|
|
||||||
Privileged: true,
|
|
||||||
Mounts: []string{"/does/not/exist"},
|
|
||||||
DNSServer: []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.2.2")},
|
|
||||||
DNSSearch: []string{"example.com", "example.example.com"},
|
|
||||||
PortMappings: []ocicni.PortMapping{
|
|
||||||
{
|
|
||||||
HostPort: 80,
|
|
||||||
ContainerPort: 90,
|
|
||||||
Protocol: "tcp",
|
|
||||||
HostIP: "192.168.3.3",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
HostPort: 100,
|
|
||||||
ContainerPort: 110,
|
|
||||||
Protocol: "udp",
|
|
||||||
HostIP: "192.168.4.4",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
state: &containerRuntimeInfo{
|
|
||||||
State: ContainerStateRunning,
|
|
||||||
ConfigPath: "/does/not/exist/specs/" + id,
|
|
||||||
RunDir: "/does/not/exist/tmp/",
|
|
||||||
Mounted: true,
|
|
||||||
Mountpoint: "/does/not/exist/tmp/" + id,
|
|
||||||
PID: 1234,
|
|
||||||
},
|
|
||||||
valid: true,
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
g := generate.New()
|
// Get an empty in-memory state for use in tests
|
||||||
ctr.config.Spec = g.Spec()
|
func getEmptyInMemoryState() (s State, p string, p2 string, err error) {
|
||||||
|
tmpDir, err := ioutil.TempDir("", tmpDirPrefix)
|
||||||
ctr.config.Labels["test"] = "testing"
|
|
||||||
|
|
||||||
// Must make lockfile or container will error on being retrieved from DB
|
|
||||||
lockPath := filepath.Join(locksDir, id)
|
|
||||||
lock, err := storage.GetLockfile(lockPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
ctr.lock = lock
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
os.RemoveAll(tmpDir)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
return ctr, nil
|
state, err := NewInMemoryState()
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't need a separate locks dir as InMemoryState stores nothing on
|
||||||
|
// disk
|
||||||
|
return state, tmpDir, tmpDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This horrible hack tests if containers are equal in a way that should handle
|
// Get an empty SQL state for use in tests
|
||||||
// empty arrays being dropped to nil pointers in the spec JSON
|
|
||||||
func testContainersEqual(a, b *Container) bool {
|
|
||||||
if a == nil && b == nil {
|
|
||||||
return true
|
|
||||||
} else if a == nil || b == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.valid != b.valid {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
aConfigJSON, err := json.Marshal(a.config)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
bConfigJSON, err := json.Marshal(b.config)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(aConfigJSON, bConfigJSON) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
aStateJSON, err := json.Marshal(a.state)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
bStateJSON, err := json.Marshal(b.state)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return reflect.DeepEqual(aStateJSON, bStateJSON)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get an empty state for use in tests
|
|
||||||
// An empty Runtime is provided
|
// An empty Runtime is provided
|
||||||
func getEmptyState() (s State, p string, p2 string, err error) {
|
func getEmptySQLState() (s State, p string, p2 string, err error) {
|
||||||
tmpDir, err := ioutil.TempDir("", "libpod_state_test_")
|
tmpDir, err := ioutil.TempDir("", tmpDirPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", "", err
|
return nil, "", "", err
|
||||||
}
|
}
|
||||||
@ -146,12 +79,32 @@ func getEmptyState() (s State, p string, p2 string, err error) {
|
|||||||
return state, tmpDir, lockDir, nil
|
return state, tmpDir, lockDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddAndGetContainer(t *testing.T) {
|
func runForAllStates(t *testing.T, testName string, testFunc func(*testing.T, State, string)) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
for stateName, stateFunc := range testedStates {
|
||||||
assert.NoError(t, err)
|
state, path, lockPath, err := stateFunc()
|
||||||
defer os.RemoveAll(path)
|
if err != nil {
|
||||||
defer state.Close()
|
t.Fatalf("Error initializing state %s", stateName)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(path)
|
||||||
|
defer state.Close()
|
||||||
|
|
||||||
|
testName = testName + "-" + stateName
|
||||||
|
|
||||||
|
success := t.Run(testName, func(t *testing.T) {
|
||||||
|
testFunc(t, state, lockPath)
|
||||||
|
})
|
||||||
|
if !success {
|
||||||
|
t.Fail()
|
||||||
|
t.Logf("%s failed for state %s", testName, stateName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddAndGetContainer(t *testing.T) {
|
||||||
|
runForAllStates(t, "TestAddAndGetContainer", addAndGetContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addAndGetContainer(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -169,11 +122,10 @@ func TestAddAndGetContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddAndGetContainerFromMultiple(t *testing.T) {
|
func TestAddAndGetContainerFromMultiple(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestAddAndGetContainerFromMultiple", addAndGetContainerFromMultiple)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func addAndGetContainerFromMultiple(t *testing.T, state State, lockPath string) {
|
||||||
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath)
|
testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath)
|
||||||
@ -196,21 +148,19 @@ func TestAddAndGetContainerFromMultiple(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddInvalidContainerFails(t *testing.T) {
|
func TestAddInvalidContainerFails(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestAddInvalidContainerFails", addInvalidContainerFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
err = state.AddContainer(&Container{})
|
func addInvalidContainerFails(t *testing.T, state State, lockPath string) {
|
||||||
|
err := state.AddContainer(&Container{config:&ContainerConfig{ID: "1234"}})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddDuplicateIDFails(t *testing.T) {
|
func TestAddDuplicateCtrIDFails(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestAddDuplicateCtrIDFails", addDuplicateCtrIDFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func addDuplicateCtrIDFails(t *testing.T, state State, lockPath string) {
|
||||||
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
testCtr2, err := getTestContainer(testCtr1.ID(), "test2", lockPath)
|
testCtr2, err := getTestContainer(testCtr1.ID(), "test2", lockPath)
|
||||||
@ -223,12 +173,11 @@ func TestAddDuplicateIDFails(t *testing.T) {
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddDuplicateNameFails(t *testing.T) {
|
func TestAddDuplicateCtrNameFails(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestAddDuplicateCtrNameFails", addDuplicateCtrNameFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func addDuplicateCtrNameFails(t *testing.T, state State, lockPath string) {
|
||||||
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
testCtr2, err := getTestContainer("22222222222222222222222222222222", testCtr1.Name(), lockPath)
|
testCtr2, err := getTestContainer("22222222222222222222222222222222", testCtr1.Name(), lockPath)
|
||||||
@ -241,51 +190,47 @@ func TestAddDuplicateNameFails(t *testing.T) {
|
|||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNonexistantContainerFails(t *testing.T) {
|
func TestGetNonexistentContainerFails(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestGetNonexistentContainerFails", getNonexistentContainerFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
_, err = state.Container("does not exist")
|
func getNonexistentContainerFails(t *testing.T, state State, lockPath string) {
|
||||||
|
_, err := state.Container("does not exist")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContainerWithEmptyIDFails(t *testing.T) {
|
func TestGetContainerWithEmptyIDFails(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestGetContainerWithEmptyIDFails", getContainerWithEmptyIDFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
_, err = state.Container("")
|
func getContainerWithEmptyIDFails(t *testing.T, state State, lockPath string) {
|
||||||
|
_, err := state.Container("")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerWithEmptyIDFails(t *testing.T) {
|
func TestLookupContainerWithEmptyIDFails(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestLookupContainerWithEmptyIDFails", lookupContainerWithEmptyIDFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
_, err = state.LookupContainer("")
|
func lookupContainerWithEmptyIDFails(t *testing.T, state State, lockPath string) {
|
||||||
|
_, err := state.LookupContainer("")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupNonexistantContainerFails(t *testing.T) {
|
func TestLookupNonexistentContainerFails(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestLookupNonexistantContainerFails", lookupNonexistentContainerFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
|
|
||||||
_, err = state.LookupContainer("does not exist")
|
func lookupNonexistentContainerFails(t *testing.T, state State, lockPath string) {
|
||||||
|
_, err := state.LookupContainer("does not exist")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByFullID(t *testing.T) {
|
func TestLookupContainerByFullID(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestLookupContainerByFullID", lookupContainerByFullID)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func lookupContainerByFullID(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -303,11 +248,10 @@ func TestLookupContainerByFullID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByUniquePartialID(t *testing.T) {
|
func TestLookupContainerByUniquePartialID(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestLookupContainerByUniquePartialID", lookupContainerByUniquePartialID)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func lookupContainerByUniquePartialID(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -325,11 +269,10 @@ func TestLookupContainerByUniquePartialID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) {
|
func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestLookupContainerByNonUniquePartialIDFails", lookupContainerByNonUniquePartialIDFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func lookupContainerByNonUniquePartialIDFails(t *testing.T, state State, lockPath string) {
|
||||||
testCtr1, err := getTestContainer("00000000000000000000000000000000", "test1", lockPath)
|
testCtr1, err := getTestContainer("00000000000000000000000000000000", "test1", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
testCtr2, err := getTestContainer("00000000000000000000000000000001", "test2", lockPath)
|
testCtr2, err := getTestContainer("00000000000000000000000000000001", "test2", lockPath)
|
||||||
@ -346,7 +289,11 @@ func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLookupContainerByName(t *testing.T) {
|
func TestLookupContainerByName(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestLookupContainerByName", lookupContainerByName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookupContainerByName(t *testing.T, state State, lockPath string) {
|
||||||
|
state, path, lockPath, err := getEmptySQLState()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
defer state.Close()
|
defer state.Close()
|
||||||
@ -368,32 +315,29 @@ func TestLookupContainerByName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHasContainerEmptyIDFails(t *testing.T) {
|
func TestHasContainerEmptyIDFails(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestHasContainerEmptyIDFails", hasContainerEmptyIDFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
_, err = state.HasContainer("")
|
func hasContainerEmptyIDFails(t *testing.T, state State, lockPath string) {
|
||||||
|
_, err := state.HasContainer("")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) {
|
func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestHasContainerNoSuchContainerReturnsFalse", hasContainerNoSuchContainerReturnsFalse)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func hasContainerNoSuchContainerReturnsFalse(t *testing.T, state State, lockPath string) {
|
||||||
exists, err := state.HasContainer("does not exist")
|
exists, err := state.HasContainer("does not exist")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, exists)
|
assert.False(t, exists)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasContainerFindsContainer(t *testing.T) {
|
func TestHasContainerFindsContainer(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestHasContainerFindsContainer", hasContainerFindsContainer)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func hasContainerFindsContainer(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -406,11 +350,10 @@ func TestHasContainerFindsContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSaveAndUpdateContainer(t *testing.T) {
|
func TestSaveAndUpdateContainer(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestSaveAndUpdateContainer", saveAndUpdateContainer)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func saveAndUpdateContainer(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -438,11 +381,10 @@ func TestSaveAndUpdateContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) {
|
func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestUpdateContainerNotInDatabaseReturnsError", updateContainerNotInDatabaseReturnsError)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func updateContainerNotInDatabaseReturnsError(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -452,44 +394,41 @@ func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateInvalidContainerReturnsError(t *testing.T) {
|
func TestUpdateInvalidContainerReturnsError(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestUpdateInvalidContainerReturnsError", updateInvalidContainerReturnsError)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
err = state.UpdateContainer(&Container{})
|
func updateInvalidContainerReturnsError(t *testing.T, state State, lockPath string) {
|
||||||
|
err := state.UpdateContainer(&Container{config:&ContainerConfig{ID: "1234"}})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSaveInvalidContainerReturnsError(t *testing.T) {
|
func TestSaveInvalidContainerReturnsError(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestSaveInvalidContainerReturnsError", saveInvalidContainerReturnsError)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
err = state.SaveContainer(&Container{})
|
func saveInvalidContainerReturnsError(t *testing.T, state State, lockPath string) {
|
||||||
|
err := state.SaveContainer(&Container{config:&ContainerConfig{ID: "1234"}})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSaveContainerNotInStateReturnsError(t *testing.T) {
|
func TestSaveContainerNotInStateReturnsError(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestSaveContainerNotInStateReturnsError", saveContainerNotInStateReturnsError)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func saveContainerNotInStateReturnsError(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = state.SaveContainer(testCtr)
|
err = state.SaveContainer(testCtr)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
assert.False(t, testCtr.valid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveContainer(t *testing.T) {
|
func TestRemoveContainer(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestRemoveContainer", removeContainer)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func removeContainer(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -509,11 +448,10 @@ func TestRemoveContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveNonexistantContainerFails(t *testing.T) {
|
func TestRemoveNonexistantContainerFails(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestRemoveNonexistantContainerFails", removeNonexistantContainerFails)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func removeNonexistantContainerFails(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -522,22 +460,20 @@ func TestRemoveNonexistantContainerFails(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) {
|
func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) {
|
||||||
state, path, _, err := getEmptyState()
|
runForAllStates(t, "TestGetAllContainersOnNewStateIsEmpty", getAllContainersOnNewStateIsEmpty)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func getAllContainersOnNewStateIsEmpty(t *testing.T, state State, lockPath string) {
|
||||||
ctrs, err := state.AllContainers()
|
ctrs, err := state.AllContainers()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 0, len(ctrs))
|
assert.Equal(t, 0, len(ctrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllContainersWithOneContainer(t *testing.T) {
|
func TestGetAllContainersWithOneContainer(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestGetAllContainersWithOneContainer", getAllContainersWithOneContainer)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func getAllContainersWithOneContainer(t *testing.T, state State, lockPath string) {
|
||||||
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@ -556,11 +492,10 @@ func TestGetAllContainersWithOneContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllContainersTwoContainers(t *testing.T) {
|
func TestGetAllContainersTwoContainers(t *testing.T) {
|
||||||
state, path, lockPath, err := getEmptyState()
|
runForAllStates(t, "TestGetAllContainersTwoContainers", getAllContainersTwoContainers)
|
||||||
assert.NoError(t, err)
|
}
|
||||||
defer os.RemoveAll(path)
|
|
||||||
defer state.Close()
|
|
||||||
|
|
||||||
|
func getAllContainersTwoContainers(t *testing.T, state State, lockPath string) {
|
||||||
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath)
|
testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath)
|
||||||
@ -575,17 +510,6 @@ func TestGetAllContainersTwoContainers(t *testing.T) {
|
|||||||
ctrs, err := state.AllContainers()
|
ctrs, err := state.AllContainers()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 2, len(ctrs))
|
assert.Equal(t, 2, len(ctrs))
|
||||||
|
|
||||||
// Containers should be ordered by creation time
|
|
||||||
|
|
||||||
// Use assert.EqualValues if the test fails to pretty print diff
|
|
||||||
// between actual and expected
|
|
||||||
if !testContainersEqual(testCtr2, ctrs[0]) {
|
|
||||||
assert.EqualValues(t, testCtr2, ctrs[0])
|
|
||||||
}
|
|
||||||
if !testContainersEqual(testCtr1, ctrs[1]) {
|
|
||||||
assert.EqualValues(t, testCtr1, ctrs[1])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContainerInUseInvalidContainer(t *testing.T) {
|
func TestContainerInUseInvalidContainer(t *testing.T) {
|
114
libpod/test_common.go
Normal file
114
libpod/test_common.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package libpod
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/storage"
|
||||||
|
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||||
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getTestContainer(id, name, locksDir string) (*Container, error) {
|
||||||
|
ctr := &Container{
|
||||||
|
config: &ContainerConfig{
|
||||||
|
ID: id,
|
||||||
|
Name: name,
|
||||||
|
RootfsImageID: id,
|
||||||
|
RootfsImageName: "testimg",
|
||||||
|
ImageVolumes: true,
|
||||||
|
ReadOnly: true,
|
||||||
|
StaticDir: "/does/not/exist/",
|
||||||
|
Stdin: true,
|
||||||
|
Labels: make(map[string]string),
|
||||||
|
StopSignal: 0,
|
||||||
|
StopTimeout: 0,
|
||||||
|
CreatedTime: time.Now(),
|
||||||
|
Privileged: true,
|
||||||
|
Mounts: []string{"/does/not/exist"},
|
||||||
|
DNSServer: []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.2.2")},
|
||||||
|
DNSSearch: []string{"example.com", "example.example.com"},
|
||||||
|
PortMappings: []ocicni.PortMapping{
|
||||||
|
{
|
||||||
|
HostPort: 80,
|
||||||
|
ContainerPort: 90,
|
||||||
|
Protocol: "tcp",
|
||||||
|
HostIP: "192.168.3.3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
HostPort: 100,
|
||||||
|
ContainerPort: 110,
|
||||||
|
Protocol: "udp",
|
||||||
|
HostIP: "192.168.4.4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
state: &containerRuntimeInfo{
|
||||||
|
State: ContainerStateRunning,
|
||||||
|
ConfigPath: "/does/not/exist/specs/" + id,
|
||||||
|
RunDir: "/does/not/exist/tmp/",
|
||||||
|
Mounted: true,
|
||||||
|
Mountpoint: "/does/not/exist/tmp/" + id,
|
||||||
|
PID: 1234,
|
||||||
|
},
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
g := generate.New()
|
||||||
|
ctr.config.Spec = g.Spec()
|
||||||
|
|
||||||
|
ctr.config.Labels["test"] = "testing"
|
||||||
|
|
||||||
|
// Must make lockfile or container will error on being retrieved from DB
|
||||||
|
lockPath := filepath.Join(locksDir, id)
|
||||||
|
lock, err := storage.GetLockfile(lockPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctr.lock = lock
|
||||||
|
|
||||||
|
return ctr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This horrible hack tests if containers are equal in a way that should handle
|
||||||
|
// empty arrays being dropped to nil pointers in the spec JSON
|
||||||
|
func testContainersEqual(a, b *Container) bool {
|
||||||
|
if a == nil && b == nil {
|
||||||
|
return true
|
||||||
|
} else if a == nil || b == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.valid != b.valid {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aConfigJSON, err := json.Marshal(a.config)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
bConfigJSON, err := json.Marshal(b.config)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(aConfigJSON, bConfigJSON) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
aStateJSON, err := json.Marshal(a.state)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
bStateJSON, err := json.Marshal(b.state)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.DeepEqual(aStateJSON, bStateJSON)
|
||||||
|
}
|
Reference in New Issue
Block a user