summaryrefslogtreecommitdiff
path: root/libpod/sql_state_test.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-20 15:43:56 -0500
committerMatthew Heon <matthew.heon@gmail.com>2017-11-20 16:24:28 -0500
commit51fc8827f54436864924ea8d4dc96111da81e5bf (patch)
tree312ed45344f42d0c16ef7b0cb5fecd1316d20f0b /libpod/sql_state_test.go
parent5d52f74d2136786c2874898ad373808e25609545 (diff)
downloadpodman-51fc8827f54436864924ea8d4dc96111da81e5bf.tar.gz
podman-51fc8827f54436864924ea8d4dc96111da81e5bf.tar.bz2
podman-51fc8827f54436864924ea8d4dc96111da81e5bf.zip
Add tests for SQL-backed state impl
Minor changes to container.go and sql_state.go to fix issues identified by the tests Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'libpod/sql_state_test.go')
-rw-r--r--libpod/sql_state_test.go520
1 files changed, 520 insertions, 0 deletions
diff --git a/libpod/sql_state_test.go b/libpod/sql_state_test.go
new file mode 100644
index 000000000..b50f3aced
--- /dev/null
+++ b/libpod/sql_state_test.go
@@ -0,0 +1,520 @@
+package libpod
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/opencontainers/runtime-tools/generate"
+ "github.com/stretchr/testify/assert"
+)
+
+func getTestContainer(id, name string) *Container {
+ ctr := &Container{
+ config: &containerConfig{
+ ID: id,
+ Name: name,
+ RootfsImageID: id,
+ RootfsImageName: "testimg",
+ UseImageConfig: true,
+ StaticDir: "/does/not/exist/",
+ Stdin: true,
+ Labels: make(map[string]string),
+ StopSignal: 0,
+ CreatedTime: time.Now(),
+ },
+ state: &containerRuntimeInfo{
+ State: ContainerStateRunning,
+ ConfigPath: "/does/not/exist/specs/" + id,
+ RunDir: "/does/not/exist/tmp/",
+ Mounted: true,
+ Mountpoint: "/does/not/exist/tmp/" + id,
+ },
+ valid: true,
+ }
+
+ g := generate.New()
+ ctr.config.Spec = g.Spec()
+
+ ctr.config.Labels["test"] = "testing"
+
+ return ctr
+}
+
+// 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)
+}
+
+// Get an empty state for use in tests
+// An empty Runtime is provided
+func getEmptyState() (s State, p string, err error) {
+ tmpDir, err := ioutil.TempDir("", "libpod_state_test_")
+ if err != nil {
+ return nil, "", err
+ }
+ defer func() {
+ if err != nil {
+ os.RemoveAll(tmpDir)
+ }
+ }()
+
+ dbPath := filepath.Join(tmpDir, "db.sql")
+ lockPath := filepath.Join(tmpDir, "db.lck")
+
+ state, err := NewSQLState(dbPath, lockPath, tmpDir, nil)
+ if err != nil {
+ return nil, "", err
+ }
+
+ return state, tmpDir, nil
+}
+
+func TestAddAndGetContainer(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ retrievedCtr, err := state.Container(testCtr.ID())
+ assert.NoError(t, err)
+
+ // Use assert.EqualValues if the test fails to pretty print diff
+ // between actual and expected
+ if !testContainersEqual(testCtr, retrievedCtr) {
+ assert.EqualValues(t, testCtr, retrievedCtr)
+ }
+}
+
+func TestAddAndGetContainerFromMultiple(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
+ testCtr2 := getTestContainer("22222222222222222222222222222222", "test2")
+
+ err = state.AddContainer(testCtr1)
+ assert.NoError(t, err)
+
+ err = state.AddContainer(testCtr2)
+ assert.NoError(t, err)
+
+ retrievedCtr, err := state.Container(testCtr1.ID())
+ assert.NoError(t, err)
+
+ // Use assert.EqualValues if the test fails to pretty print diff
+ // between actual and expected
+ if !testContainersEqual(testCtr1, retrievedCtr) {
+ assert.EqualValues(t, testCtr1, retrievedCtr)
+ }
+}
+
+func TestAddInvalidContainerFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ err = state.AddContainer(&Container{})
+ assert.Error(t, err)
+}
+
+func TestAddDuplicateIDFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
+ testCtr2 := getTestContainer(testCtr1.ID(), "test2")
+
+ err = state.AddContainer(testCtr1)
+ assert.NoError(t, err)
+
+ err = state.AddContainer(testCtr2)
+ assert.Error(t, err)
+}
+
+func TestAddDuplicateNameFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
+ testCtr2 := getTestContainer("22222222222222222222222222222222", testCtr1.Name())
+
+ err = state.AddContainer(testCtr1)
+ assert.NoError(t, err)
+
+ err = state.AddContainer(testCtr2)
+ assert.Error(t, err)
+}
+
+func TestGetNonexistantContainerFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ _, err = state.Container("does not exist")
+ assert.Error(t, err)
+}
+
+func TestGetContainerWithEmptyIDFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ _, err = state.Container("")
+ assert.Error(t, err)
+}
+
+func TestLookupContainerWithEmptyIDFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ _, err = state.LookupContainer("")
+ assert.Error(t, err)
+}
+
+func TestLookupNonexistantContainerFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+
+ _, err = state.LookupContainer("does not exist")
+ assert.Error(t, err)
+}
+
+func TestLookupContainerByFullID(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ retrievedCtr, err := state.LookupContainer(testCtr.ID())
+ assert.NoError(t, err)
+
+ // Use assert.EqualValues if the test fails to pretty print diff
+ // between actual and expected
+ if !testContainersEqual(testCtr, retrievedCtr) {
+ assert.EqualValues(t, testCtr, retrievedCtr)
+ }
+}
+
+func TestLookupContainerByUniquePartialID(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ retrievedCtr, err := state.LookupContainer(testCtr.ID()[0:8])
+ assert.NoError(t, err)
+
+ // Use assert.EqualValues if the test fails to pretty print diff
+ // between actual and expected
+ if !testContainersEqual(testCtr, retrievedCtr) {
+ assert.EqualValues(t, testCtr, retrievedCtr)
+ }
+}
+
+func TestLookupContainerByNonUniquePartialIDFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr1 := getTestContainer("00000000000000000000000000000000", "test1")
+ testCtr2 := getTestContainer("00000000000000000000000000000001", "test2")
+
+ err = state.AddContainer(testCtr1)
+ assert.NoError(t, err)
+
+ err = state.AddContainer(testCtr2)
+ assert.NoError(t, err)
+
+ _, err = state.LookupContainer(testCtr1.ID()[0:8])
+ assert.Error(t, err)
+}
+
+func TestLookupContainerByName(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ retrievedCtr, err := state.LookupContainer(testCtr.Name())
+ assert.NoError(t, err)
+
+ // Use assert.EqualValues if the test fails to pretty print diff
+ // between actual and expected
+ if !testContainersEqual(testCtr, retrievedCtr) {
+ assert.EqualValues(t, testCtr, retrievedCtr)
+ }
+}
+
+func TestHasContainerEmptyIDFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ _, err = state.HasContainer("")
+ assert.Error(t, err)
+}
+
+func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ exists, err := state.HasContainer("does not exist")
+ assert.NoError(t, err)
+ assert.False(t, exists)
+}
+
+func TestHasContainerFindsContainer(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ exists, err := state.HasContainer(testCtr.ID())
+ assert.NoError(t, err)
+ assert.True(t, exists)
+}
+
+func TestSaveAndUpdateContainer(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ retrievedCtr, err := state.Container(testCtr.ID())
+ assert.NoError(t, err)
+
+ retrievedCtr.state.State = ContainerStateStopped
+ retrievedCtr.state.ExitCode = 127
+ retrievedCtr.state.FinishedTime = time.Now()
+
+ err = state.SaveContainer(retrievedCtr)
+ assert.NoError(t, err)
+
+ err = state.UpdateContainer(testCtr)
+ assert.NoError(t, err)
+
+ // Use assert.EqualValues if the test fails to pretty print diff
+ // between actual and expected
+ if !testContainersEqual(testCtr, retrievedCtr) {
+ assert.EqualValues(t, testCtr, retrievedCtr)
+ }
+}
+
+func TestUpdateContainerNotInDatabaseReturnsError(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.UpdateContainer(testCtr)
+ assert.Error(t, err)
+ assert.False(t, testCtr.valid)
+}
+
+func TestUpdateInvalidContainerReturnsError(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ err = state.UpdateContainer(&Container{})
+ assert.Error(t, err)
+}
+
+func TestSaveInvalidContainerReturnsError(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ err = state.SaveContainer(&Container{})
+ assert.Error(t, err)
+}
+
+func TestSaveContainerNotInStateReturnsError(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.SaveContainer(testCtr)
+ assert.Error(t, err)
+}
+
+func TestRemoveContainer(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ ctrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 1, len(ctrs))
+
+ err = state.RemoveContainer(testCtr)
+ assert.NoError(t, err)
+
+ ctrs2, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(ctrs2))
+}
+
+func TestRemoveNonexistantContainerFails(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.RemoveContainer(testCtr)
+ assert.Error(t, err)
+}
+
+func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ ctrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 0, len(ctrs))
+}
+
+func TestGetAllContainersWithOneContainer(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test")
+
+ err = state.AddContainer(testCtr)
+ assert.NoError(t, err)
+
+ ctrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 1, len(ctrs))
+
+ // Use assert.EqualValues if the test fails to pretty print diff
+ // between actual and expected
+ if !testContainersEqual(testCtr, ctrs[0]) {
+ assert.EqualValues(t, testCtr, ctrs[0])
+ }
+}
+
+func TestGetAllContainersTwoContainers(t *testing.T) {
+ state, path, err := getEmptyState()
+ assert.NoError(t, err)
+ defer os.RemoveAll(path)
+ defer state.Close()
+
+ testCtr1 := getTestContainer("11111111111111111111111111111111", "test1")
+ testCtr2 := getTestContainer("22222222222222222222222222222222", "test2")
+
+ err = state.AddContainer(testCtr1)
+ assert.NoError(t, err)
+
+ err = state.AddContainer(testCtr2)
+ assert.NoError(t, err)
+
+ ctrs, err := state.AllContainers()
+ assert.NoError(t, err)
+ assert.Equal(t, 2, len(ctrs))
+}