diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2018-01-29 04:59:25 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-02-09 15:01:34 +0000 |
commit | 4ecebf20b4e41720b9a0b55e0c22f05061c77e60 (patch) | |
tree | c1864f919fe7f4290b190ac2f330d97e466af58b /libpod | |
parent | 0920e8de5a08328cceb70617ee04ef177b30d355 (diff) | |
download | podman-4ecebf20b4e41720b9a0b55e0c22f05061c77e60.tar.gz podman-4ecebf20b4e41720b9a0b55e0c22f05061c77e60.tar.bz2 podman-4ecebf20b4e41720b9a0b55e0c22f05061c77e60.zip |
Rework state tests to avoid boilerplate. Begin adding pod tests.
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Closes: #268
Approved by: rhatdan
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/in_memory_state.go | 8 | ||||
-rw-r--r-- | libpod/pod.go | 6 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 3 | ||||
-rw-r--r-- | libpod/sql_state.go | 28 | ||||
-rw-r--r-- | libpod/sql_state_internal.go | 42 | ||||
-rw-r--r-- | libpod/state_test.go | 989 | ||||
-rw-r--r-- | libpod/test_common.go | 44 |
7 files changed, 747 insertions, 373 deletions
diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index d85ea1399..c057f6804 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -8,9 +8,9 @@ import ( "github.com/projectatomic/libpod/pkg/registrar" ) -// TODO: unified name/ID registry to ensure no name and ID conflicts between -// containers and pods -// This can probably be used to replace the existing trunc index and registrars +// TODO: Maybe separate idIndex for pod/containers +// As of right now, partial IDs used in Lookup... need to be unique as well +// This may be undesirable? // An InMemoryState is a purely in-memory state store type InMemoryState struct { @@ -486,7 +486,7 @@ func (s *InMemoryState) AddContainerToPod(pod *Pod, ctr *Container) error { } // Is the container already in the pod? - if _, ok := podCtrs[ctr.ID()]; ok { + if _, ok = podCtrs[ctr.ID()]; ok { return errors.Wrapf(ErrCtrExists, "container with ID %s already exists in pod %s", ctr.ID(), pod.ID()) } diff --git a/libpod/pod.go b/libpod/pod.go index 91636546d..4f5521ccb 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -17,7 +17,7 @@ type Pod struct { valid bool runtime *Runtime - lock storage.Locker + lock storage.Locker } // ID retrieves the pod's ID @@ -59,7 +59,7 @@ func newPod(lockDir string, runtime *Runtime) (*Pod, error) { return pod, nil } -// Init() initializes all containers within a pod that have not been initialized +// Init initializes all containers within a pod that have not been initialized func (p *Pod) Init() error { return ErrNotImplemented } @@ -88,7 +88,7 @@ func (p *Pod) HasContainer(id string) (bool, error) { return p.runtime.state.PodHasContainer(p, id) } -// AllContainersID returns the container IDs of all the containers in the pod +// AllContainersByID returns the container IDs of all the containers in the pod func (p *Pod) AllContainersByID() ([]string, error) { p.lock.Lock() defer p.lock.Unlock() diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 942535343..e1c80772e 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -121,8 +121,9 @@ func (r *Runtime) removeContainer(c *Container, force bool) error { // We need to lock the pod before we lock the container // To avoid races around removing a container and the pod it is in var pod *Pod + var err error if c.config.Pod != "" { - pod, err := r.state.Pod(c.config.Pod) + pod, err = r.state.Pod(c.config.Pod) if err != nil { return errors.Wrapf(err, "container %s is in pod %s, but pod cannot be retrieved", c.ID(), pod.ID()) } diff --git a/libpod/sql_state.go b/libpod/sql_state.go index b7fd0dac7..a5809fe58 100644 --- a/libpod/sql_state.go +++ b/libpod/sql_state.go @@ -754,7 +754,10 @@ func (s *SQLState) PodContainers(pod *Pod) ([]*Container, error) { // AddPod adds a pod to the state // Only empty pods can be added to the state func (s *SQLState) AddPod(pod *Pod) (err error) { - const query = "INSERT INTO pods VALUES (?, ?, ?);" + const ( + podQuery = "INSERT INTO pods VALUES (?, ?, ?);" + registryQuery = "INSERT INTO registry VALUES (?, ?);" + ) if !s.valid { return ErrDBClosed @@ -781,8 +784,11 @@ func (s *SQLState) AddPod(pod *Pod) (err error) { } }() - _, err = tx.Exec(query, pod.ID(), pod.Name(), string(labelsJSON)) - if err != nil { + if _, err := tx.Exec(registryQuery, pod.ID(), pod.Name()); err != nil { + return errors.Wrapf(err, "error adding pod %s to name/ID registry", pod.ID()) + } + + if _, err = tx.Exec(podQuery, pod.ID(), pod.Name(), string(labelsJSON)); err != nil { return errors.Wrapf(err, "error adding pod %s to database", pod.ID()) } @@ -796,7 +802,10 @@ func (s *SQLState) AddPod(pod *Pod) (err error) { // RemovePod removes a pod from the state // Only empty pods can be removed func (s *SQLState) RemovePod(pod *Pod) error { - const query = "DELETE FROM pods WHERE ID=?;" + const ( + removePod = "DELETE FROM pods WHERE ID=?;" + removeRegistry = "DELETE FROM registry WHERE Id=?;" + ) if !s.valid { return ErrDBClosed @@ -814,8 +823,8 @@ func (s *SQLState) RemovePod(pod *Pod) error { } }() - // Check rows acted on for the first transaction, verify we actually removed something - result, err := tx.Exec(query, pod.ID()) + // Check rows acted on for the first statement, verify we actually removed something + result, err := tx.Exec(removePod, pod.ID()) if err != nil { return errors.Wrapf(err, "error removing pod %s from pods table", pod.ID()) } @@ -826,6 +835,11 @@ func (s *SQLState) RemovePod(pod *Pod) error { return ErrNoSuchPod } + // We know it exists, remove it from registry + if _, err := tx.Exec(removeRegistry, pod.ID()); err != nil { + return errors.Wrapf(err, "error removing pod %s from name/ID registry", pod.ID()) + } + if err := tx.Commit(); err != nil { return errors.Wrapf(err, "error committing transaction to remove pod %s", pod.ID()) } @@ -891,7 +905,7 @@ func (s *SQLState) RemovePodContainers(pod *Pod) error { return errors.Wrapf(err, "error retrieving container rows") } - // Have container IDs, now exec SQL to remove contianers in the pod + // Have container IDs, now exec SQL to remove containers in the pod // Remove state first, as it needs the subquery on containers // Don't bother checking if we actually removed anything, we just want to // empty the pod diff --git a/libpod/sql_state_internal.go b/libpod/sql_state_internal.go index 064be7955..f2b0d603c 100644 --- a/libpod/sql_state_internal.go +++ b/libpod/sql_state_internal.go @@ -173,9 +173,6 @@ func checkDB(db *sql.DB, r *Runtime) (err error) { // Performs database setup including by not limited to initializing tables in // the database func prepareDB(db *sql.DB) (err error) { - // TODO create pod tables - // TODO add Pod ID to CreateStaticContainer as a FOREIGN KEY referencing podStatic(Id) - // TODO add ctr shared namespaces information - A separate table, probably? So we can FOREIGN KEY the ID // TODO schema migration might be necessary and should be handled here // TODO maybe make a port mappings table instead of JSONing the array and storing it? // TODO prepared statements for common queries for performance @@ -185,6 +182,14 @@ func prepareDB(db *sql.DB) (err error) { return errors.Wrapf(err, "error enabling foreign key support in database") } + // Create a table for holding container and pod names and IDs + const createRegistry = ` + CREATE TABLE IF NOT EXISTS registry( + Id TEXT NOT NULL PRIMARY KEY, + Name TEXT NOT NULL UNIQUE + ); + ` + // Create a table for unchanging container data const createCtr = ` CREATE TABLE IF NOT EXISTS containers( @@ -235,7 +240,9 @@ func prepareDB(db *sql.DB) (err error) { CHECK (CreateNetNS IN (0, 1)), CHECK (Stdin IN (0, 1)), CHECK (StopSignal>=0), - FOREIGN KEY (Id) REFERENCES containerState(Id) DEFERRABLE INITIALLY DEFERRED + FOREIGN KEY (Id) REFERENCES registry(Id) DEFERRABLE INITIALLY DEFERRED, + FOREIGN KEY (Id) REFERENCES containerState(Id) DEFERRABLE INITIALLY DEFERRED, + FOREIGN KEY (Name) REFERENCES registry(Name) DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (Pod) REFERENCES pods(Id) DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (IPCNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED, FOREIGN KEY (MountNsCtr) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED, @@ -266,7 +273,8 @@ func prepareDB(db *sql.DB) (err error) { CHECK (State>0), CHECK (OomKilled IN (0, 1)), - FOREIGN KEY (Id) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED + FOREIGN KEY (Id) REFERENCES registry(Id) DEFERRABLE INITIALLY DEFERRED, + FOREIGN KEY (Id) REFERENCES containers(Id) DEFERRABLE INITIALLY DEFERRED ); ` @@ -275,7 +283,9 @@ func prepareDB(db *sql.DB) (err error) { CREATE TABLE IF NOT EXISTS pods( Id TEXT NOT NULL PRIMARY KEY, Name TEXT NOT NULL UNIQUE, - Labels TEXT NOT NULL + Labels TEXT NOT NULL, + FOREIGN KEY (Id) REFERENCES registry(Id) DEFERRABLE INITIALLY DEFERRED, + FOREIGN KEY (Name) REFERENCES registry(Name) DEFERRABLE INITIALLY DEFERRED ); ` @@ -293,6 +303,9 @@ func prepareDB(db *sql.DB) (err error) { }() + if _, err := tx.Exec(createRegistry); err != nil { + return errors.Wrapf(err, "error creating ID and Name registry in database") + } if _, err := tx.Exec(createCtr); err != nil { return errors.Wrapf(err, "error creating containers table in database") } @@ -720,6 +733,7 @@ func (s *SQLState) addContainer(ctr *Container) (err error) { ?, ?, ?, ?, ?, ?, ?, ? );` + addRegistry = "INSERT INTO registry VALUES (?, ?);" ) if !s.valid { @@ -786,6 +800,11 @@ func (s *SQLState) addContainer(ctr *Container) (err error) { } }() + // Add container to registry + if _, err := tx.Exec(addRegistry, ctr.ID(), ctr.Name()); err != nil { + return errors.Wrapf(err, "error adding container %s to name/ID registry", ctr.ID()) + } + // Add static container information _, err = tx.Exec(addCtr, ctr.ID(), @@ -888,8 +907,9 @@ func (s *SQLState) addContainer(ctr *Container) (err error) { // Internal functions for removing containers func (s *SQLState) removeContainer(ctr *Container) error { const ( - removeCtr = "DELETE FROM containers WHERE Id=?;" - removeState = "DELETE FROM containerState WHERE Id=?;" + removeCtr = "DELETE FROM containers WHERE Id=?;" + removeState = "DELETE FROM containerState WHERE Id=?;" + removeRegistry = "DELETE FROM registry WHERE Id=?;" ) if !s.valid { @@ -926,6 +946,12 @@ func (s *SQLState) removeContainer(ctr *Container) error { return errors.Wrapf(err, "error removing container %s from state table", ctr.ID()) } + // Remove registry last of all + // So we know the container did exist + if _, err := tx.Exec(removeRegistry, ctr.ID()); err != nil { + return errors.Wrapf(err, "error removing container %s from name/ID registry", ctr.ID()) + } + if err := tx.Commit(); err != nil { return errors.Wrapf(err, "error committing transaction to remove container %s", ctr.ID()) } diff --git a/libpod/state_test.go b/libpod/state_test.go index 0a18c988d..6c4ee30af 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -4,6 +4,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "testing" "time" @@ -79,544 +80,834 @@ func getEmptySQLState() (s State, p string, p2 string, err error) { return state, tmpDir, lockDir, nil } -func runForAllStates(t *testing.T, testName string, testFunc func(*testing.T, State, string)) { +func runForAllStates(t *testing.T, testFunc func(*testing.T, State, string)) { for stateName, stateFunc := range testedStates { state, path, lockPath, err := stateFunc() if err != nil { - t.Fatalf("Error initializing state %s", stateName) + t.Fatalf("Error initializing state %s: %v", stateName, err) } defer os.RemoveAll(path) defer state.Close() - testName = testName + "-" + stateName - - success := t.Run(testName, func(t *testing.T) { + success := t.Run(stateName, 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 getTestCtrN(n, lockPath string) (*Container, error) { + return getTestContainer(strings.Repeat(n, 32), "test"+n, lockPath) } -func addAndGetContainer(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) - - err = state.AddContainer(testCtr) - assert.NoError(t, err) +func getTestCtr1(lockPath string) (*Container, error) { + return getTestCtrN("1", lockPath) +} - retrievedCtr, err := state.Container(testCtr.ID()) - assert.NoError(t, err) +func getTestCtr2(lockPath string) (*Container, error) { + return getTestCtrN("2", lockPath) +} - // 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 getTestPodN(n, lockPath string) (*Pod, error) { + return getTestPod(strings.Repeat(n, 32), "test"+n, lockPath) } -func TestAddAndGetContainerFromMultiple(t *testing.T) { - runForAllStates(t, "TestAddAndGetContainerFromMultiple", addAndGetContainerFromMultiple) +func getTestPod1(lockPath string) (*Pod, error) { + return getTestPodN("1", lockPath) } -func addAndGetContainerFromMultiple(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath) - assert.NoError(t, err) +func getTestPod2(lockPath string) (*Pod, error) { + return getTestPodN("2", lockPath) +} - err = state.AddContainer(testCtr1) - assert.NoError(t, err) +func TestAddAndGetContainer(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr2) - assert.NoError(t, err) + err = state.AddContainer(testCtr) + assert.NoError(t, err) - retrievedCtr, err := state.Container(testCtr1.ID()) - 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(testCtr1, retrievedCtr) { - assert.EqualValues(t, testCtr1, retrievedCtr) - } + // 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 TestAddInvalidContainerFails(t *testing.T) { - runForAllStates(t, "TestAddInvalidContainerFails", addInvalidContainerFails) +func TestAddAndGetContainerFromMultiple(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) + + 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 addInvalidContainerFails(t *testing.T, state State, lockPath string) { - err := state.AddContainer(&Container{config: &ContainerConfig{ID: "1234"}}) - assert.Error(t, err) +func TestGetContainerPodSameIDFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) + + err = state.AddPod(testPod) + assert.NoError(t, err) + + _, err = state.Container(testPod.ID()) + assert.Error(t, err) + }) } -func TestAddDuplicateCtrIDFails(t *testing.T) { - runForAllStates(t, "TestAddDuplicateCtrIDFails", addDuplicateCtrIDFails) +func TestAddInvalidContainerFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + err := state.AddContainer(&Container{config: &ContainerConfig{ID: "1234"}}) + assert.Error(t, err) + }) } -func addDuplicateCtrIDFails(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer(testCtr1.ID(), "test2", lockPath) - assert.NoError(t, err) +func TestAddDuplicateCtrIDFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestContainer(testCtr1.ID(), "test2", lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + err = state.AddContainer(testCtr1) + assert.NoError(t, err) - err = state.AddContainer(testCtr2) - assert.Error(t, err) + err = state.AddContainer(testCtr2) + assert.Error(t, err) + }) } func TestAddDuplicateCtrNameFails(t *testing.T) { - runForAllStates(t, "TestAddDuplicateCtrNameFails", addDuplicateCtrNameFails) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestContainer(strings.Repeat("2", 32), testCtr1.Name(), lockPath) + assert.NoError(t, err) + + err = state.AddContainer(testCtr1) + assert.NoError(t, err) + + err = state.AddContainer(testCtr2) + assert.Error(t, err) + }) } -func addDuplicateCtrNameFails(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("22222222222222222222222222222222", testCtr1.Name(), lockPath) - assert.NoError(t, err) +func TestAddCtrPodDupIDFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) + testCtr, err := getTestContainer(testPod.ID(), "testCtr", lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + err = state.AddPod(testPod) + assert.NoError(t, err) - err = state.AddContainer(testCtr2) - assert.Error(t, err) + err = state.AddContainer(testCtr) + assert.Error(t, err) + }) } -func TestGetNonexistentContainerFails(t *testing.T) { - runForAllStates(t, "TestGetNonexistentContainerFails", getNonexistentContainerFails) -} +func TestAddCtrPodDupNameFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) + testCtr, err := getTestContainer(strings.Repeat("2", 32), testPod.Name(), lockPath) + assert.NoError(t, err) -func getNonexistentContainerFails(t *testing.T, state State, lockPath string) { - _, err := state.Container("does not exist") - assert.Error(t, err) -} + err = state.AddPod(testPod) + assert.NoError(t, err) -func TestGetContainerWithEmptyIDFails(t *testing.T) { - runForAllStates(t, "TestGetContainerWithEmptyIDFails", getContainerWithEmptyIDFails) + err = state.AddContainer(testCtr) + assert.Error(t, err) + }) } -func getContainerWithEmptyIDFails(t *testing.T, state State, lockPath string) { - _, err := state.Container("") - assert.Error(t, err) +func TestGetNonexistentContainerFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.Container("does not exist") + assert.Error(t, err) + }) } -func TestLookupContainerWithEmptyIDFails(t *testing.T) { - runForAllStates(t, "TestLookupContainerWithEmptyIDFails", lookupContainerWithEmptyIDFails) +func TestGetContainerWithEmptyIDFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.Container("") + assert.Error(t, err) + }) } -func lookupContainerWithEmptyIDFails(t *testing.T, state State, lockPath string) { - _, err := state.LookupContainer("") - assert.Error(t, err) +func TestLookupContainerWithEmptyIDFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.LookupContainer("") + assert.Error(t, err) + }) } func TestLookupNonexistentContainerFails(t *testing.T) { - runForAllStates(t, "TestLookupNonexistantContainerFails", lookupNonexistentContainerFails) -} - -func lookupNonexistentContainerFails(t *testing.T, state State, lockPath string) { - _, err := state.LookupContainer("does not exist") - assert.Error(t, err) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.LookupContainer("does not exist") + assert.Error(t, err) + }) } func TestLookupContainerByFullID(t *testing.T) { - runForAllStates(t, "TestLookupContainerByFullID", lookupContainerByFullID) -} - -func lookupContainerByFullID(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr) - assert.NoError(t, err) + err = state.AddContainer(testCtr) + assert.NoError(t, err) - retrievedCtr, err := state.LookupContainer(testCtr.ID()) - 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) - } + // 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) { - runForAllStates(t, "TestLookupContainerByUniquePartialID", lookupContainerByUniquePartialID) -} + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) -func lookupContainerByUniquePartialID(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) + err = state.AddContainer(testCtr) + assert.NoError(t, err) - err = state.AddContainer(testCtr) - assert.NoError(t, err) + retrievedCtr, err := state.LookupContainer(testCtr.ID()[0:8]) + 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) - } + // 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) { - runForAllStates(t, "TestLookupContainerByNonUniquePartialIDFails", lookupContainerByNonUniquePartialIDFails) -} + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestContainer(strings.Repeat("0", 32), "test1", lockPath) + assert.NoError(t, err) + testCtr2, err := getTestContainer(strings.Repeat("0", 31)+"1", "test2", lockPath) + assert.NoError(t, err) -func lookupContainerByNonUniquePartialIDFails(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("00000000000000000000000000000000", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("00000000000000000000000000000001", "test2", lockPath) - assert.NoError(t, err) + err = state.AddContainer(testCtr1) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + err = state.AddContainer(testCtr2) + assert.NoError(t, err) - err = state.AddContainer(testCtr2) - assert.NoError(t, err) - - _, err = state.LookupContainer(testCtr1.ID()[0:8]) - assert.Error(t, err) + _, err = state.LookupContainer(testCtr1.ID()[0:8]) + assert.Error(t, err) + }) } func TestLookupContainerByName(t *testing.T) { - runForAllStates(t, "TestLookupContainerByName", lookupContainerByName) -} + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) -func lookupContainerByName(t *testing.T, state State, lockPath string) { - state, path, lockPath, err := getEmptySQLState() - assert.NoError(t, err) - defer os.RemoveAll(path) - defer state.Close() + err = state.AddContainer(testCtr) + assert.NoError(t, err) - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) + retrievedCtr, err := state.LookupContainer(testCtr.Name()) + assert.NoError(t, err) - err = state.AddContainer(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) + } + }) +} - retrievedCtr, err := state.LookupContainer(testCtr.Name()) - assert.NoError(t, err) +func TestLookupCtrByPodNameFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + 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) - } -} + err = state.AddPod(testPod) + assert.NoError(t, err) -func TestHasContainerEmptyIDFails(t *testing.T) { - runForAllStates(t, "TestHasContainerEmptyIDFails", hasContainerEmptyIDFails) + _, err = state.LookupContainer(testPod.Name()) + assert.Error(t, err) + }) } -func hasContainerEmptyIDFails(t *testing.T, state State, lockPath string) { - _, err := state.HasContainer("") - assert.Error(t, err) +func TestLookupCtrByPodIDFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) + + err = state.AddPod(testPod) + assert.NoError(t, err) + + _, err = state.LookupContainer(testPod.ID()) + assert.Error(t, err) + }) } -func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) { - runForAllStates(t, "TestHasContainerNoSuchContainerReturnsFalse", hasContainerNoSuchContainerReturnsFalse) +func TestHasContainerEmptyIDFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.HasContainer("") + assert.Error(t, err) + }) } -func hasContainerNoSuchContainerReturnsFalse(t *testing.T, state State, lockPath string) { - exists, err := state.HasContainer("does not exist") - assert.NoError(t, err) - assert.False(t, exists) +func TestHasContainerNoSuchContainerReturnsFalse(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + exists, err := state.HasContainer("does not exist") + assert.NoError(t, err) + assert.False(t, exists) + }) } func TestHasContainerFindsContainer(t *testing.T) { - runForAllStates(t, "TestHasContainerFindsContainer", hasContainerFindsContainer) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) + + err = state.AddContainer(testCtr) + assert.NoError(t, err) + + exists, err := state.HasContainer(testCtr.ID()) + assert.NoError(t, err) + assert.True(t, exists) + }) } -func hasContainerFindsContainer(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) +func TestHasContainerPodIDIsFalse(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr) - assert.NoError(t, err) + err = state.AddPod(testPod) + assert.NoError(t, err) - exists, err := state.HasContainer(testCtr.ID()) - assert.NoError(t, err) - assert.True(t, exists) + exists, err := state.HasContainer(testPod.ID()) + assert.NoError(t, err) + assert.False(t, exists) + }) } func TestSaveAndUpdateContainer(t *testing.T) { - runForAllStates(t, "TestSaveAndUpdateContainer", saveAndUpdateContainer) -} - -func saveAndUpdateContainer(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr) - assert.NoError(t, err) + err = state.AddContainer(testCtr) + assert.NoError(t, err) - retrievedCtr, err := state.Container(testCtr.ID()) - 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() + retrievedCtr.state.State = ContainerStateStopped + retrievedCtr.state.ExitCode = 127 + retrievedCtr.state.FinishedTime = time.Now() - err = state.SaveContainer(retrievedCtr) - assert.NoError(t, err) + err = state.SaveContainer(retrievedCtr) + assert.NoError(t, err) - err = state.UpdateContainer(testCtr) - 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) - } + // 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) { - runForAllStates(t, "TestUpdateContainerNotInDatabaseReturnsError", updateContainerNotInDatabaseReturnsError) -} - -func updateContainerNotInDatabaseReturnsError(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - err = state.UpdateContainer(testCtr) - assert.Error(t, err) - assert.False(t, testCtr.valid) + err = state.UpdateContainer(testCtr) + assert.Error(t, err) + assert.False(t, testCtr.valid) + }) } func TestUpdateInvalidContainerReturnsError(t *testing.T) { - runForAllStates(t, "TestUpdateInvalidContainerReturnsError", updateInvalidContainerReturnsError) -} - -func updateInvalidContainerReturnsError(t *testing.T, state State, lockPath string) { - err := state.UpdateContainer(&Container{config: &ContainerConfig{ID: "1234"}}) - assert.Error(t, err) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + err := state.UpdateContainer(&Container{config: &ContainerConfig{ID: "1234"}}) + assert.Error(t, err) + }) } func TestSaveInvalidContainerReturnsError(t *testing.T) { - runForAllStates(t, "TestSaveInvalidContainerReturnsError", saveInvalidContainerReturnsError) + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + err := state.SaveContainer(&Container{config: &ContainerConfig{ID: "1234"}}) + assert.Error(t, err) + }) } -func saveInvalidContainerReturnsError(t *testing.T, state State, lockPath string) { - err := state.SaveContainer(&Container{config: &ContainerConfig{ID: "1234"}}) - assert.Error(t, err) +func TestSaveContainerNotInStateReturnsError(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) + + err = state.SaveContainer(testCtr) + assert.Error(t, err) + assert.False(t, testCtr.valid) + }) } -func TestSaveContainerNotInStateReturnsError(t *testing.T) { - runForAllStates(t, "TestSaveContainerNotInStateReturnsError", saveContainerNotInStateReturnsError) +func TestRemoveContainer(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) + + 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 saveContainerNotInStateReturnsError(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) +func TestRemoveNonexistantContainerFails(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - err = state.SaveContainer(testCtr) - assert.Error(t, err) - assert.False(t, testCtr.valid) + err = state.RemoveContainer(testCtr) + assert.Error(t, err) + }) } -func TestRemoveContainer(t *testing.T) { - runForAllStates(t, "TestRemoveContainer", removeContainer) +func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + ctrs, err := state.AllContainers() + assert.NoError(t, err) + assert.Equal(t, 0, len(ctrs)) + }) } -func removeContainer(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) +func TestGetAllContainersWithOneContainer(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) + + 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]) + } + }) +} - err = state.AddContainer(testCtr) - assert.NoError(t, err) +func TestGetAllContainersTwoContainers(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) - ctrs, err := state.AllContainers() - assert.NoError(t, err) - assert.Equal(t, 1, len(ctrs)) + err = state.AddContainer(testCtr1) + assert.NoError(t, err) - err = state.RemoveContainer(testCtr) - assert.NoError(t, err) + err = state.AddContainer(testCtr2) + assert.NoError(t, err) - ctrs2, err := state.AllContainers() - assert.NoError(t, err) - assert.Equal(t, 0, len(ctrs2)) + ctrs, err := state.AllContainers() + assert.NoError(t, err) + assert.Equal(t, 2, len(ctrs)) + }) } -func TestRemoveNonexistantContainerFails(t *testing.T) { - runForAllStates(t, "TestRemoveNonexistantContainerFails", removeNonexistantContainerFails) +func TestContainerInUseInvalidContainer(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.ContainerInUse(&Container{}) + assert.Error(t, err) + }) } -func removeNonexistantContainerFails(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) +func TestContainerInUseOneContainer(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) - err = state.RemoveContainer(testCtr) - assert.Error(t, err) -} + testCtr2.config.UserNsCtr = testCtr1.config.ID -func TestGetAllContainersOnNewStateIsEmpty(t *testing.T) { - runForAllStates(t, "TestGetAllContainersOnNewStateIsEmpty", getAllContainersOnNewStateIsEmpty) + err = state.AddContainer(testCtr1) + assert.NoError(t, err) + + err = state.AddContainer(testCtr2) + assert.NoError(t, err) + + ids, err := state.ContainerInUse(testCtr1) + assert.NoError(t, err) + assert.Equal(t, 1, len(ids)) + assert.Equal(t, testCtr2.config.ID, ids[0]) + }) } -func getAllContainersOnNewStateIsEmpty(t *testing.T, state State, lockPath string) { - ctrs, err := state.AllContainers() - assert.NoError(t, err) - assert.Equal(t, 0, len(ctrs)) +func TestContainerInUseTwoContainers(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) + testCtr3, err := getTestCtrN("3", lockPath) + assert.NoError(t, err) + + testCtr2.config.UserNsCtr = testCtr1.config.ID + testCtr3.config.IPCNsCtr = testCtr1.config.ID + + err = state.AddContainer(testCtr1) + assert.NoError(t, err) + + err = state.AddContainer(testCtr2) + assert.NoError(t, err) + + err = state.AddContainer(testCtr3) + assert.NoError(t, err) + + ids, err := state.ContainerInUse(testCtr1) + assert.NoError(t, err) + assert.Equal(t, 2, len(ids)) + }) } -func TestGetAllContainersWithOneContainer(t *testing.T) { - runForAllStates(t, "TestGetAllContainersWithOneContainer", getAllContainersWithOneContainer) +func TestContainerInUseOneContainerMultipleDependencies(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) + + testCtr2.config.UserNsCtr = testCtr1.config.ID + testCtr2.config.IPCNsCtr = testCtr1.config.ID + + err = state.AddContainer(testCtr1) + assert.NoError(t, err) + + err = state.AddContainer(testCtr2) + assert.NoError(t, err) + + ids, err := state.ContainerInUse(testCtr1) + assert.NoError(t, err) + assert.Equal(t, 1, len(ids)) + assert.Equal(t, testCtr2.config.ID, ids[0]) + }) } -func getAllContainersWithOneContainer(t *testing.T, state State, lockPath string) { - testCtr, err := getTestContainer("0123456789ABCDEF0123456789ABCDEF", "test", lockPath) - assert.NoError(t, err) +func TestCannotRemoveContainerWithDependency(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr) - assert.NoError(t, err) + testCtr2.config.UserNsCtr = testCtr1.config.ID - ctrs, err := state.AllContainers() - assert.NoError(t, err) - assert.Equal(t, 1, len(ctrs)) + err = state.AddContainer(testCtr1) + assert.NoError(t, err) - // 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]) - } + err = state.AddContainer(testCtr2) + assert.NoError(t, err) + + err = state.RemoveContainer(testCtr1) + assert.Error(t, err) + }) } -func TestGetAllContainersTwoContainers(t *testing.T) { - runForAllStates(t, "TestGetAllContainersTwoContainers", getAllContainersTwoContainers) +func TestCanRemoveContainerAfterDependencyRemoved(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) + + testCtr2.config.UserNsCtr = testCtr1.ID() + + err = state.AddContainer(testCtr1) + assert.NoError(t, err) + + err = state.AddContainer(testCtr2) + assert.NoError(t, err) + + err = state.RemoveContainer(testCtr2) + assert.NoError(t, err) + + err = state.RemoveContainer(testCtr1) + assert.NoError(t, err) + }) } -func getAllContainersTwoContainers(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath) - assert.NoError(t, err) +func TestCanRemoveContainerAfterDependencyRemovedDuplicate(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr1, err := getTestCtr1(lockPath) + assert.NoError(t, err) + testCtr2, err := getTestCtr2(lockPath) + assert.NoError(t, err) + + testCtr2.config.UserNsCtr = testCtr1.ID() + testCtr2.config.IPCNsCtr = testCtr1.ID() + + err = state.AddContainer(testCtr1) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + err = state.AddContainer(testCtr2) + assert.NoError(t, err) - err = state.AddContainer(testCtr2) - assert.NoError(t, err) + err = state.RemoveContainer(testCtr2) + assert.NoError(t, err) - ctrs, err := state.AllContainers() - assert.NoError(t, err) - assert.Equal(t, 2, len(ctrs)) + err = state.RemoveContainer(testCtr1) + assert.NoError(t, err) + }) } -func TestContainerInUseInvalidContainer(t *testing.T) { - runForAllStates(t, "TestContainerInUseInvalidContainer", containerInUseInvalidContainer) +func TestGetPodDoesNotExist(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.Pod("doesnotexist") + assert.Error(t, err) + }) } -func containerInUseInvalidContainer(t *testing.T, state State, lockPath string) { - _, err := state.ContainerInUse(&Container{}) - assert.Error(t, err) +func TestGetPodEmptyID(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.Pod("") + assert.Error(t, err) + }) } -func TestContainerInUseOneContainer(t *testing.T) { - runForAllStates(t, "TestContainerInUseOneContainer", containerInUseOneContainer) +func TestGetPodOnePod(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) + + err = state.AddPod(testPod) + assert.NoError(t, err) + + statePod, err := state.Pod(testPod.ID()) + assert.NoError(t, err) + + // Use assert.EqualValues if the test fails to pretty print diff + // between actual and expected + if !testPodsEqual(testPod, statePod) { + assert.EqualValues(t, testPod, statePod) + } + }) } -func containerInUseOneContainer(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath) - assert.NoError(t, err) +func TestGetOnePodFromTwo(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod1, err := getTestPod1(lockPath) + assert.NoError(t, err) + + testPod2, err := getTestPod2(lockPath) + assert.NoError(t, err) - testCtr2.config.UserNsCtr = testCtr1.config.ID + err = state.AddPod(testPod1) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + err = state.AddPod(testPod2) + assert.NoError(t, err) - err = state.AddContainer(testCtr2) - assert.NoError(t, err) + statePod, err := state.Pod(testPod1.ID()) + assert.NoError(t, err) - ids, err := state.ContainerInUse(testCtr1) - assert.NoError(t, err) - assert.Equal(t, 1, len(ids)) - assert.Equal(t, testCtr2.config.ID, ids[0]) + // Use assert.EqualValues if the test fails to pretty print diff + // between actual and expected + if !testPodsEqual(testPod1, statePod) { + assert.EqualValues(t, testPod1, statePod) + } + }) } -func TestContainerInUseTwoContainers(t *testing.T) { - runForAllStates(t, "TestContainerInUseTwoContainers", containerInUseTwoContainers) +func TestGetNotExistPodWithPods(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod1, err := getTestPod1(lockPath) + assert.NoError(t, err) + + testPod2, err := getTestPod2(lockPath) + assert.NoError(t, err) + + err = state.AddPod(testPod1) + assert.NoError(t, err) + + err = state.AddPod(testPod2) + assert.NoError(t, err) + + _, err = state.Pod("notexist") + assert.Error(t, err) + }) } -func containerInUseTwoContainers(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath) - assert.NoError(t, err) - testCtr3, err := getTestContainer("33333333333333333333333333333333", "test3", lockPath) - assert.NoError(t, err) +func TestGetPodByCtrID(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - testCtr2.config.UserNsCtr = testCtr1.config.ID - testCtr3.config.IPCNsCtr = testCtr1.config.ID + err = state.AddContainer(testCtr) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + _, err = state.Pod(testCtr.ID()) + assert.Error(t, err) + }) +} + +func TestLookupPodEmptyID(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.LookupPod("") + assert.Error(t, err) + }) +} + +func TestLookupNotExistPod(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + _, err := state.LookupPod("doesnotexist") + assert.Error(t, err) + }) +} - err = state.AddContainer(testCtr2) - assert.NoError(t, err) +func TestLookupPodFullID(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr3) - assert.NoError(t, err) + err = state.AddPod(testPod) + assert.NoError(t, err) - ids, err := state.ContainerInUse(testCtr1) - assert.NoError(t, err) - assert.Equal(t, 2, len(ids)) + statePod, err := state.LookupPod(testPod.ID()) + assert.NoError(t, err) + + // Use assert.EqualValues if the test fails to pretty print diff + // between actual and expected + if !testPodsEqual(testPod, statePod) { + assert.EqualValues(t, testPod, statePod) + } + }) } -func TestCannotRemoveContainerWithDependency(t *testing.T) { - runForAllStates(t, "TestCannotRemoveContainerWithDependency", cannotRemoveContainerWithDependency) +func TestLookupPodUniquePartialID(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) + + err = state.AddPod(testPod) + assert.NoError(t, err) + + statePod, err := state.LookupPod(testPod.ID()[0:8]) + assert.NoError(t, err) + + // Use assert.EqualValues if the test fails to pretty print diff + // between actual and expected + if !testPodsEqual(testPod, statePod) { + assert.EqualValues(t, testPod, statePod) + } + }) } -func cannotRemoveContainerWithDependency(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath) - assert.NoError(t, err) +func TestLookupPodNonUniquePartialID(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod1, err := getTestPod(strings.Repeat("1", 32), "test1", lockPath) + assert.NoError(t, err) - testCtr2.config.UserNsCtr = testCtr1.config.ID + testPod2, err := getTestPod(strings.Repeat("1", 31)+"2", "test2", lockPath) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + err = state.AddPod(testPod1) + assert.NoError(t, err) - err = state.AddContainer(testCtr2) - assert.NoError(t, err) + err = state.AddPod(testPod2) + assert.NoError(t, err) - err = state.RemoveContainer(testCtr1) - assert.Error(t, err) + _, err = state.LookupPod(testPod1.ID()[0:8]) + assert.Error(t, err) + }) } -func TestCanRemoveContainerAfterDependencyRemoved(t *testing.T) { - runForAllStates(t, "TestCanRemoveContainerAfterDependencyRemoved", canRemoveContainerAfterDependencyRemoved) +func TestLookupPodByName(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testPod, err := getTestPod1(lockPath) + assert.NoError(t, err) + + err = state.AddPod(testPod) + assert.NoError(t, err) + + statePod, err := state.LookupPod(testPod.Name()) + assert.NoError(t, err) + + // Use assert.EqualValues if the test fails to pretty print diff + // between actual and expected + if !testPodsEqual(testPod, statePod) { + assert.EqualValues(t, testPod, statePod) + } + }) } -func canRemoveContainerAfterDependencyRemoved(t *testing.T, state State, lockPath string) { - testCtr1, err := getTestContainer("11111111111111111111111111111111", "test1", lockPath) - assert.NoError(t, err) - testCtr2, err := getTestContainer("22222222222222222222222222222222", "test2", lockPath) - assert.NoError(t, err) +func TestLookupPodByCtrID(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - testCtr2.config.UserNsCtr = testCtr1.config.ID + err = state.AddContainer(testCtr) + assert.NoError(t, err) - err = state.AddContainer(testCtr1) - assert.NoError(t, err) + _, err = state.LookupPod(testCtr.ID()) + assert.Error(t, err) + }) +} - err = state.AddContainer(testCtr2) - assert.NoError(t, err) +func TestLookupPodByCtrName(t *testing.T) { + runForAllStates(t, func(t *testing.T, state State, lockPath string) { + testCtr, err := getTestCtr1(lockPath) + assert.NoError(t, err) - err = state.RemoveContainer(testCtr2) - assert.NoError(t, err) + err = state.AddContainer(testCtr) + assert.NoError(t, err) - err = state.RemoveContainer(testCtr1) - assert.NoError(t, err) + _, err = state.LookupPod(testCtr.Name()) + assert.Error(t, err) + }) } diff --git a/libpod/test_common.go b/libpod/test_common.go index b6188ce80..ad3020b7e 100644 --- a/libpod/test_common.go +++ b/libpod/test_common.go @@ -24,7 +24,7 @@ func getTestContainer(id, name, locksDir string) (*Container, error) { StaticDir: "/does/not/exist/", LogPath: "/does/not/exist/", Stdin: true, - Labels: make(map[string]string), + Labels: map[string]string{"a": "b", "c": "d"}, StopSignal: 0, StopTimeout: 0, CreatedTime: time.Now(), @@ -74,6 +74,25 @@ func getTestContainer(id, name, locksDir string) (*Container, error) { return ctr, nil } +// nolint +func getTestPod(id, name, locksDir string) (*Pod, error) { + pod := &Pod{ + id: id, + name: name, + labels: map[string]string{"a": "b", "c": "d"}, + valid: true, + } + + lockPath := filepath.Join(locksDir, id) + lock, err := storage.GetLockfile(lockPath) + if err != nil { + return nil, err + } + pod.lock = lock + + return pod, 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 // nolint @@ -114,3 +133,26 @@ func testContainersEqual(a, b *Container) bool { return reflect.DeepEqual(aStateJSON, bStateJSON) } + +// This tests pod equality +// We cannot guarantee equality in lockfile objects so we can't simply compare +// nolint +func testPodsEqual(a, b *Pod) bool { + if a == nil && b == nil { + return true + } else if a == nil || b == nil { + return false + } + + if a.id != b.id { + return false + } + if a.name != b.name { + return false + } + if a.valid != b.valid { + return false + } + + return reflect.DeepEqual(a.labels, b.labels) +} |