summaryrefslogtreecommitdiffhomepage
path: root/runsc/container/container_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/container/container_test.go')
-rw-r--r--runsc/container/container_test.go52
1 files changed, 46 insertions, 6 deletions
diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go
index 790334249..ab1823f1c 100644
--- a/runsc/container/container_test.go
+++ b/runsc/container/container_test.go
@@ -200,6 +200,7 @@ func run(spec *specs.Spec, conf *boot.Config) error {
if err := s.Start(conf); err != nil {
return fmt.Errorf("error starting container: %v", err)
}
+
ws, err := s.Wait()
if err != nil {
return fmt.Errorf("error waiting on container: %v", err)
@@ -251,6 +252,35 @@ func configs(opts ...configOption) []*boot.Config {
return cs
}
+// In normal runsc usage, sandbox processes will be parented to
+// init and init will reap the them. However, in the test environment
+// the test runner is the parent and will not reap the sandbox
+// processes, so we must do it ourselves, or else they will left
+// as zombies.
+// The function returns a wait group, and the caller can reap
+// children synchronously by waiting on the wait group.
+func reapChildren(c *Container) (*sync.WaitGroup, error) {
+ var wg sync.WaitGroup
+ p, err := os.FindProcess(c.Sandbox.Pid)
+ if err != nil {
+ return nil, fmt.Errorf("error finding sandbox process: %v", err)
+ }
+ g, err := os.FindProcess(c.GoferPid)
+ if err != nil {
+ return nil, fmt.Errorf("error finding gofer process: %v", err)
+ }
+ wg.Add(2)
+ go func() {
+ p.Wait()
+ wg.Done()
+ }()
+ go func() {
+ g.Wait()
+ wg.Done()
+ }()
+ return &wg, nil
+}
+
// TestLifecycle tests the basic Create/Start/Signal/Destroy container lifecycle.
// It verifies after each step that the container can be loaded from disk, and
// has the correct status.
@@ -306,6 +336,7 @@ func TestLifecycle(t *testing.T) {
if err := s.Start(conf); err != nil {
t.Fatalf("error starting container: %v", err)
}
+
// Load the container from disk and check the status.
s, err = Load(rootDir, id)
if err != nil {
@@ -352,10 +383,11 @@ func TestLifecycle(t *testing.T) {
// and init will reap the sandbox. However, in this case the
// test runner is the parent and will not reap the sandbox
// process, so we must do it ourselves.
- p, _ := os.FindProcess(s.Sandbox.Pid)
- p.Wait()
- g, _ := os.FindProcess(s.GoferPid)
- g.Wait()
+ reapWg, err := reapChildren(s)
+ if err != nil {
+ t.Fatalf("error reaping children: %v", err)
+ }
+ reapWg.Wait()
// Load the container from disk and check the status.
s, err = Load(rootDir, id)
@@ -1164,6 +1196,11 @@ func TestConsoleSocket(t *testing.T) {
t.Errorf("fd is not a terminal (ioctl TGGETS got %v)", err)
}
+ // Reap the sandbox process.
+ if _, err := reapChildren(s); err != nil {
+ t.Fatalf("error reaping children: %v", err)
+ }
+
// Shut it down.
if err := s.Destroy(); err != nil {
t.Fatalf("error destroying container: %v", err)
@@ -1259,6 +1296,7 @@ func TestReadonlyRoot(t *testing.T) {
if err := s.Start(conf); err != nil {
t.Fatalf("error starting container: %v", err)
}
+
ws, err := s.Wait()
if err != nil {
t.Fatalf("error waiting on container: %v", err)
@@ -1302,6 +1340,7 @@ func TestReadonlyMount(t *testing.T) {
if err := s.Start(conf); err != nil {
t.Fatalf("error starting container: %v", err)
}
+
ws, err := s.Wait()
if err != nil {
t.Fatalf("error waiting on container: %v", err)
@@ -1547,8 +1586,9 @@ func TestGoferExits(t *testing.T) {
if _, err := gofer.Wait(); err != nil {
t.Fatalf("error waiting for gofer process: %v", err)
}
- if c.IsRunning() {
- t.Errorf("container shouldn't be running, container: %+v", c)
+
+ if err := c.waitForStopped(); err != nil {
+ t.Errorf("container is not stopped: %v", err)
}
}