Integration tests: remove dependency on private APIs

This commit is contained in:
Victor Vieux 2013-11-14 06:10:20 +00:00 committed by Victor Vieux
parent 359a6f49b9
commit c001a5af67
8 changed files with 528 additions and 1120 deletions

View File

@ -1,76 +1,35 @@
package docker package docker
import ( import (
"archive/tar" _ "archive/tar"
"bufio" _ "bufio"
"bytes" _ "bytes"
"encoding/json" "encoding/json"
"fmt" "github.com/dotcloud/docker"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
"io" "io"
"net" _ "net"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" _ "os"
"path" _ "path"
"strings" _ "strings"
"testing" "testing"
"time" "time"
) )
func TestGetBoolParam(t *testing.T) { /*
if ret, err := getBoolParam("true"); err != nil || !ret {
t.Fatalf("true -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("True"); err != nil || !ret {
t.Fatalf("True -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("1"); err != nil || !ret {
t.Fatalf("1 -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam(""); err != nil || ret {
t.Fatalf("\"\" -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("false"); err != nil || ret {
t.Fatalf("false -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("0"); err != nil || ret {
t.Fatalf("0 -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("faux"); err == nil || ret {
t.Fatalf("faux -> false, err | got %t %s", ret, err)
}
}
func TesthttpError(t *testing.T) {
r := httptest.NewRecorder()
httpError(r, fmt.Errorf("No such method"))
if r.Code != http.StatusNotFound {
t.Fatalf("Expected %d, got %d", http.StatusNotFound, r.Code)
}
httpError(r, fmt.Errorf("This accound hasn't been activated"))
if r.Code != http.StatusForbidden {
t.Fatalf("Expected %d, got %d", http.StatusForbidden, r.Code)
}
httpError(r, fmt.Errorf("Some error"))
if r.Code != http.StatusInternalServerError {
t.Fatalf("Expected %d, got %d", http.StatusInternalServerError, r.Code)
}
}
func TestGetVersion(t *testing.T) { func TestGetVersion(t *testing.T) {
var err error runtime := mkRuntime()
runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
var err error
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getVersion(srv, APIVERSION, r, nil, nil); err != nil { // FIXME getting the version should require an actual running Server
if err := getVersion(srv, docker.APIVERSION, r, nil, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -83,11 +42,29 @@ func TestGetVersion(t *testing.T) {
} }
} }
var err error
r := httptest.NewRecorder()
// FIXME getting the version should require an actual running Server
if err := getVersion(&docker.Server{}, docker.APIVERSION, r, nil, nil); err != nil {
t.Fatal(err)
}
v := &APIVersion{}
if err = json.Unmarshal(r.Body.Bytes(), v); err != nil {
t.Fatal(err)
}
if v.Version != VERSION {
t.Errorf("Expected version %s, %s found", VERSION, v.Version)
}
}
func TestGetInfo(t *testing.T) { func TestGetInfo(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
initialImages, err := srv.runtime.graph.Map() initialImages, err := srv.runtime.graph.Map()
if err != nil { if err != nil {
@ -96,7 +73,7 @@ func TestGetInfo(t *testing.T) {
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getInfo(srv, APIVERSION, r, nil, nil); err != nil { if err := getInfo(srv, docker.APIVERSION, r, nil, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -109,18 +86,25 @@ func TestGetInfo(t *testing.T) {
t.Errorf("Expected images: %d, %d found", len(initialImages), infos.Images) t.Errorf("Expected images: %d, %d found", len(initialImages), infos.Images)
} }
} }
*/
func TestGetEvents(t *testing.T) { func TestGetEvents(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t)
// FIXME: we might not need runtime, why not simply nuke
// the engine?
runtime := mkRuntimeFromEngine(eng, t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{
runtime: runtime,
events: make([]utils.JSONMessage, 0, 64),
listeners: make(map[string]chan utils.JSONMessage),
}
srv.LogEvent("fakeaction", "fakeid", "fakeimage") var events []*utils.JSONMessage
srv.LogEvent("fakeaction2", "fakeid", "fakeimage") for _, parts := range [][3]string{
{"fakeaction", "fakeid", "fakeimage"},
{"fakeaction2", "fakeid", "fakeimage"},
} {
action, id, from := parts[0], parts[1], parts[2]
ev := srv.LogEvent(action, id, from)
events = append(events, ev)
}
req, err := http.NewRequest("GET", "/events?since=1", nil) req, err := http.NewRequest("GET", "/events?since=1", nil)
if err != nil { if err != nil {
@ -129,7 +113,7 @@ func TestGetEvents(t *testing.T) {
r := httptest.NewRecorder() r := httptest.NewRecorder()
setTimeout(t, "", 500*time.Millisecond, func() { setTimeout(t, "", 500*time.Millisecond, func() {
if err := getEvents(srv, APIVERSION, r, req, nil); err != nil { if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
t.Fatal(err) t.Fatal(err)
} }
}) })
@ -142,18 +126,20 @@ func TestGetEvents(t *testing.T) {
} else if err != nil { } else if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if jm != srv.events[i] { if jm != *events[i] {
t.Fatalf("Event received it different than expected") t.Fatalf("Event received it different than expected")
} }
} }
} }
/*
func TestGetImagesJSON(t *testing.T) { func TestGetImagesJSON(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
// all=0 // all=0
@ -169,7 +155,7 @@ func TestGetImagesJSON(t *testing.T) {
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getImagesJSON(srv, APIVERSION, r, req, nil); err != nil { if err := getImagesJSON(srv, docker.APIVERSION, r, req, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -207,7 +193,7 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if err := getImagesJSON(srv, APIVERSION, r2, req2, nil); err != nil { if err := getImagesJSON(srv, docker.APIVERSION, r2, req2, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -239,7 +225,7 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if err := getImagesJSON(srv, APIVERSION, r3, req3, nil); err != nil { if err := getImagesJSON(srv, docker.APIVERSION, r3, req3, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -260,7 +246,7 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = getImagesJSON(srv, APIVERSION, r4, req4, nil) err = getImagesJSON(srv, docker.APIVERSION, r4, req4, nil)
if err == nil { if err == nil {
t.Fatalf("Error expected, received none") t.Fatalf("Error expected, received none")
} }
@ -279,11 +265,11 @@ func TestGetImagesHistory(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getImagesHistory(srv, APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { if err := getImagesHistory(srv, docker.APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -300,14 +286,14 @@ func TestGetImagesByName(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getImagesByName(srv, APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { if err := getImagesByName(srv, docker.APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
img := &Image{} img := &docker.Image{}
if err := json.Unmarshal(r.Body.Bytes(), img); err != nil { if err := json.Unmarshal(r.Body.Bytes(), img); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -320,7 +306,7 @@ func TestGetContainersJSON(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
beginLen := runtime.containers.Len() beginLen := runtime.containers.Len()
@ -339,7 +325,7 @@ func TestGetContainersJSON(t *testing.T) {
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getContainersJSON(srv, APIVERSION, r, req, nil); err != nil { if err := getContainersJSON(srv, docker.APIVERSION, r, req, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
containers := []APIContainers{} containers := []APIContainers{}
@ -358,7 +344,7 @@ func TestGetContainersExport(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
// Create a container and remove a file // Create a container and remove a file
container, _, err := runtime.Create( container, _, err := runtime.Create(
@ -378,7 +364,7 @@ func TestGetContainersExport(t *testing.T) {
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err = getContainersExport(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { if err = getContainersExport(srv, docker.APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -409,7 +395,7 @@ func TestGetContainersChanges(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
// Create a container and remove a file // Create a container and remove a file
container, _, err := runtime.Create( container, _, err := runtime.Create(
@ -429,7 +415,7 @@ func TestGetContainersChanges(t *testing.T) {
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getContainersChanges(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { if err := getContainersChanges(srv, docker.APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
changes := []Change{} changes := []Change{}
@ -454,7 +440,7 @@ func TestGetContainersTop(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &Config{
@ -505,7 +491,7 @@ func TestGetContainersTop(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := getContainersTop(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { if err := getContainersTop(srv, docker.APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
procs := APITop{} procs := APITop{}
@ -535,7 +521,7 @@ func TestGetContainersByName(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
// Create a container and remove a file // Create a container and remove a file
container, _, err := runtime.Create( container, _, err := runtime.Create(
@ -551,10 +537,10 @@ func TestGetContainersByName(t *testing.T) {
defer runtime.Destroy(container) defer runtime.Destroy(container)
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := getContainersByName(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { if err := getContainersByName(srv, docker.APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
outContainer := &Container{} outContainer := &docker.Container{}
if err := json.Unmarshal(r.Body.Bytes(), outContainer); err != nil { if err := json.Unmarshal(r.Body.Bytes(), outContainer); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -567,7 +553,7 @@ func TestPostCommit(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
// Create a container and remove a file // Create a container and remove a file
container, _, err := runtime.Create( container, _, err := runtime.Create(
@ -592,7 +578,7 @@ func TestPostCommit(t *testing.T) {
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := postCommit(srv, APIVERSION, r, req, nil); err != nil { if err := postCommit(srv, docker.APIVERSION, r, req, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Code != http.StatusCreated { if r.Code != http.StatusCreated {
@ -629,7 +615,7 @@ func TestPostContainersCreate(t *testing.T) {
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := postContainersCreate(srv, APIVERSION, r, req, nil); err != nil { if err := postContainersCreate(srv, docker.APIVERSION, r, req, nil); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Code != http.StatusCreated { if r.Code != http.StatusCreated {
@ -663,7 +649,7 @@ func TestPostContainersKill(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &Config{
@ -690,7 +676,7 @@ func TestPostContainersKill(t *testing.T) {
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := postContainersKill(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { if err := postContainersKill(srv, docker.APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Code != http.StatusNoContent { if r.Code != http.StatusNoContent {
@ -705,7 +691,7 @@ func TestPostContainersRestart(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &Config{
@ -736,7 +722,7 @@ func TestPostContainersRestart(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := postContainersRestart(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { if err := postContainersRestart(srv, docker.APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Code != http.StatusNoContent { if r.Code != http.StatusNoContent {
@ -780,7 +766,7 @@ func TestPostContainersStart(t *testing.T) {
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := postContainersStart(srv, APIVERSION, r, req, map[string]string{"name": id}); err != nil { if err := postContainersStart(srv, docker.APIVERSION, r, req, map[string]string{"name": id}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Code != http.StatusNoContent { if r.Code != http.StatusNoContent {
@ -799,7 +785,7 @@ func TestPostContainersStart(t *testing.T) {
} }
r = httptest.NewRecorder() r = httptest.NewRecorder()
if err = postContainersStart(srv, APIVERSION, r, req, map[string]string{"name": id}); err == nil { if err = postContainersStart(srv, docker.APIVERSION, r, req, map[string]string{"name": id}); err == nil {
t.Fatalf("A running container should be able to be started") t.Fatalf("A running container should be able to be started")
} }
@ -812,7 +798,7 @@ func TestPostContainersStop(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &Config{
@ -844,7 +830,7 @@ func TestPostContainersStop(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := postContainersStop(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { if err := postContainersStop(srv, docker.APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Code != http.StatusNoContent { if r.Code != http.StatusNoContent {
@ -859,7 +845,7 @@ func TestPostContainersWait(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &Config{
@ -880,7 +866,7 @@ func TestPostContainersWait(t *testing.T) {
setTimeout(t, "Wait timed out", 3*time.Second, func() { setTimeout(t, "Wait timed out", 3*time.Second, func() {
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := postContainersWait(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { if err := postContainersWait(srv, docker.APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
apiWait := &APIWait{} apiWait := &APIWait{}
@ -901,7 +887,7 @@ func TestPostContainersAttach(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &Config{
@ -946,7 +932,7 @@ func TestPostContainersAttach(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if err := postContainersAttach(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { if err := postContainersAttach(srv, docker.APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
}() }()
@ -990,7 +976,7 @@ func TestPostContainersAttachStderr(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &Config{
@ -1035,7 +1021,7 @@ func TestPostContainersAttachStderr(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if err := postContainersAttach(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { if err := postContainersAttach(srv, docker.APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
}() }()
@ -1082,7 +1068,7 @@ func TestDeleteContainers(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
@ -1102,7 +1088,7 @@ func TestDeleteContainers(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := deleteContainers(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { if err := deleteContainers(srv, docker.APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r.Code != http.StatusNoContent { if r.Code != http.StatusNoContent {
@ -1123,7 +1109,7 @@ func TestOptionsRoute(t *testing.T) {
defer nuke(runtime) defer nuke(runtime)
runtime.config.EnableCors = true runtime.config.EnableCors = true
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
r := httptest.NewRecorder() r := httptest.NewRecorder()
router, err := createRouter(srv, false) router, err := createRouter(srv, false)
@ -1147,7 +1133,7 @@ func TestGetEnabledCors(t *testing.T) {
defer nuke(runtime) defer nuke(runtime)
runtime.config.EnableCors = true runtime.config.EnableCors = true
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
r := httptest.NewRecorder() r := httptest.NewRecorder()
@ -1185,7 +1171,7 @@ func TestDeleteImages(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
initialImages, err := srv.Images(false, "") initialImages, err := srv.Images(false, "")
if err != nil { if err != nil {
@ -1211,7 +1197,7 @@ func TestDeleteImages(t *testing.T) {
} }
r := httptest.NewRecorder() r := httptest.NewRecorder()
if err := deleteImages(srv, APIVERSION, r, req, map[string]string{"name": unitTestImageID}); err == nil { if err := deleteImages(srv, docker.APIVERSION, r, req, map[string]string{"name": unitTestImageID}); err == nil {
t.Fatalf("Expected conflict error, got none") t.Fatalf("Expected conflict error, got none")
} }
@ -1221,7 +1207,7 @@ func TestDeleteImages(t *testing.T) {
} }
r2 := httptest.NewRecorder() r2 := httptest.NewRecorder()
if err := deleteImages(srv, APIVERSION, r2, req2, map[string]string{"name": "test:test"}); err != nil { if err := deleteImages(srv, docker.APIVERSION, r2, req2, map[string]string{"name": "test:test"}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if r2.Code != http.StatusOK { if r2.Code != http.StatusOK {
@ -1243,14 +1229,6 @@ func TestDeleteImages(t *testing.T) {
if len(images[0].RepoTags) != len(initialImages[0].RepoTags) { if len(images[0].RepoTags) != len(initialImages[0].RepoTags) {
t.Errorf("Expected %d image, %d found", len(initialImages), len(images)) t.Errorf("Expected %d image, %d found", len(initialImages), len(images))
} }
/* if c := runtime.Get(container.Id); c != nil {
t.Fatalf("The container as not been deleted")
}
if _, err := os.Stat(path.Join(container.rwPath(), "test")); err == nil {
t.Fatalf("The test file has not been deleted")
} */
} }
func TestJsonContentType(t *testing.T) { func TestJsonContentType(t *testing.T) {
@ -1271,7 +1249,7 @@ func TestPostContainersCopy(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
srv := &Server{runtime: runtime} srv := &docker.Server{runtime: runtime}
// Create a container and remove a file // Create a container and remove a file
container, _, err := runtime.Create( container, _, err := runtime.Create(
@ -1303,7 +1281,7 @@ func TestPostContainersCopy(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
req.Header.Add("Content-Type", "application/json") req.Header.Add("Content-Type", "application/json")
if err = postContainersCopy(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { if err = postContainersCopy(srv, docker.APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1356,3 +1334,4 @@ func (t *hijackTester) Hijack() (net.Conn, *bufio.ReadWriter, error) {
} }
return conn, bufrw, nil return conn, bufrw, nil
} }
*/

View File

@ -2,7 +2,9 @@ package docker
import ( import (
"fmt" "fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/archive" "github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/engine"
"io/ioutil" "io/ioutil"
"net" "net"
"net/http" "net/http"
@ -14,7 +16,7 @@ import (
// mkTestContext generates a build context from the contents of the provided dockerfile. // mkTestContext generates a build context from the contents of the provided dockerfile.
// This context is suitable for use as an argument to BuildFile.Build() // This context is suitable for use as an argument to BuildFile.Build()
func mkTestContext(dockerfile string, files [][2]string, t *testing.T) archive.Archive { func mkTestContext(dockerfile string, files [][2]string, t *testing.T) archive.Archive {
context, err := mkBuildContext(dockerfile, files) context, err := docker.MkBuildContext(dockerfile, files)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -228,17 +230,15 @@ func TestBuild(t *testing.T) {
} }
} }
func buildImage(context testContextTemplate, t *testing.T, srv *Server, useCache bool) *Image { func buildImage(context testContextTemplate, t *testing.T, eng *engine.Engine, useCache bool) *docker.Image {
if srv == nil { if eng == nil {
runtime := mkRuntime(t) eng = NewTestEngine(t)
runtime := mkRuntimeFromEngine(eng, t)
// FIXME: we might not need runtime, why not simply nuke
// the engine?
defer nuke(runtime) defer nuke(runtime)
srv = &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
} }
srv := mkServerFromEngine(eng, t)
httpServer, err := mkTestingFileServer(context.remoteFiles) httpServer, err := mkTestingFileServer(context.remoteFiles)
if err != nil { if err != nil {
@ -252,10 +252,17 @@ func buildImage(context testContextTemplate, t *testing.T, srv *Server, useCache
} }
port := httpServer.URL[idx+1:] port := httpServer.URL[idx+1:]
ip := srv.runtime.networkManager.bridgeNetwork.IP iIP := eng.Hack_GetGlobalVar("httpapi.bridgeIP")
if iIP == nil {
t.Fatal("Legacy bridgeIP field not set in engine")
}
ip, ok := iIP.(net.IP)
if !ok {
panic("Legacy bridgeIP field in engine does not cast to net.IP")
}
dockerfile := constructDockerfile(context.dockerfile, ip, port) dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := NewBuildFile(srv, ioutil.Discard, false, useCache, false) buildfile := docker.NewBuildFile(srv, ioutil.Discard, false, useCache, false)
id, err := buildfile.Build(mkTestContext(dockerfile, context.files, t)) id, err := buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -368,20 +375,14 @@ func TestBuildEntrypoint(t *testing.T) {
// testing #1405 - config.Cmd does not get cleaned up if // testing #1405 - config.Cmd does not get cleaned up if
// utilizing cache // utilizing cache
func TestBuildEntrypointRunCleanup(t *testing.T) { func TestBuildEntrypointRunCleanup(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer nuke(mkRuntimeFromEngine(eng, t))
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
img := buildImage(testContextTemplate{` img := buildImage(testContextTemplate{`
from {IMAGE} from {IMAGE}
run echo "hello" run echo "hello"
`, `,
nil, nil}, t, srv, true) nil, nil}, t, eng, true)
img = buildImage(testContextTemplate{` img = buildImage(testContextTemplate{`
from {IMAGE} from {IMAGE}
@ -389,7 +390,7 @@ func TestBuildEntrypointRunCleanup(t *testing.T) {
add foo /foo add foo /foo
entrypoint ["/bin/echo"] entrypoint ["/bin/echo"]
`, `,
[][2]string{{"foo", "HEYO"}}, nil}, t, srv, true) [][2]string{{"foo", "HEYO"}}, nil}, t, eng, true)
if len(img.Config.Cmd) != 0 { if len(img.Config.Cmd) != 0 {
t.Fail() t.Fail()
@ -397,14 +398,8 @@ func TestBuildEntrypointRunCleanup(t *testing.T) {
} }
func TestBuildImageWithCache(t *testing.T) { func TestBuildImageWithCache(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer nuke(mkRuntimeFromEngine(eng, t))
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
template := testContextTemplate{` template := testContextTemplate{`
from {IMAGE} from {IMAGE}
@ -412,11 +407,11 @@ func TestBuildImageWithCache(t *testing.T) {
`, `,
nil, nil} nil, nil}
img := buildImage(template, t, srv, true) img := buildImage(template, t, eng, true)
imageId := img.ID imageId := img.ID
img = nil img = nil
img = buildImage(template, t, srv, true) img = buildImage(template, t, eng, true)
if imageId != img.ID { if imageId != img.ID {
t.Logf("Image ids should match: %s != %s", imageId, img.ID) t.Logf("Image ids should match: %s != %s", imageId, img.ID)
@ -425,14 +420,8 @@ func TestBuildImageWithCache(t *testing.T) {
} }
func TestBuildImageWithoutCache(t *testing.T) { func TestBuildImageWithoutCache(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer nuke(mkRuntimeFromEngine(eng, t))
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
template := testContextTemplate{` template := testContextTemplate{`
from {IMAGE} from {IMAGE}
@ -440,11 +429,11 @@ func TestBuildImageWithoutCache(t *testing.T) {
`, `,
nil, nil} nil, nil}
img := buildImage(template, t, srv, true) img := buildImage(template, t, eng, true)
imageId := img.ID imageId := img.ID
img = nil img = nil
img = buildImage(template, t, srv, false) img = buildImage(template, t, eng, false)
if imageId == img.ID { if imageId == img.ID {
t.Logf("Image ids should not match: %s == %s", imageId, img.ID) t.Logf("Image ids should not match: %s == %s", imageId, img.ID)
@ -453,14 +442,9 @@ func TestBuildImageWithoutCache(t *testing.T) {
} }
func TestForbiddenContextPath(t *testing.T) { func TestForbiddenContextPath(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer nuke(mkRuntimeFromEngine(eng, t))
srv := mkServerFromEngine(eng, t)
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
context := testContextTemplate{` context := testContextTemplate{`
from {IMAGE} from {IMAGE}
@ -481,10 +465,17 @@ func TestForbiddenContextPath(t *testing.T) {
} }
port := httpServer.URL[idx+1:] port := httpServer.URL[idx+1:]
ip := srv.runtime.networkManager.bridgeNetwork.IP iIP := eng.Hack_GetGlobalVar("httpapi.bridgeIP")
if iIP == nil {
t.Fatal("Legacy bridgeIP field not set in engine")
}
ip, ok := iIP.(net.IP)
if !ok {
panic("Legacy bridgeIP field in engine does not cast to net.IP")
}
dockerfile := constructDockerfile(context.dockerfile, ip, port) dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := NewBuildFile(srv, ioutil.Discard, false, true, false) buildfile := docker.NewBuildFile(srv, ioutil.Discard, false, true, false)
_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t)) _, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err == nil { if err == nil {
@ -499,14 +490,8 @@ func TestForbiddenContextPath(t *testing.T) {
} }
func TestBuildADDFileNotFound(t *testing.T) { func TestBuildADDFileNotFound(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer nuke(mkRuntimeFromEngine(eng, t))
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
context := testContextTemplate{` context := testContextTemplate{`
from {IMAGE} from {IMAGE}
@ -526,10 +511,17 @@ func TestBuildADDFileNotFound(t *testing.T) {
} }
port := httpServer.URL[idx+1:] port := httpServer.URL[idx+1:]
ip := srv.runtime.networkManager.bridgeNetwork.IP iIP := eng.Hack_GetGlobalVar("httpapi.bridgeIP")
if iIP == nil {
t.Fatal("Legacy bridgeIP field not set in engine")
}
ip, ok := iIP.(net.IP)
if !ok {
panic("Legacy bridgeIP field in engine does not cast to net.IP")
}
dockerfile := constructDockerfile(context.dockerfile, ip, port) dockerfile := constructDockerfile(context.dockerfile, ip, port)
buildfile := NewBuildFile(srv, ioutil.Discard, false, true, false) buildfile := docker.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, false, true, false)
_, err = buildfile.Build(mkTestContext(dockerfile, context.files, t)) _, err = buildfile.Build(mkTestContext(dockerfile, context.files, t))
if err == nil { if err == nil {
@ -544,26 +536,20 @@ func TestBuildADDFileNotFound(t *testing.T) {
} }
func TestBuildInheritance(t *testing.T) { func TestBuildInheritance(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer nuke(mkRuntimeFromEngine(eng, t))
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
img := buildImage(testContextTemplate{` img := buildImage(testContextTemplate{`
from {IMAGE} from {IMAGE}
expose 4243 expose 4243
`, `,
nil, nil}, t, srv, true) nil, nil}, t, eng, true)
img2 := buildImage(testContextTemplate{fmt.Sprintf(` img2 := buildImage(testContextTemplate{fmt.Sprintf(`
from %s from %s
entrypoint ["/bin/echo"] entrypoint ["/bin/echo"]
`, img.ID), `, img.ID),
nil, nil}, t, srv, true) nil, nil}, t, eng, true)
// from child // from child
if img2.Config.Entrypoint[0] != "/bin/echo" { if img2.Config.Entrypoint[0] != "/bin/echo" {

View File

@ -3,6 +3,8 @@ package docker
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
"io" "io"
"io/ioutil" "io/ioutil"
@ -66,8 +68,8 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error
func TestRunHostname(t *testing.T) { func TestRunHostname(t *testing.T) {
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -111,8 +113,8 @@ func TestRunHostname(t *testing.T) {
func TestRunWorkdir(t *testing.T) { func TestRunWorkdir(t *testing.T) {
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -156,8 +158,8 @@ func TestRunWorkdir(t *testing.T) {
func TestRunWorkdirExists(t *testing.T) { func TestRunWorkdirExists(t *testing.T) {
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -201,8 +203,8 @@ func TestRunExit(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c1 := make(chan struct{}) c1 := make(chan struct{})
go func() { go func() {
@ -254,8 +256,8 @@ func TestRunDisconnect(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c1 := make(chan struct{}) c1 := make(chan struct{})
go func() { go func() {
@ -299,8 +301,8 @@ func TestRunDisconnectTty(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c1 := make(chan struct{}) c1 := make(chan struct{})
go func() { go func() {
@ -356,8 +358,8 @@ func TestRunAttachStdin(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
ch := make(chan struct{}) ch := make(chan struct{})
go func() { go func() {
@ -420,8 +422,8 @@ func TestRunDetach(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
ch := make(chan struct{}) ch := make(chan struct{})
go func() { go func() {
@ -466,8 +468,8 @@ func TestAttachDetach(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
ch := make(chan struct{}) ch := make(chan struct{})
go func() { go func() {
@ -477,7 +479,7 @@ func TestAttachDetach(t *testing.T) {
} }
}() }()
var container *Container var container *docker.Container
setTimeout(t, "Reading container's id timed out", 10*time.Second, func() { setTimeout(t, "Reading container's id timed out", 10*time.Second, func() {
buf := make([]byte, 1024) buf := make([]byte, 1024)
@ -498,7 +500,7 @@ func TestAttachDetach(t *testing.T) {
stdin, stdinPipe = io.Pipe() stdin, stdinPipe = io.Pipe()
stdout, stdoutPipe = io.Pipe() stdout, stdoutPipe = io.Pipe()
cli = NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli = docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
ch = make(chan struct{}) ch = make(chan struct{})
go func() { go func() {
@ -546,8 +548,8 @@ func TestAttachDetachTruncatedID(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
go stdout.Read(make([]byte, 1024)) go stdout.Read(make([]byte, 1024))
setTimeout(t, "Starting container timed out", 2*time.Second, func() { setTimeout(t, "Starting container timed out", 2*time.Second, func() {
@ -560,7 +562,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
stdin, stdinPipe = io.Pipe() stdin, stdinPipe = io.Pipe()
stdout, stdoutPipe = io.Pipe() stdout, stdoutPipe = io.Pipe()
cli = NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli = docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
ch := make(chan struct{}) ch := make(chan struct{})
go func() { go func() {
@ -608,8 +610,8 @@ func TestAttachDisconnect(t *testing.T) {
stdin, stdinPipe := io.Pipe() stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
go func() { go func() {
// Start a process in daemon mode // Start a process in daemon mode
@ -677,8 +679,8 @@ func TestAttachDisconnect(t *testing.T) {
func TestRunAutoRemove(t *testing.T) { func TestRunAutoRemove(t *testing.T) {
t.Skip("Fixme. Skipping test for now, race condition") t.Skip("Fixme. Skipping test for now, race condition")
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -712,8 +714,8 @@ func TestRunAutoRemove(t *testing.T) {
} }
func TestCmdLogs(t *testing.T) { func TestCmdLogs(t *testing.T) {
cli := NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
if err := cli.CmdRun(unitTestImageID, "sh", "-c", "ls -l"); err != nil { if err := cli.CmdRun(unitTestImageID, "sh", "-c", "ls -l"); err != nil {
t.Fatal(err) t.Fatal(err)
@ -730,8 +732,8 @@ func TestCmdLogs(t *testing.T) {
// Expected behaviour: using / as a bind mount source should throw an error // Expected behaviour: using / as a bind mount source should throw an error
func TestRunErrorBindMountRootSource(t *testing.T) { func TestRunErrorBindMountRootSource(t *testing.T) {
cli := NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -749,8 +751,8 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
// Expected behaviour: error out when attempting to bind mount non-existing source paths // Expected behaviour: error out when attempting to bind mount non-existing source paths
func TestRunErrorBindNonExistingSource(t *testing.T) { func TestRunErrorBindNonExistingSource(t *testing.T) {
cli := NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -768,11 +770,10 @@ func TestRunErrorBindNonExistingSource(t *testing.T) {
func TestImagesViz(t *testing.T) { func TestImagesViz(t *testing.T) {
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
srv := &Server{runtime: globalRuntime} image := buildTestImages(t, globalEngine)
image := buildTestImages(t, srv)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -819,11 +820,10 @@ func TestImagesViz(t *testing.T) {
func TestImagesTree(t *testing.T) { func TestImagesTree(t *testing.T) {
stdout, stdoutPipe := io.Pipe() stdout, stdoutPipe := io.Pipe()
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
srv := &Server{runtime: globalRuntime} image := buildTestImages(t, globalEngine)
image := buildTestImages(t, srv)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
@ -867,7 +867,7 @@ func TestImagesTree(t *testing.T) {
}) })
} }
func buildTestImages(t *testing.T, srv *Server) *Image { func buildTestImages(t *testing.T, eng *engine.Engine) *docker.Image {
var testBuilder = testContextTemplate{ var testBuilder = testContextTemplate{
` `
@ -880,9 +880,9 @@ run [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]
nil, nil,
nil, nil,
} }
image := buildImage(testBuilder, t, srv, true) image := buildImage(testBuilder, t, eng, true)
err := srv.ContainerTag(image.ID, "test", "latest", false) err := mkServerFromEngine(eng, t).ContainerTag(image.ID, "test", "latest", false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -902,8 +902,8 @@ func TestRunCidFile(t *testing.T) {
} }
tmpCidFile := path.Join(tmpDir, "cid") tmpCidFile := path.Join(tmpDir, "cid")
cli := NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr) cli := docker.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr)
defer cleanup(globalRuntime) defer cleanup(globalEngine, t)
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {

View File

@ -3,10 +3,10 @@ package docker
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
"io" "io"
"io/ioutil" "io/ioutil"
"math/rand"
"os" "os"
"path" "path"
"regexp" "regexp"
@ -20,7 +20,7 @@ func TestIDFormat(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container1, _, err := runtime.Create( container1, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/sh", "-c", "echo hello world"}, Cmd: []string{"/bin/sh", "-c", "echo hello world"},
}, },
@ -134,7 +134,8 @@ func TestMultipleAttachRestart(t *testing.T) {
} }
func TestDiff(t *testing.T) { func TestDiff(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
runtime := mkRuntimeFromEngine(eng, t)
defer nuke(runtime) defer nuke(runtime)
// Create a container and remove a file // Create a container and remove a file
container1, _ := mkContainer(runtime, []string{"_", "/bin/rm", "/etc/passwd"}, t) container1, _ := mkContainer(runtime, []string{"_", "/bin/rm", "/etc/passwd"}, t)
@ -169,11 +170,7 @@ func TestDiff(t *testing.T) {
} }
// Commit the container // Commit the container
rwTar, err := container1.ExportRw() img, err := runtime.Commit(container1, "", "", "unit test commited image - diff", "", nil)
if err != nil {
t.Error(err)
}
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image - diff", "", nil)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -237,11 +234,7 @@ func TestCommitAutoRun(t *testing.T) {
t.Errorf("Container shouldn't be running") t.Errorf("Container shouldn't be running")
} }
rwTar, err := container1.ExportRw() img, err := runtime.Commit(container1, "", "", "unit test commited image", "", &docker.Config{Cmd: []string{"cat", "/world"}})
if err != nil {
t.Error(err)
}
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", &Config{Cmd: []string{"cat", "/world"}})
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -297,11 +290,7 @@ func TestCommitRun(t *testing.T) {
t.Errorf("Container shouldn't be running") t.Errorf("Container shouldn't be running")
} }
rwTar, err := container1.ExportRw() img, err := runtime.Commit(container1, "", "", "unit test commited image", "", nil)
if err != nil {
t.Error(err)
}
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", nil)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -391,7 +380,7 @@ func TestOutput(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foobar"}, Cmd: []string{"echo", "-n", "foobar"},
}, },
@ -414,7 +403,7 @@ func TestContainerNetwork(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"ping", "-c", "1", "127.0.0.1"}, Cmd: []string{"ping", "-c", "1", "127.0.0.1"},
}, },
@ -436,7 +425,7 @@ func TestKillDifferentUser(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"}, Cmd: []string{"cat"},
OpenStdin: true, OpenStdin: true,
@ -448,7 +437,9 @@ func TestKillDifferentUser(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
defer runtime.Destroy(container) defer runtime.Destroy(container)
defer container.stdin.Close() // FIXME @shykes: this seems redundant, but is very old, I'm leaving it in case
// there is a side effect I'm not seeing.
// defer container.stdin.Close()
if container.State.Running { if container.State.Running {
t.Errorf("Container shouldn't be running") t.Errorf("Container shouldn't be running")
@ -490,22 +481,35 @@ func TestKillDifferentUser(t *testing.T) {
// Test that creating a container with a volume doesn't crash. Regression test for #995. // Test that creating a container with a volume doesn't crash. Regression test for #995.
func TestCreateVolume(t *testing.T) { func TestCreateVolume(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
runtime := mkRuntimeFromEngine(eng, t)
defer nuke(runtime) defer nuke(runtime)
config, hc, _, err := ParseRun([]string{"-v", "/var/lib/data", GetTestImage(runtime).ID, "echo", "hello", "world"}, nil) config, hc, _, err := docker.ParseRun([]string{"-v", "/var/lib/data", unitTestImageID, "echo", "hello", "world"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
c, _, err := runtime.Create(config, "") jobCreate := eng.Job("create")
if err != nil { if err := jobCreate.ImportEnv(config); err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer runtime.Destroy(c) var id string
c.hostConfig = hc jobCreate.StdoutParseString(&id)
if err := c.Start(); err != nil { if err := jobCreate.Run(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
jobStart := eng.Job("start", id)
if err := jobStart.ImportEnv(hc); err != nil {
t.Fatal(err)
}
if err := jobStart.Run(); err != nil {
t.Fatal(err)
}
// FIXME: this hack can be removed once Wait is a job
c := runtime.Get(id)
if c == nil {
t.Fatalf("Couldn't retrieve container %s from runtime", id)
}
c.WaitTimeout(500 * time.Millisecond) c.WaitTimeout(500 * time.Millisecond)
c.Wait() c.Wait()
} }
@ -513,7 +517,7 @@ func TestCreateVolume(t *testing.T) {
func TestKill(t *testing.T) { func TestKill(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"sleep", "2"}, Cmd: []string{"sleep", "2"},
}, },
@ -557,7 +561,7 @@ func TestExitCode(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
trueContainer, _, err := runtime.Create(&Config{ trueContainer, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/true", ""}, Cmd: []string{"/bin/true", ""},
}, "") }, "")
@ -572,7 +576,7 @@ func TestExitCode(t *testing.T) {
t.Errorf("Unexpected exit code %d (expected 0)", trueContainer.State.ExitCode) t.Errorf("Unexpected exit code %d (expected 0)", trueContainer.State.ExitCode)
} }
falseContainer, _, err := runtime.Create(&Config{ falseContainer, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/false", ""}, Cmd: []string{"/bin/false", ""},
}, "") }, "")
@ -591,7 +595,7 @@ func TestExitCode(t *testing.T) {
func TestRestart(t *testing.T) { func TestRestart(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foobar"}, Cmd: []string{"echo", "-n", "foobar"},
}, },
@ -622,7 +626,7 @@ func TestRestart(t *testing.T) {
func TestRestartStdin(t *testing.T) { func TestRestartStdin(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"}, Cmd: []string{"cat"},
@ -700,7 +704,7 @@ func TestUser(t *testing.T) {
defer nuke(runtime) defer nuke(runtime)
// Default user must be root // Default user must be root
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"id"}, Cmd: []string{"id"},
}, },
@ -719,7 +723,7 @@ func TestUser(t *testing.T) {
} }
// Set a username // Set a username
container, _, err = runtime.Create(&Config{ container, _, err = runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"id"}, Cmd: []string{"id"},
@ -740,7 +744,7 @@ func TestUser(t *testing.T) {
} }
// Set a UID // Set a UID
container, _, err = runtime.Create(&Config{ container, _, err = runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"id"}, Cmd: []string{"id"},
@ -761,7 +765,7 @@ func TestUser(t *testing.T) {
} }
// Set a different user by uid // Set a different user by uid
container, _, err = runtime.Create(&Config{ container, _, err = runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"id"}, Cmd: []string{"id"},
@ -784,7 +788,7 @@ func TestUser(t *testing.T) {
} }
// Set a different user by username // Set a different user by username
container, _, err = runtime.Create(&Config{ container, _, err = runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"id"}, Cmd: []string{"id"},
@ -805,7 +809,7 @@ func TestUser(t *testing.T) {
} }
// Test an wrong username // Test an wrong username
container, _, err = runtime.Create(&Config{ container, _, err = runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"id"}, Cmd: []string{"id"},
@ -827,7 +831,7 @@ func TestMultipleContainers(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container1, _, err := runtime.Create(&Config{ container1, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"sleep", "2"}, Cmd: []string{"sleep", "2"},
}, },
@ -838,7 +842,7 @@ func TestMultipleContainers(t *testing.T) {
} }
defer runtime.Destroy(container1) defer runtime.Destroy(container1)
container2, _, err := runtime.Create(&Config{ container2, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"sleep", "2"}, Cmd: []string{"sleep", "2"},
}, },
@ -882,7 +886,7 @@ func TestMultipleContainers(t *testing.T) {
func TestStdin(t *testing.T) { func TestStdin(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"}, Cmd: []string{"cat"},
@ -927,7 +931,7 @@ func TestStdin(t *testing.T) {
func TestTty(t *testing.T) { func TestTty(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"}, Cmd: []string{"cat"},
@ -974,7 +978,7 @@ func TestEnv(t *testing.T) {
os.Setenv("TRICKY", "tri\ncky\n") os.Setenv("TRICKY", "tri\ncky\n")
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
config, _, _, err := ParseRun([]string{"-e=FALSE=true", "-e=TRUE", "-e=TRICKY", GetTestImage(runtime).ID, "env"}, nil) config, _, _, err := docker.ParseRun([]string{"-e=FALSE=true", "-e=TRUE", "-e=TRICKY", GetTestImage(runtime).ID, "env"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1028,7 +1032,7 @@ func TestEntrypoint(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Entrypoint: []string{"/bin/echo"}, Entrypoint: []string{"/bin/echo"},
Cmd: []string{"-n", "foobar"}, Cmd: []string{"-n", "foobar"},
@ -1052,7 +1056,7 @@ func TestEntrypointNoCmd(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Entrypoint: []string{"/bin/echo", "foobar"}, Entrypoint: []string{"/bin/echo", "foobar"},
}, },
@ -1071,96 +1075,11 @@ func TestEntrypointNoCmd(t *testing.T) {
} }
} }
func grepFile(t *testing.T, path string, pattern string) {
f, err := os.Open(path)
if err != nil {
t.Fatal(err)
}
defer f.Close()
r := bufio.NewReader(f)
var (
line string
)
err = nil
for err == nil {
line, err = r.ReadString('\n')
if strings.Contains(line, pattern) == true {
return
}
}
t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
}
func TestLXCConfig(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
// Memory is allocated randomly for testing
rand.Seed(time.Now().UTC().UnixNano())
memMin := 33554432
memMax := 536870912
mem := memMin + rand.Intn(memMax-memMin)
// CPU shares as well
cpuMin := 100
cpuMax := 10000
cpu := cpuMin + rand.Intn(cpuMax-cpuMin)
container, _, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/true"},
Hostname: "foobar",
Memory: int64(mem),
CpuShares: int64(cpu),
},
"",
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
container.generateLXCConfig()
grepFile(t, container.lxcConfigPath(), "lxc.utsname = foobar")
grepFile(t, container.lxcConfigPath(),
fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
grepFile(t, container.lxcConfigPath(),
fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
}
func TestCustomLxcConfig(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, _, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/true"},
Hostname: "foobar",
},
"",
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
container.hostConfig = &HostConfig{LxcConf: []KeyValuePair{
{
Key: "lxc.utsname",
Value: "docker",
},
{
Key: "lxc.cgroup.cpuset.cpus",
Value: "0,1",
},
}}
container.generateLXCConfig()
grepFile(t, container.lxcConfigPath(), "lxc.utsname = docker")
grepFile(t, container.lxcConfigPath(), "lxc.cgroup.cpuset.cpus = 0,1")
}
func BenchmarkRunSequencial(b *testing.B) { func BenchmarkRunSequencial(b *testing.B) {
runtime := mkRuntime(b) runtime := mkRuntime(b)
defer nuke(runtime) defer nuke(runtime)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foo"}, Cmd: []string{"echo", "-n", "foo"},
}, },
@ -1193,7 +1112,7 @@ func BenchmarkRunParallel(b *testing.B) {
complete := make(chan error) complete := make(chan error)
tasks = append(tasks, complete) tasks = append(tasks, complete)
go func(i int, complete chan error) { go func(i int, complete chan error) {
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foo"}, Cmd: []string{"echo", "-n", "foo"},
}, },
@ -1261,11 +1180,7 @@ func TestCopyVolumeUidGid(t *testing.T) {
t.Errorf("Container shouldn't be running") t.Errorf("Container shouldn't be running")
} }
rwTar, err := container1.ExportRw() img, err := r.Commit(container1, "", "", "unit test commited image", "", nil)
if err != nil {
t.Error(err)
}
img, err := r.graph.Create(rwTar, container1, "unit test commited image", "", nil)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -1298,11 +1213,7 @@ func TestCopyVolumeContent(t *testing.T) {
t.Errorf("Container shouldn't be running") t.Errorf("Container shouldn't be running")
} }
rwTar, err := container1.ExportRw() img, err := r.Commit(container1, "", "", "unit test commited image", "", nil)
if err != nil {
t.Error(err)
}
img, err := r.graph.Create(rwTar, container1, "unit test commited image", "", nil)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -1344,7 +1255,7 @@ func TestFromVolumesInReadonlyMode(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"}, Cmd: []string{"/bin/echo", "-n", "foobar"},
Volumes: map[string]struct{}{"/test": {}}, Volumes: map[string]struct{}{"/test": {}},
@ -1364,7 +1275,7 @@ func TestFromVolumesInReadonlyMode(t *testing.T) {
} }
container2, _, err := runtime.Create( container2, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"}, Cmd: []string{"/bin/echo", "-n", "foobar"},
VolumesFrom: container.ID + ":ro", VolumesFrom: container.ID + ":ro",
@ -1405,7 +1316,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"}, Cmd: []string{"/bin/echo", "-n", "foobar"},
Volumes: map[string]struct{}{"/test": {}}, Volumes: map[string]struct{}{"/test": {}},
@ -1425,7 +1336,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) {
} }
container2, _, err := runtime.Create( container2, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"}, Cmd: []string{"/bin/echo", "-n", "foobar"},
VolumesFrom: container.ID, VolumesFrom: container.ID,
@ -1461,7 +1372,7 @@ func TestRestartWithVolumes(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foobar"}, Cmd: []string{"echo", "-n", "foobar"},
Volumes: map[string]struct{}{"/test": {}}, Volumes: map[string]struct{}{"/test": {}},
@ -1505,7 +1416,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"}, Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
Volumes: map[string]struct{}{"/test": {}}, Volumes: map[string]struct{}{"/test": {}},
@ -1534,7 +1445,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
} }
container2, _, err := runtime.Create( container2, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"cat", "/test/foo"}, Cmd: []string{"cat", "/test/foo"},
VolumesFrom: container.ID, VolumesFrom: container.ID,
@ -1568,26 +1479,42 @@ func TestVolumesFromWithVolumes(t *testing.T) {
} }
func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) { func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
runtime := mkRuntimeFromEngine(eng, t)
defer nuke(runtime) defer nuke(runtime)
config, hc, _, err := ParseRun([]string{"-n=false", GetTestImage(runtime).ID, "ip", "addr", "show"}, nil) config, hc, _, err := docker.ParseRun([]string{"-n=false", GetTestImage(runtime).ID, "ip", "addr", "show"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
c, _, err := runtime.Create(config, "")
if err != nil { jobCreate := eng.Job("create")
if err := jobCreate.ImportEnv(config); err != nil {
t.Fatal(err) t.Fatal(err)
} }
var id string
jobCreate.StdoutParseString(&id)
if err := jobCreate.Run(); err != nil {
t.Fatal(err)
}
// FIXME: this hack can be removed once Wait is a job
c := runtime.Get(id)
if c == nil {
t.Fatalf("Couldn't retrieve container %s from runtime", id)
}
stdout, err := c.StdoutPipe() stdout, err := c.StdoutPipe()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer runtime.Destroy(c)
c.hostConfig = hc jobStart := eng.Job("start", id)
if err := c.Start(); err != nil { if err := jobStart.ImportEnv(hc); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := jobStart.Run(); err != nil {
t.Fatal(err)
}
c.WaitTimeout(500 * time.Millisecond) c.WaitTimeout(500 * time.Millisecond)
c.Wait() c.Wait()
output, err := ioutil.ReadAll(stdout) output, err := ioutil.ReadAll(stdout)
@ -1602,7 +1529,6 @@ func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
if !strings.HasSuffix(interfaces[0], ": lo") { if !strings.HasSuffix(interfaces[0], ": lo") {
t.Fatalf("Wrong interface in test container: expected [*: lo], got %s", interfaces) t.Fatalf("Wrong interface in test container: expected [*: lo], got %s", interfaces)
} }
} }
func TestPrivilegedCanMknod(t *testing.T) { func TestPrivilegedCanMknod(t *testing.T) {
@ -1641,7 +1567,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"}, Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
Volumes: map[string]struct{}{"/test": {}}, Volumes: map[string]struct{}{"/test": {}},
@ -1670,7 +1596,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
} }
container2, _, err := runtime.Create( container2, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"sh", "-c", "echo -n bar > /other/foo"}, Cmd: []string{"sh", "-c", "echo -n bar > /other/foo"},
Volumes: map[string]struct{}{"/other": {}}, Volumes: map[string]struct{}{"/other": {}},
@ -1692,7 +1618,7 @@ func TestMultipleVolumesFrom(t *testing.T) {
} }
container3, _, err := runtime.Create( container3, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"}, Cmd: []string{"/bin/echo", "-n", "foobar"},
VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","), VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","),
@ -1720,7 +1646,7 @@ func TestRestartGhost(t *testing.T) {
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create( container, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"}, Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
Volumes: map[string]struct{}{"/test": {}}, Volumes: map[string]struct{}{"/test": {}},

View File

@ -3,6 +3,7 @@ package docker
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/sysinit" "github.com/dotcloud/docker/sysinit"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
@ -15,7 +16,6 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"sync"
"syscall" "syscall"
"testing" "testing"
"time" "time"
@ -32,39 +32,33 @@ const (
) )
var ( var (
globalRuntime *Runtime // FIXME: globalRuntime is deprecated by globalEngine. All tests should be converted.
globalRuntime *docker.Runtime
globalEngine *engine.Engine
startFds int startFds int
startGoroutines int startGoroutines int
) )
func nuke(runtime *Runtime) error { // FIXME: nuke() is deprecated by Runtime.Nuke()
var wg sync.WaitGroup func nuke(runtime *docker.Runtime) error {
for _, container := range runtime.List() { return runtime.Nuke()
wg.Add(1)
go func(c *Container) {
c.Kill()
wg.Done()
}(container)
}
wg.Wait()
runtime.Close()
os.Remove(filepath.Join(runtime.config.Root, "linkgraph.db"))
return os.RemoveAll(runtime.config.Root)
} }
func cleanup(runtime *Runtime) error { // FIXME: cleanup and nuke are redundant.
func cleanup(eng *engine.Engine, t *testing.T) error {
runtime := mkRuntimeFromEngine(eng, t)
for _, container := range runtime.List() { for _, container := range runtime.List() {
container.Kill() container.Kill()
runtime.Destroy(container) runtime.Destroy(container)
} }
images, err := runtime.graph.Map() srv := mkServerFromEngine(eng, t)
images, err := srv.Images(true, "")
if err != nil { if err != nil {
return err return err
} }
for _, image := range images { for _, image := range images {
if image.ID != unitTestImageID { if image.ID != unitTestImageID {
runtime.graph.Delete(image.ID) srv.ImageDelete(image.ID, false)
} }
} }
return nil return nil
@ -133,10 +127,9 @@ func setupBaseImage() {
log.Fatalf("Unable to create a runtime for tests:", err) log.Fatalf("Unable to create a runtime for tests:", err)
} }
srv := mkServerFromEngine(eng, log.New(os.Stderr, "", 0)) srv := mkServerFromEngine(eng, log.New(os.Stderr, "", 0))
runtime := srv.runtime
// If the unit test is not found, try to download it. // If the unit test is not found, try to download it.
if img, err := runtime.repositories.LookupImage(unitTestImageName); err != nil || img.ID != unitTestImageID { if img, err := srv.ImageInspect(unitTestImageName); err != nil || img.ID != unitTestImageID {
// Retrieve the Image // Retrieve the Image
if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil, nil, true); err != nil { if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil, nil, true); err != nil {
log.Fatalf("Unable to pull the test image: %s", err) log.Fatalf("Unable to pull the test image: %s", err)
@ -151,8 +144,8 @@ func spawnGlobalDaemon() {
} }
t := log.New(os.Stderr, "", 0) t := log.New(os.Stderr, "", 0)
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) globalEngine = eng
globalRuntime = srv.runtime globalRuntime = mkRuntimeFromEngine(eng, t)
// Spawn a Daemon // Spawn a Daemon
go func() { go func() {
@ -174,8 +167,8 @@ func spawnGlobalDaemon() {
// FIXME: test that ImagePull(json=true) send correct json output // FIXME: test that ImagePull(json=true) send correct json output
func GetTestImage(runtime *Runtime) *Image { func GetTestImage(runtime *docker.Runtime) *docker.Image {
imgs, err := runtime.graph.Map() imgs, err := runtime.Graph().Map()
if err != nil { if err != nil {
log.Fatalf("Unable to get the test image:", err) log.Fatalf("Unable to get the test image:", err)
} }
@ -184,7 +177,7 @@ func GetTestImage(runtime *Runtime) *Image {
return image return image
} }
} }
log.Fatalf("Test image %v not found in %s: %s", unitTestImageID, runtime.graph.Root, imgs) log.Fatalf("Test image %v not found in %s: %s", unitTestImageID, runtime.Graph().Root, imgs)
return nil return nil
} }
@ -197,7 +190,7 @@ func TestRuntimeCreate(t *testing.T) {
t.Errorf("Expected 0 containers, %v found", len(runtime.List())) t.Errorf("Expected 0 containers, %v found", len(runtime.List()))
} }
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"ls", "-al"}, Cmd: []string{"ls", "-al"},
}, },
@ -239,12 +232,12 @@ func TestRuntimeCreate(t *testing.T) {
} }
// Make sure create with bad parameters returns an error // Make sure create with bad parameters returns an error
if _, _, err = runtime.Create(&Config{Image: GetTestImage(runtime).ID}, ""); err == nil { if _, _, err = runtime.Create(&docker.Config{Image: GetTestImage(runtime).ID}, ""); err == nil {
t.Fatal("Builder.Create should throw an error when Cmd is missing") t.Fatal("Builder.Create should throw an error when Cmd is missing")
} }
if _, _, err := runtime.Create( if _, _, err := runtime.Create(
&Config{ &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{}, Cmd: []string{},
}, },
@ -253,7 +246,7 @@ func TestRuntimeCreate(t *testing.T) {
t.Fatal("Builder.Create should throw an error when Cmd is empty") t.Fatal("Builder.Create should throw an error when Cmd is empty")
} }
config := &Config{ config := &docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/ls"}, Cmd: []string{"/bin/ls"},
PortSpecs: []string{"80"}, PortSpecs: []string{"80"},
@ -266,7 +259,7 @@ func TestRuntimeCreate(t *testing.T) {
} }
// test expose 80:8000 // test expose 80:8000
container, warnings, err := runtime.Create(&Config{ container, warnings, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"ls", "-al"}, Cmd: []string{"ls", "-al"},
PortSpecs: []string{"80:8000"}, PortSpecs: []string{"80:8000"},
@ -285,7 +278,7 @@ func TestDestroy(t *testing.T) {
runtime := mkRuntime(t) runtime := mkRuntime(t)
defer nuke(runtime) defer nuke(runtime)
container, _, err := runtime.Create(&Config{ container, _, err := runtime.Create(&docker.Config{
Image: GetTestImage(runtime).ID, Image: GetTestImage(runtime).ID,
Cmd: []string{"ls", "-al"}, Cmd: []string{"ls", "-al"},
}, "") }, "")
@ -312,12 +305,6 @@ func TestDestroy(t *testing.T) {
t.Errorf("Unable to get newly created container") t.Errorf("Unable to get newly created container")
} }
// Make sure the container root directory does not exist anymore
_, err = os.Stat(container.root)
if err == nil || !os.IsNotExist(err) {
t.Errorf("Container root directory still exists after destroy")
}
// Test double destroy // Test double destroy
if err := runtime.Destroy(container); err == nil { if err := runtime.Destroy(container); err == nil {
// It should have failed // It should have failed
@ -352,15 +339,21 @@ func TestGet(t *testing.T) {
} }
func startEchoServerContainer(t *testing.T, proto string) (*Runtime, *Container, string) { func startEchoServerContainer(t *testing.T, proto string) (*docker.Runtime, *docker.Container, string) {
var ( var (
err error err error
container *Container id string
strPort string strPort string
runtime = mkRuntime(t) eng = NewTestEngine(t)
port = 5554 runtime = mkRuntimeFromEngine(eng, t)
p Port port = 5554
p docker.Port
) )
defer func() {
if err != nil {
runtime.Nuke()
}
}()
for { for {
port += 1 port += 1
@ -373,37 +366,45 @@ func startEchoServerContainer(t *testing.T, proto string) (*Runtime, *Container,
} else { } else {
t.Fatal(fmt.Errorf("Unknown protocol %v", proto)) t.Fatal(fmt.Errorf("Unknown protocol %v", proto))
} }
ep := make(map[Port]struct{}, 1) ep := make(map[docker.Port]struct{}, 1)
p = Port(fmt.Sprintf("%s/%s", strPort, proto)) p = docker.Port(fmt.Sprintf("%s/%s", strPort, proto))
ep[p] = struct{}{} ep[p] = struct{}{}
container, _, err = runtime.Create(&Config{ jobCreate := eng.Job("create")
Image: GetTestImage(runtime).ID, jobCreate.Setenv("Image", unitTestImageID)
Cmd: []string{"sh", "-c", cmd}, jobCreate.SetenvList("Cmd", []string{"sh", "-c", cmd})
PortSpecs: []string{fmt.Sprintf("%s/%s", strPort, proto)}, jobCreate.SetenvList("PortSpecs", []string{fmt.Sprintf("%s/%s", strPort, proto)})
ExposedPorts: ep, jobCreate.SetenvJson("ExposedPorts", ep)
}, "") jobCreate.StdoutParseString(&id)
if err != nil { if err := jobCreate.Run(); err != nil {
nuke(runtime)
t.Fatal(err) t.Fatal(err)
} }
// FIXME: this relies on the undocumented behavior of runtime.Create
if container != nil { // which will return a nil error AND container if the exposed ports
// are invalid. That behavior should be fixed!
if id != "" {
break break
} }
t.Logf("Port %v already in use, trying another one", strPort) t.Logf("Port %v already in use, trying another one", strPort)
} }
container.hostConfig = &HostConfig{ jobStart := eng.Job("start", id)
PortBindings: make(map[Port][]PortBinding), portBindings := make(map[docker.Port][]docker.PortBinding)
} portBindings[p] = []docker.PortBinding{
container.hostConfig.PortBindings[p] = []PortBinding{
{}, {},
} }
if err := container.Start(); err != nil { if err := jobStart.SetenvJson("PortsBindings", portBindings); err != nil {
nuke(runtime)
t.Fatal(err) t.Fatal(err)
} }
if err := jobStart.Run(); err != nil {
t.Fatal(err)
}
container := runtime.Get(id)
if container == nil {
t.Fatalf("Couldn't fetch test container %s", id)
}
setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() { setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() {
for !container.State.Running { for !container.State.Running {
@ -504,8 +505,9 @@ func TestAllocateUDPPortLocalhost(t *testing.T) {
} }
func TestRestore(t *testing.T) { func TestRestore(t *testing.T) {
runtime1 := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime1) runtime1 := mkRuntimeFromEngine(eng, t)
defer runtime1.Nuke()
// Create a container with one instance of docker // Create a container with one instance of docker
container1, _ := mkContainer(runtime1, []string{"_", "ls", "-al"}, t) container1, _ := mkContainer(runtime1, []string{"_", "ls", "-al"}, t)
defer runtime1.Destroy(container1) defer runtime1.Destroy(container1)
@ -545,12 +547,14 @@ func TestRestore(t *testing.T) {
// Here are are simulating a docker restart - that is, reloading all containers // Here are are simulating a docker restart - that is, reloading all containers
// from scratch // from scratch
runtime1.config.AutoRestart = false job := eng.Job("initapi")
runtime2, err := NewRuntimeFromDirectory(runtime1.config) job.Setenv("Root", eng.Root())
if err != nil { job.SetenvBool("AutoRestart", false)
if err := job.Run(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer nuke(runtime2)
runtime2 := mkRuntimeFromEngine(eng, t)
if len(runtime2.List()) != 2 { if len(runtime2.List()) != 2 {
t.Errorf("Expected 2 container, %v found", len(runtime2.List())) t.Errorf("Expected 2 container, %v found", len(runtime2.List()))
} }
@ -575,7 +579,24 @@ func TestRestore(t *testing.T) {
} }
func TestReloadContainerLinks(t *testing.T) { func TestReloadContainerLinks(t *testing.T) {
runtime1 := mkRuntime(t) // FIXME: here we don't use NewTestEngine because it calls initapi with Autorestart=false,
// and we want to set it to true.
root, err := newTestDirectory(unitTestStoreBase)
if err != nil {
t.Fatal(err)
}
eng, err := engine.New(root)
if err != nil {
t.Fatal(err)
}
job := eng.Job("initapi")
job.Setenv("Root", eng.Root())
job.SetenvBool("Autorestart", true)
if err := job.Run(); err != nil {
t.Fatal(err)
}
runtime1 := mkRuntimeFromEngine(eng, t)
defer nuke(runtime1) defer nuke(runtime1)
// Create a container with one instance of docker // Create a container with one instance of docker
container1, _ := mkContainer(runtime1, []string{"-i", "_", "/bin/sh"}, t) container1, _ := mkContainer(runtime1, []string{"-i", "_", "/bin/sh"}, t)
@ -590,7 +611,9 @@ func TestReloadContainerLinks(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// Add a link to container 2 // Add a link to container 2
container1.hostConfig.Links = []string{"/" + container2.ID + ":first"} // FIXME @shykes: setting hostConfig.Links seems redundant with calling RegisterLink().
// Why do we need it @crosbymichael?
// container1.hostConfig.Links = []string{"/" + container2.ID + ":first"}
if err := runtime1.RegisterLink(container1, container2, "first"); err != nil { if err := runtime1.RegisterLink(container1, container2, "first"); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -612,12 +635,13 @@ func TestReloadContainerLinks(t *testing.T) {
// Here are are simulating a docker restart - that is, reloading all containers // Here are are simulating a docker restart - that is, reloading all containers
// from scratch // from scratch
runtime1.config.AutoRestart = true job = eng.Job("initapi")
runtime2, err := NewRuntimeFromDirectory(runtime1.config) job.Setenv("Root", eng.Root())
if err != nil { job.SetenvBool("AutoRestart", false)
if err := job.Run(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer nuke(runtime2) runtime2 := mkRuntimeFromEngine(eng, t)
if len(runtime2.List()) != 2 { if len(runtime2.List()) != 2 {
t.Errorf("Expected 2 container, %v found", len(runtime2.List())) t.Errorf("Expected 2 container, %v found", len(runtime2.List()))
} }
@ -631,27 +655,32 @@ func TestReloadContainerLinks(t *testing.T) {
t.Fatalf("Expected 2 container alive, %d found", runningCount) t.Fatalf("Expected 2 container alive, %d found", runningCount)
} }
// FIXME: we no longer test if containers were registered in the right order,
// because there is no public
// Make sure container 2 ( the child of container 1 ) was registered and started first // Make sure container 2 ( the child of container 1 ) was registered and started first
// with the runtime // with the runtime
first := runtime2.containers.Front() //
if first.Value.(*Container).ID != container2.ID { containers := runtime2.List()
if len(containers) == 0 {
t.Fatalf("Runtime has no containers")
}
first := containers[0]
if first.ID != container2.ID {
t.Fatalf("Container 2 %s should be registered first in the runtime", container2.ID) t.Fatalf("Container 2 %s should be registered first in the runtime", container2.ID)
} }
// Verify that the link is still registered in the runtime // Verify that the link is still registered in the runtime
entity := runtime2.containerGraph.Get(container1.Name) if c := runtime2.Get(container1.Name); c == nil {
if entity == nil { t.Fatal("Named container is no longer registered after restart")
t.Fatal("Entity should not be nil")
} }
} }
func TestDefaultContainerName(t *testing.T) { func TestDefaultContainerName(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) runtime := mkRuntimeFromEngine(eng, t)
runtime := srv.runtime
defer nuke(runtime) defer nuke(runtime)
config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -663,29 +692,19 @@ func TestDefaultContainerName(t *testing.T) {
t.Fatalf("Expect /some_name got %s", container.Name) t.Fatalf("Expect /some_name got %s", container.Name)
} }
paths := runtime.containerGraph.RefPaths(containerID) if c := runtime.Get("/some_name"); c == nil {
if paths == nil || len(paths) == 0 { t.Fatalf("Couldn't retrieve test container as /some_name")
t.Fatalf("Could not find edges for %s", containerID) } else if c.ID != containerID {
} t.Fatalf("Container /some_name has ID %s instead of %s", c.ID, containerID)
edge := paths[0]
if edge.ParentID != "0" {
t.Fatalf("Expected engine got %s", edge.ParentID)
}
if edge.EntityID != containerID {
t.Fatalf("Expected %s got %s", containerID, edge.EntityID)
}
if edge.Name != "some_name" {
t.Fatalf("Expected some_name got %s", edge.Name)
} }
} }
func TestRandomContainerName(t *testing.T) { func TestRandomContainerName(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) runtime := mkRuntimeFromEngine(eng, t)
runtime := srv.runtime
defer nuke(runtime) defer nuke(runtime)
config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, _, _, err := docker.ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -697,29 +716,19 @@ func TestRandomContainerName(t *testing.T) {
t.Fatalf("Expected not empty container name") t.Fatalf("Expected not empty container name")
} }
paths := runtime.containerGraph.RefPaths(containerID) if c := runtime.Get(container.Name); c == nil {
if paths == nil || len(paths) == 0 { log.Fatalf("Could not lookup container %s by its name", container.Name)
t.Fatalf("Could not find edges for %s", containerID) } else if c.ID != containerID {
} log.Fatalf("Looking up container name %s returned id %s instead of %s", container.Name, c.ID, containerID)
edge := paths[0]
if edge.ParentID != "0" {
t.Fatalf("Expected engine got %s", edge.ParentID)
}
if edge.EntityID != containerID {
t.Fatalf("Expected %s got %s", containerID, edge.EntityID)
}
if edge.Name == "" {
t.Fatalf("Expected not empty container name")
} }
} }
func TestLinkChildContainer(t *testing.T) { func TestLinkChildContainer(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) runtime := mkRuntimeFromEngine(eng, t)
runtime := srv.runtime
defer nuke(runtime) defer nuke(runtime)
config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -735,7 +744,7 @@ func TestLinkChildContainer(t *testing.T) {
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID) t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
} }
config, _, _, err = ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, _, _, err = docker.ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -758,11 +767,10 @@ func TestLinkChildContainer(t *testing.T) {
func TestGetAllChildren(t *testing.T) { func TestGetAllChildren(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) runtime := mkRuntimeFromEngine(eng, t)
runtime := srv.runtime
defer nuke(runtime) defer nuke(runtime)
config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -778,7 +786,7 @@ func TestGetAllChildren(t *testing.T) {
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID) t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
} }
config, _, _, err = ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, _, _, err = docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -810,19 +818,3 @@ func TestGetAllChildren(t *testing.T) {
} }
} }
} }
func TestGetFullName(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
name, err := runtime.getFullName("testing")
if err != nil {
t.Fatal(err)
}
if name != "/testing" {
t.Fatalf("Expected /testing got %s", name)
}
if _, err := runtime.getFullName(""); err == nil {
t.Fatal("Error should not be nil")
}
}

View File

@ -1,32 +1,31 @@
package docker package docker
import ( import (
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
"io/ioutil" "io/ioutil"
"strings" "strings"
"testing" "testing"
"time"
) )
func TestContainerTagImageDelete(t *testing.T) { func TestContainerTagImageDelete(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer mkRuntimeFromEngine(eng, t).Nuke()
srv := &Server{runtime: runtime} srv := mkServerFromEngine(eng, t)
initialImages, err := srv.Images(false, "") initialImages, err := srv.Images(false, "")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := srv.ContainerTag(unitTestImageName, "utest", "tag1", false); err != nil {
if err := srv.runtime.repositories.Set("utest", "tag1", unitTestImageName, false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := srv.runtime.repositories.Set("utest/docker", "tag2", unitTestImageName, false); err != nil { if err := srv.ContainerTag(unitTestImageName, "utest/docker", "tag2", false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := srv.runtime.repositories.Set("utest:5000/docker", "tag3", unitTestImageName, false); err != nil { if err := srv.ContainerTag(unitTestImageName, "utest:5000/docker", "tag3", false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -82,46 +81,43 @@ func TestContainerTagImageDelete(t *testing.T) {
func TestCreateRm(t *testing.T) { func TestCreateRm(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) srv := mkServerFromEngine(eng, t)
runtime := srv.runtime defer mkRuntimeFromEngine(eng, t).Nuke()
defer nuke(runtime)
config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
id := createTestContainer(eng, config, t) id := createTestContainer(eng, config, t)
if len(runtime.List()) != 1 { if c := srv.Containers(true, false, -1, "", ""); len(c) != 1 {
t.Errorf("Expected 1 container, %v found", len(runtime.List())) t.Errorf("Expected 1 container, %v found", len(c))
} }
if err = srv.ContainerDestroy(id, true, false); err != nil { if err = srv.ContainerDestroy(id, true, false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if len(runtime.List()) != 0 { if c := srv.Containers(true, false, -1, "", ""); len(c) != 0 {
t.Errorf("Expected 0 container, %v found", len(runtime.List())) t.Errorf("Expected 0 container, %v found", len(c))
} }
} }
func TestCreateRmVolumes(t *testing.T) { func TestCreateRmVolumes(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) srv := mkServerFromEngine(eng, t)
runtime := srv.runtime defer mkRuntimeFromEngine(eng, t).Nuke()
defer nuke(runtime)
config, hostConfig, _, err := ParseRun([]string{"-v", "/srv", GetTestImage(runtime).ID, "echo test"}, nil) config, hostConfig, _, err := docker.ParseRun([]string{"-v", "/srv", unitTestImageID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
id := createTestContainer(eng, config, t) id := createTestContainer(eng, config, t)
if len(runtime.List()) != 1 { if c := srv.Containers(true, false, -1, "", ""); len(c) != 1 {
t.Errorf("Expected 1 container, %v found", len(runtime.List())) t.Errorf("Expected 1 container, %v found", len(c))
} }
job := eng.Job("start", id) job := eng.Job("start", id)
@ -141,18 +137,17 @@ func TestCreateRmVolumes(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if len(runtime.List()) != 0 { if c := srv.Containers(true, false, -1, "", ""); len(c) != 0 {
t.Errorf("Expected 0 container, %v found", len(runtime.List())) t.Errorf("Expected 0 container, %v found", len(c))
} }
} }
func TestCommit(t *testing.T) { func TestCommit(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) srv := mkServerFromEngine(eng, t)
runtime := srv.runtime defer mkRuntimeFromEngine(eng, t).Nuke()
defer nuke(runtime)
config, _, _, err := ParseRun([]string{GetTestImage(runtime).ID, "/bin/cat"}, nil) config, _, _, err := docker.ParseRun([]string{unitTestImageID, "/bin/cat"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -167,18 +162,17 @@ func TestCommit(t *testing.T) {
func TestCreateStartRestartStopStartKillRm(t *testing.T) { func TestCreateStartRestartStopStartKillRm(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) srv := mkServerFromEngine(eng, t)
runtime := srv.runtime defer mkRuntimeFromEngine(eng, t).Nuke()
defer nuke(runtime)
config, hostConfig, _, err := ParseRun([]string{GetTestImage(runtime).ID, "/bin/cat"}, nil) config, hostConfig, _, err := docker.ParseRun([]string{unitTestImageID, "/bin/cat"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
id := createTestContainer(eng, config, t) id := createTestContainer(eng, config, t)
if len(runtime.List()) != 1 { if c := srv.Containers(true, false, -1, "", ""); len(c) != 1 {
t.Errorf("Expected 1 container, %v found", len(runtime.List())) t.Errorf("Expected 1 container, %v found", len(c))
} }
job := eng.Job("start", id) job := eng.Job("start", id)
@ -214,21 +208,18 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if len(runtime.List()) != 0 { if c := srv.Containers(true, false, -1, "", ""); len(c) != 0 {
t.Errorf("Expected 0 container, %v found", len(runtime.List())) t.Errorf("Expected 0 container, %v found", len(c))
} }
} }
func TestRunWithTooLowMemoryLimit(t *testing.T) { func TestRunWithTooLowMemoryLimit(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) defer mkRuntimeFromEngine(eng, t).Nuke()
runtime := srv.runtime
defer nuke(runtime)
// Try to create a container with a memory limit of 1 byte less than the minimum allowed limit. // Try to create a container with a memory limit of 1 byte less than the minimum allowed limit.
job := eng.Job("create") job := eng.Job("create")
job.Setenv("Image", GetTestImage(runtime).ID) job.Setenv("Image", unitTestImageID)
job.Setenv("Memory", "524287") job.Setenv("Memory", "524287")
job.Setenv("CpuShares", "1000") job.Setenv("CpuShares", "1000")
job.SetenvList("Cmd", []string{"/bin/cat"}) job.SetenvList("Cmd", []string{"/bin/cat"})
@ -239,163 +230,17 @@ func TestRunWithTooLowMemoryLimit(t *testing.T) {
} }
} }
func TestContainerTop(t *testing.T) {
t.Skip("Fixme. Skipping test for now. Reported error: 'server_test.go:236: Expected 2 processes, found 1.'")
runtime := mkRuntime(t)
defer nuke(runtime)
srv := &Server{runtime: runtime}
c, _ := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t)
c, err := mkContainer(runtime, []string{"_", "/bin/sh", "-c", "sleep 2"}, t)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(c)
if err := c.Start(); err != nil {
t.Fatal(err)
}
// Give some time to the process to start
c.WaitTimeout(500 * time.Millisecond)
if !c.State.Running {
t.Errorf("Container should be running")
}
procs, err := srv.ContainerTop(c.ID, "")
if err != nil {
t.Fatal(err)
}
if len(procs.Processes) != 2 {
t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes))
}
pos := -1
for i := 0; i < len(procs.Titles); i++ {
if procs.Titles[i] == "CMD" {
pos = i
break
}
}
if pos == -1 {
t.Fatalf("Expected CMD, not found.")
}
if procs.Processes[0][pos] != "sh" && procs.Processes[0][pos] != "busybox" {
t.Fatalf("Expected `busybox` or `sh`, found %s.", procs.Processes[0][pos])
}
if procs.Processes[1][pos] != "sh" && procs.Processes[1][pos] != "busybox" {
t.Fatalf("Expected `busybox` or `sh`, found %s.", procs.Processes[1][pos])
}
}
func TestPools(t *testing.T) {
runtime := mkRuntime(t)
srv := &Server{
runtime: runtime,
pullingPool: make(map[string]struct{}),
pushingPool: make(map[string]struct{}),
}
defer nuke(runtime)
err := srv.poolAdd("pull", "test1")
if err != nil {
t.Fatal(err)
}
err = srv.poolAdd("pull", "test2")
if err != nil {
t.Fatal(err)
}
err = srv.poolAdd("push", "test1")
if err == nil || err.Error() != "pull test1 is already in progress" {
t.Fatalf("Expected `pull test1 is already in progress`")
}
err = srv.poolAdd("pull", "test1")
if err == nil || err.Error() != "pull test1 is already in progress" {
t.Fatalf("Expected `pull test1 is already in progress`")
}
err = srv.poolAdd("wait", "test3")
if err == nil || err.Error() != "Unknown pool type" {
t.Fatalf("Expected `Unknown pool type`")
}
err = srv.poolRemove("pull", "test2")
if err != nil {
t.Fatal(err)
}
err = srv.poolRemove("pull", "test2")
if err != nil {
t.Fatal(err)
}
err = srv.poolRemove("pull", "test1")
if err != nil {
t.Fatal(err)
}
err = srv.poolRemove("push", "test1")
if err != nil {
t.Fatal(err)
}
err = srv.poolRemove("wait", "test3")
if err == nil || err.Error() != "Unknown pool type" {
t.Fatalf("Expected `Unknown pool type`")
}
}
func TestLogEvent(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
srv := &Server{
runtime: runtime,
events: make([]utils.JSONMessage, 0, 64),
listeners: make(map[string]chan utils.JSONMessage),
}
srv.LogEvent("fakeaction", "fakeid", "fakeimage")
listener := make(chan utils.JSONMessage)
srv.Lock()
srv.listeners["test"] = listener
srv.Unlock()
srv.LogEvent("fakeaction2", "fakeid", "fakeimage")
if len(srv.events) != 2 {
t.Fatalf("Expected 2 events, found %d", len(srv.events))
}
go func() {
time.Sleep(200 * time.Millisecond)
srv.LogEvent("fakeaction3", "fakeid", "fakeimage")
time.Sleep(200 * time.Millisecond)
srv.LogEvent("fakeaction4", "fakeid", "fakeimage")
}()
setTimeout(t, "Listening for events timed out", 2*time.Second, func() {
for i := 2; i < 4; i++ {
event := <-listener
if event != srv.events[i] {
t.Fatalf("Event received it different than expected")
}
}
})
}
func TestRmi(t *testing.T) { func TestRmi(t *testing.T) {
eng := NewTestEngine(t) eng := NewTestEngine(t)
srv := mkServerFromEngine(eng, t) srv := mkServerFromEngine(eng, t)
runtime := srv.runtime defer mkRuntimeFromEngine(eng, t).Nuke()
defer nuke(runtime)
initialImages, err := srv.Images(false, "") initialImages, err := srv.Images(false, "")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
config, hostConfig, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) config, hostConfig, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -471,19 +316,19 @@ func TestRmi(t *testing.T) {
} }
func TestImagesFilter(t *testing.T) { func TestImagesFilter(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer nuke(mkRuntimeFromEngine(eng, t))
srv := &Server{runtime: runtime} srv := mkServerFromEngine(eng, t)
if err := srv.runtime.repositories.Set("utest", "tag1", unitTestImageName, false); err != nil { if err := srv.ContainerTag(unitTestImageName, "utest", "tag1", false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := srv.runtime.repositories.Set("utest/docker", "tag2", unitTestImageName, false); err != nil { if err := srv.ContainerTag(unitTestImageName, "utest/docker", "tag2", false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := srv.runtime.repositories.Set("utest:5000/docker", "tag3", unitTestImageName, false); err != nil { if err := srv.ContainerTag(unitTestImageName, "utest:5000/docker", "tag3", false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -525,9 +370,9 @@ func TestImagesFilter(t *testing.T) {
} }
func TestImageInsert(t *testing.T) { func TestImageInsert(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer mkRuntimeFromEngine(eng, t).Nuke()
srv := &Server{runtime: runtime} srv := mkServerFromEngine(eng, t)
sf := utils.NewStreamFormatter(true) sf := utils.NewStreamFormatter(true)
// bad image name fails // bad image name fails
@ -536,12 +381,12 @@ func TestImageInsert(t *testing.T) {
} }
// bad url fails // bad url fails
if err := srv.ImageInsert(GetTestImage(runtime).ID, "http://bad_host_name_that_will_totally_fail.com/", "/foo", ioutil.Discard, sf); err == nil { if err := srv.ImageInsert(unitTestImageID, "http://bad_host_name_that_will_totally_fail.com/", "/foo", ioutil.Discard, sf); err == nil {
t.Fatal("expected an error and got none") t.Fatal("expected an error and got none")
} }
// success returns nil // success returns nil
if err := srv.ImageInsert(GetTestImage(runtime).ID, "https://www.docker.io/static/img/docker-top-logo.png", "/foo", ioutil.Discard, sf); err != nil { if err := srv.ImageInsert(unitTestImageID, "https://www.docker.io/static/img/docker-top-logo.png", "/foo", ioutil.Discard, sf); err != nil {
t.Fatalf("expected no error, but got %v", err) t.Fatalf("expected no error, but got %v", err)
} }
} }

View File

@ -1,25 +1,21 @@
package docker package docker
import ( import (
"fmt" "github.com/dotcloud/docker"
"github.com/dotcloud/docker/utils"
"io/ioutil"
"testing" "testing"
"time" "time"
) )
func TestServerListOrderedImagesByCreationDate(t *testing.T) { func TestServerListOrderedImagesByCreationDate(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
archive, err := fakeTar() if err := generateImage("", srv); err != nil {
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, err = runtime.graph.Create(archive, nil, "Testing", "", nil)
if err != nil {
t.Fatal(err)
}
srv := &Server{runtime: runtime}
images, err := srv.Images(true, "") images, err := srv.Images(true, "")
if err != nil { if err != nil {
@ -32,22 +28,22 @@ func TestServerListOrderedImagesByCreationDate(t *testing.T) {
} }
func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) { func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) {
runtime := mkRuntime(t) eng := NewTestEngine(t)
defer nuke(runtime) defer mkRuntimeFromEngine(eng, t).Nuke()
srv := mkServerFromEngine(eng, t)
err := generateImage("bar", runtime) err := generateImage("bar", srv)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
time.Sleep(time.Second) time.Sleep(time.Second)
err = generateImage("zed", runtime) err = generateImage("zed", srv)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
srv := &Server{runtime: runtime}
images, err := srv.Images(true, "") images, err := srv.Images(true, "")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -58,54 +54,10 @@ func TestServerListOrderedImagesByCreationDateAndTag(t *testing.T) {
} }
} }
func generateImage(name string, runtime *Runtime) error { func generateImage(name string, srv *docker.Server) error {
archive, err := fakeTar() archive, err := fakeTar()
if err != nil { if err != nil {
return err return err
} }
image, err := runtime.graph.Create(archive, nil, "Testing", "", nil) return srv.ImageImport("-", "repo", name, archive, ioutil.Discard, utils.NewStreamFormatter(true))
if err != nil {
return err
}
srv := &Server{runtime: runtime}
srv.ContainerTag(image.ID, "repo", name, false)
return nil
}
func TestSortUniquePorts(t *testing.T) {
ports := []Port{
Port("6379/tcp"),
Port("22/tcp"),
}
sortPorts(ports, func(ip, jp Port) bool {
return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp")
})
first := ports[0]
if fmt.Sprint(first) != "22/tcp" {
t.Log(fmt.Sprint(first))
t.Fail()
}
}
func TestSortSamePortWithDifferentProto(t *testing.T) {
ports := []Port{
Port("8888/tcp"),
Port("8888/udp"),
Port("6379/tcp"),
Port("6379/udp"),
}
sortPorts(ports, func(ip, jp Port) bool {
return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp")
})
first := ports[0]
if fmt.Sprint(first) != "6379/tcp" {
t.Fail()
}
} }

View File

@ -1,14 +1,15 @@
package docker package docker
import ( import (
"fmt" "archive/tar"
"bytes"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
"runtime"
"strings" "strings"
"testing" "testing"
) )
@ -17,20 +18,18 @@ import (
// It has to be named XXX_test.go, apparently, in other to access private functions // It has to be named XXX_test.go, apparently, in other to access private functions
// from other XXX_test.go functions. // from other XXX_test.go functions.
var globalTestID string
// Create a temporary runtime suitable for unit testing. // Create a temporary runtime suitable for unit testing.
// Call t.Fatal() at the first error. // Call t.Fatal() at the first error.
func mkRuntime(f utils.Fataler) *Runtime { func mkRuntime(f utils.Fataler) *docker.Runtime {
root, err := newTestDirectory(unitTestStoreBase) root, err := newTestDirectory(unitTestStoreBase)
if err != nil { if err != nil {
f.Fatal(err) f.Fatal(err)
} }
config := &DaemonConfig{ config := &docker.DaemonConfig{
Root: root, Root: root,
AutoRestart: false, AutoRestart: false,
} }
r, err := NewRuntimeFromDirectory(config) r, err := docker.NewRuntimeFromDirectory(config)
if err != nil { if err != nil {
f.Fatal(err) f.Fatal(err)
} }
@ -38,7 +37,7 @@ func mkRuntime(f utils.Fataler) *Runtime {
return r return r
} }
func createNamedTestContainer(eng *engine.Engine, config *Config, f utils.Fataler, name string) (shortId string) { func createNamedTestContainer(eng *engine.Engine, config *docker.Config, f utils.Fataler, name string) (shortId string) {
job := eng.Job("create", name) job := eng.Job("create", name)
if err := job.ImportEnv(config); err != nil { if err := job.ImportEnv(config); err != nil {
f.Fatal(err) f.Fatal(err)
@ -50,22 +49,34 @@ func createNamedTestContainer(eng *engine.Engine, config *Config, f utils.Fatale
return return
} }
func createTestContainer(eng *engine.Engine, config *Config, f utils.Fataler) (shortId string) { func createTestContainer(eng *engine.Engine, config *docker.Config, f utils.Fataler) (shortId string) {
return createNamedTestContainer(eng, config, f, "") return createNamedTestContainer(eng, config, f, "")
} }
func mkServerFromEngine(eng *engine.Engine, t utils.Fataler) *Server { func mkServerFromEngine(eng *engine.Engine, t utils.Fataler) *docker.Server {
iSrv := eng.Hack_GetGlobalVar("httpapi.server") iSrv := eng.Hack_GetGlobalVar("httpapi.server")
if iSrv == nil { if iSrv == nil {
panic("Legacy server field not set in engine") panic("Legacy server field not set in engine")
} }
srv, ok := iSrv.(*Server) srv, ok := iSrv.(*docker.Server)
if !ok { if !ok {
panic("Legacy server field in engine does not cast to *Server") panic("Legacy server field in engine does not cast to *docker.Server")
} }
return srv return srv
} }
func mkRuntimeFromEngine(eng *engine.Engine, t utils.Fataler) *docker.Runtime {
iRuntime := eng.Hack_GetGlobalVar("httpapi.runtime")
if iRuntime == nil {
panic("Legacy runtime field not set in engine")
}
runtime, ok := iRuntime.(*docker.Runtime)
if !ok {
panic("Legacy runtime field in engine does not cast to *docker.Runtime")
}
return runtime
}
func NewTestEngine(t utils.Fataler) *engine.Engine { func NewTestEngine(t utils.Fataler) *engine.Engine {
root, err := newTestDirectory(unitTestStoreBase) root, err := newTestDirectory(unitTestStoreBase)
if err != nil { if err != nil {
@ -87,31 +98,11 @@ func NewTestEngine(t utils.Fataler) *engine.Engine {
} }
func newTestDirectory(templateDir string) (dir string, err error) { func newTestDirectory(templateDir string) (dir string, err error) {
if globalTestID == "" { return utils.TestDirectory(templateDir)
globalTestID = GenerateID()[:4]
}
prefix := fmt.Sprintf("docker-test%s-%s-", globalTestID, getCallerName(2))
if prefix == "" {
prefix = "docker-test-"
}
dir, err = ioutil.TempDir("", prefix)
if err = os.Remove(dir); err != nil {
return
}
if err = utils.CopyDirectory(templateDir, dir); err != nil {
return
}
return
} }
func getCallerName(depth int) string { func getCallerName(depth int) string {
// Use the caller function name as a prefix. return utils.GetCallerName(depth)
// This helps trace temp directories back to their test.
pc, _, _, _ := runtime.Caller(depth + 1)
callerLongName := runtime.FuncForPC(pc).Name()
parts := strings.Split(callerLongName, ".")
callerShortName := parts[len(parts)-1]
return callerShortName
} }
// Write `content` to the file at path `dst`, creating it if necessary, // Write `content` to the file at path `dst`, creating it if necessary,
@ -152,8 +143,8 @@ func readFile(src string, t *testing.T) (content string) {
// dynamically replaced by the current test image. // dynamically replaced by the current test image.
// The caller is responsible for destroying the container. // The caller is responsible for destroying the container.
// Call t.Fatal() at the first error. // Call t.Fatal() at the first error.
func mkContainer(r *Runtime, args []string, t *testing.T) (*Container, error) { func mkContainer(r *docker.Runtime, args []string, t *testing.T) (*docker.Container, error) {
config, hostConfig, _, err := ParseRun(args, nil) config, _, _, err := docker.ParseRun(args, nil)
defer func() { defer func() {
if err != nil && t != nil { if err != nil && t != nil {
t.Fatal(err) t.Fatal(err)
@ -169,7 +160,13 @@ func mkContainer(r *Runtime, args []string, t *testing.T) (*Container, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.hostConfig = hostConfig // NOTE: hostConfig is ignored.
// If `args` specify privileged mode, custom lxc conf, external mount binds,
// port redirects etc. they will be ignored.
// This is because the correct way to set these things is to pass environment
// to the `start` job.
// FIXME: this helper function should be deprecated in favor of calling
// `create` and `start` jobs directly.
return c, nil return c, nil
} }
@ -177,7 +174,7 @@ func mkContainer(r *Runtime, args []string, t *testing.T) (*Container, error) {
// and return its standard output as a string. // 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. // 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. // 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) { func runContainer(r *docker.Runtime, args []string, t *testing.T) (output string, err error) {
defer func() { defer func() {
if err != nil && t != nil { if err != nil && t != nil {
t.Fatal(err) t.Fatal(err)
@ -205,289 +202,20 @@ func runContainer(r *Runtime, args []string, t *testing.T) (output string, err e
return return
} }
func TestCompareConfig(t *testing.T) { // FIXME: this is duplicated from graph_test.go in the docker package.
volumes1 := make(map[string]struct{}) func fakeTar() (io.Reader, error) {
volumes1["/test1"] = struct{}{} content := []byte("Hello world!\n")
config1 := Config{ buf := new(bytes.Buffer)
Dns: []string{"1.1.1.1", "2.2.2.2"}, tw := tar.NewWriter(buf)
PortSpecs: []string{"1111:1111", "2222:2222"}, for _, name := range []string{"/etc/postgres/postgres.conf", "/etc/passwd", "/var/log/postgres/postgres.conf"} {
Env: []string{"VAR1=1", "VAR2=2"}, hdr := new(tar.Header)
VolumesFrom: "11111111", hdr.Size = int64(len(content))
Volumes: volumes1, hdr.Name = name
} if err := tw.WriteHeader(hdr); err != nil {
config2 := Config{ return nil, err
Dns: []string{"0.0.0.0", "2.2.2.2"}, }
PortSpecs: []string{"1111:1111", "2222:2222"}, tw.Write([]byte(content))
Env: []string{"VAR1=1", "VAR2=2"},
VolumesFrom: "11111111",
Volumes: volumes1,
}
config3 := Config{
Dns: []string{"1.1.1.1", "2.2.2.2"},
PortSpecs: []string{"0000:0000", "2222:2222"},
Env: []string{"VAR1=1", "VAR2=2"},
VolumesFrom: "11111111",
Volumes: volumes1,
}
config4 := Config{
Dns: []string{"1.1.1.1", "2.2.2.2"},
PortSpecs: []string{"0000:0000", "2222:2222"},
Env: []string{"VAR1=1", "VAR2=2"},
VolumesFrom: "22222222",
Volumes: volumes1,
}
volumes2 := make(map[string]struct{})
volumes2["/test2"] = struct{}{}
config5 := Config{
Dns: []string{"1.1.1.1", "2.2.2.2"},
PortSpecs: []string{"0000:0000", "2222:2222"},
Env: []string{"VAR1=1", "VAR2=2"},
VolumesFrom: "11111111",
Volumes: volumes2,
}
if CompareConfig(&config1, &config2) {
t.Fatalf("CompareConfig should return false, Dns are different")
}
if CompareConfig(&config1, &config3) {
t.Fatalf("CompareConfig should return false, PortSpecs are different")
}
if CompareConfig(&config1, &config4) {
t.Fatalf("CompareConfig should return false, VolumesFrom are different")
}
if CompareConfig(&config1, &config5) {
t.Fatalf("CompareConfig should return false, Volumes are different")
}
if !CompareConfig(&config1, &config1) {
t.Fatalf("CompareConfig should return true")
}
}
func TestMergeConfig(t *testing.T) {
volumesImage := make(map[string]struct{})
volumesImage["/test1"] = struct{}{}
volumesImage["/test2"] = struct{}{}
configImage := &Config{
Dns: []string{"1.1.1.1", "2.2.2.2"},
PortSpecs: []string{"1111:1111", "2222:2222"},
Env: []string{"VAR1=1", "VAR2=2"},
VolumesFrom: "1111",
Volumes: volumesImage,
}
volumesUser := make(map[string]struct{})
volumesUser["/test3"] = struct{}{}
configUser := &Config{
Dns: []string{"3.3.3.3"},
PortSpecs: []string{"3333:2222", "3333:3333"},
Env: []string{"VAR2=3", "VAR3=3"},
Volumes: volumesUser,
}
if err := MergeConfig(configUser, configImage); err != nil {
t.Error(err)
}
if len(configUser.Dns) != 3 {
t.Fatalf("Expected 3 dns, 1.1.1.1, 2.2.2.2 and 3.3.3.3, found %d", len(configUser.Dns))
}
for _, dns := range configUser.Dns {
if dns != "1.1.1.1" && dns != "2.2.2.2" && dns != "3.3.3.3" {
t.Fatalf("Expected 1.1.1.1 or 2.2.2.2 or 3.3.3.3, found %s", dns)
}
}
if len(configUser.ExposedPorts) != 3 {
t.Fatalf("Expected 3 ExposedPorts, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts))
}
for portSpecs := range configUser.ExposedPorts {
if portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" {
t.Fatalf("Expected 1111 or 2222 or 3333, found %s", portSpecs)
}
}
if len(configUser.Env) != 3 {
t.Fatalf("Expected 3 env var, VAR1=1, VAR2=3 and VAR3=3, found %d", len(configUser.Env))
}
for _, env := range configUser.Env {
if env != "VAR1=1" && env != "VAR2=3" && env != "VAR3=3" {
t.Fatalf("Expected VAR1=1 or VAR2=3 or VAR3=3, found %s", env)
}
}
if len(configUser.Volumes) != 3 {
t.Fatalf("Expected 3 volumes, /test1, /test2 and /test3, found %d", len(configUser.Volumes))
}
for v := range configUser.Volumes {
if v != "/test1" && v != "/test2" && v != "/test3" {
t.Fatalf("Expected /test1 or /test2 or /test3, found %s", v)
}
}
if configUser.VolumesFrom != "1111" {
t.Fatalf("Expected VolumesFrom to be 1111, found %s", configUser.VolumesFrom)
}
ports, _, err := parsePortSpecs([]string{"0000"})
if err != nil {
t.Error(err)
}
configImage2 := &Config{
ExposedPorts: ports,
}
if err := MergeConfig(configUser, configImage2); err != nil {
t.Error(err)
}
if len(configUser.ExposedPorts) != 4 {
t.Fatalf("Expected 4 ExposedPorts, 0000, 1111, 2222 and 3333, found %d", len(configUser.ExposedPorts))
}
for portSpecs := range configUser.ExposedPorts {
if portSpecs.Port() != "0000" && portSpecs.Port() != "1111" && portSpecs.Port() != "2222" && portSpecs.Port() != "3333" {
t.Fatalf("Expected 0000 or 1111 or 2222 or 3333, found %s", portSpecs)
}
}
}
func TestParseLxcConfOpt(t *testing.T) {
opts := []string{"lxc.utsname=docker", "lxc.utsname = docker "}
for _, o := range opts {
k, v, err := parseLxcOpt(o)
if err != nil {
t.FailNow()
}
if k != "lxc.utsname" {
t.Fail()
}
if v != "docker" {
t.Fail()
}
}
}
func TestParseNetworkOptsPrivateOnly(t *testing.T) {
ports, bindings, err := parsePortSpecs([]string{"192.168.1.100::80"})
if err != nil {
t.Fatal(err)
}
if len(ports) != 1 {
t.Logf("Expected 1 got %d", len(ports))
t.FailNow()
}
if len(bindings) != 1 {
t.Logf("Expected 1 got %d", len(bindings))
t.FailNow()
}
for k := range ports {
if k.Proto() != "tcp" {
t.Logf("Expected tcp got %s", k.Proto())
t.Fail()
}
if k.Port() != "80" {
t.Logf("Expected 80 got %s", k.Port())
t.Fail()
}
b, exists := bindings[k]
if !exists {
t.Log("Binding does not exist")
t.FailNow()
}
if len(b) != 1 {
t.Logf("Expected 1 got %d", len(b))
t.FailNow()
}
s := b[0]
if s.HostPort != "" {
t.Logf("Expected \"\" got %s", s.HostPort)
t.Fail()
}
if s.HostIp != "192.168.1.100" {
t.Fail()
}
}
}
func TestParseNetworkOptsPublic(t *testing.T) {
ports, bindings, err := parsePortSpecs([]string{"192.168.1.100:8080:80"})
if err != nil {
t.Fatal(err)
}
if len(ports) != 1 {
t.Logf("Expected 1 got %d", len(ports))
t.FailNow()
}
if len(bindings) != 1 {
t.Logf("Expected 1 got %d", len(bindings))
t.FailNow()
}
for k := range ports {
if k.Proto() != "tcp" {
t.Logf("Expected tcp got %s", k.Proto())
t.Fail()
}
if k.Port() != "80" {
t.Logf("Expected 80 got %s", k.Port())
t.Fail()
}
b, exists := bindings[k]
if !exists {
t.Log("Binding does not exist")
t.FailNow()
}
if len(b) != 1 {
t.Logf("Expected 1 got %d", len(b))
t.FailNow()
}
s := b[0]
if s.HostPort != "8080" {
t.Logf("Expected 8080 got %s", s.HostPort)
t.Fail()
}
if s.HostIp != "192.168.1.100" {
t.Fail()
}
}
}
func TestParseNetworkOptsUdp(t *testing.T) {
ports, bindings, err := parsePortSpecs([]string{"192.168.1.100::6000/udp"})
if err != nil {
t.Fatal(err)
}
if len(ports) != 1 {
t.Logf("Expected 1 got %d", len(ports))
t.FailNow()
}
if len(bindings) != 1 {
t.Logf("Expected 1 got %d", len(bindings))
t.FailNow()
}
for k := range ports {
if k.Proto() != "udp" {
t.Logf("Expected udp got %s", k.Proto())
t.Fail()
}
if k.Port() != "6000" {
t.Logf("Expected 6000 got %s", k.Port())
t.Fail()
}
b, exists := bindings[k]
if !exists {
t.Log("Binding does not exist")
t.FailNow()
}
if len(b) != 1 {
t.Logf("Expected 1 got %d", len(b))
t.FailNow()
}
s := b[0]
if s.HostPort != "" {
t.Logf("Expected \"\" got %s", s.HostPort)
t.Fail()
}
if s.HostIp != "192.168.1.100" {
t.Fail()
}
} }
tw.Close()
return buf, nil
} }