| package docker |
| |
| import ( |
| "io" |
| "io/ioutil" |
| "os" |
| "path" |
| "strings" |
| "testing" |
| "github.com/dotcloud/docker/utils" |
| ) |
| |
| // This file contains utility functions for docker's unit test suite. |
| // It has to be named XXX_test.go, apparently, in other to access private functions |
| // from other XXX_test.go functions. |
| |
| // Create a temporary runtime suitable for unit testing. |
| // Call t.Fatal() at the first error. |
| func mkRuntime(f Fataler) *Runtime { |
| runtime, err := newTestRuntime() |
| if err != nil { |
| f.Fatal(err) |
| } |
| return runtime |
| } |
| |
| // A common interface to access the Fatal method of |
| // both testing.B and testing.T. |
| type Fataler interface { |
| Fatal(args ...interface{}) |
| } |
| |
| func newTestRuntime() (*Runtime, error) { |
| root, err := ioutil.TempDir("", "docker-test") |
| if err != nil { |
| return nil, err |
| } |
| if err := os.Remove(root); err != nil { |
| return nil, err |
| } |
| if err := utils.CopyDirectory(unitTestStoreBase, root); err != nil { |
| return nil, err |
| } |
| |
| runtime, err := NewRuntimeFromDirectory(root, false) |
| if err != nil { |
| return nil, err |
| } |
| runtime.UpdateCapabilities(true) |
| return runtime, nil |
| } |
| |
| // Write `content` to the file at path `dst`, creating it if necessary, |
| // as well as any missing directories. |
| // The file is truncated if it already exists. |
| // Call t.Fatal() at the first error. |
| func writeFile(dst, content string, t *testing.T) { |
| // Create subdirectories if necessary |
| if err := os.MkdirAll(path.Dir(dst), 0700); err != nil && !os.IsExist(err) { |
| t.Fatal(err) |
| } |
| f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700) |
| if err != nil { |
| t.Fatal(err) |
| } |
| // Write content (truncate if it exists) |
| if _, err := io.Copy(f, strings.NewReader(content)); err != nil { |
| t.Fatal(err) |
| } |
| } |
| |
| // Return the contents of file at path `src`. |
| // Call t.Fatal() at the first error (including if the file doesn't exist) |
| func readFile(src string, t *testing.T) (content string) { |
| f, err := os.Open(src) |
| if err != nil { |
| t.Fatal(err) |
| } |
| data, err := ioutil.ReadAll(f) |
| if err != nil { |
| t.Fatal(err) |
| } |
| return string(data) |
| } |
| |
| // Create a test container from the given runtime `r` and run arguments `args`. |
| // The image name (eg. the XXX in []string{"-i", "-t", "XXX", "bash"}, is dynamically replaced by the current test image. |
| // The caller is responsible for destroying the container. |
| // Call t.Fatal() at the first error. |
| func mkContainer(r *Runtime, args []string, t *testing.T) (*Container, *HostConfig) { |
| config, hostConfig, _, err := ParseRun(args, nil) |
| if err != nil { |
| t.Fatal(err) |
| } |
| config.Image = GetTestImage(r).ID |
| c, err := NewBuilder(r).Create(config) |
| if err != nil { |
| t.Fatal(err) |
| } |
| return c, hostConfig |
| } |
| |
| // Create a test container, start it, wait for it to complete, destroy it, |
| // and return its standard output as a string. |
| // The image name (eg. the XXX in []string{"-i", "-t", "XXX", "bash"}, is dynamically replaced by the current test image. |
| // If t is not nil, call t.Fatal() at the first error. Otherwise return errors normally. |
| func runContainer(r *Runtime, args []string, t *testing.T) (output string, err error) { |
| defer func() { |
| if err != nil && t != nil { |
| t.Fatal(err) |
| } |
| }() |
| container, hostConfig := mkContainer(r, args, t) |
| defer r.Destroy(container) |
| stdout, err := container.StdoutPipe() |
| if err != nil { |
| return "", err |
| } |
| defer stdout.Close() |
| if err := container.Start(hostConfig); err != nil { |
| return "", err |
| } |
| container.Wait() |
| data, err := ioutil.ReadAll(stdout) |
| if err != nil { |
| return "", err |
| } |
| output = string(data) |
| return |
| } |