60ddcaa1 |
package docker
import ( |
5bec9275 |
"archive/tar" |
310fec48 |
"bufio" |
b2b59ddb |
"bytes" |
60ddcaa1 |
"encoding/json"
"github.com/dotcloud/docker/auth" |
e7077320 |
"github.com/dotcloud/docker/utils" |
310fec48 |
"io"
"net" |
b2b59ddb |
"net/http"
"net/http/httptest" |
2a303dab |
"os"
"path" |
60ddcaa1 |
"testing" |
2a303dab |
"time" |
60ddcaa1 |
)
|
49e65683 |
func TestPostAuth(t *testing.T) { |
b2b59ddb |
runtime, err := newTestRuntime() |
60ddcaa1 |
if err != nil {
t.Fatal(err)
} |
b2b59ddb |
defer nuke(runtime) |
60ddcaa1 |
|
95dd6d31 |
srv := &Server{ |
b76d6120 |
runtime: runtime, |
95dd6d31 |
} |
60ddcaa1 |
|
b2b59ddb |
r := httptest.NewRecorder() |
60ddcaa1 |
|
b2b59ddb |
authConfig := &auth.AuthConfig{
Username: "utest",
Password: "utest",
Email: "utest@yopmail.com", |
60ddcaa1 |
}
|
fd224ee5 |
authConfigJSON, err := json.Marshal(authConfig) |
60ddcaa1 |
if err != nil {
t.Fatal(err)
} |
b2b59ddb |
|
fd224ee5 |
req, err := http.NewRequest("POST", "/auth", bytes.NewReader(authConfigJSON)) |
60ddcaa1 |
if err != nil {
t.Fatal(err)
}
|
fd224ee5 |
if err := postAuth(srv, APIVERSION, r, req, nil); err != nil { |
60ddcaa1 |
t.Fatal(err)
} |
10e19e4b |
|
53a8229c |
if r.Code != http.StatusOK && r.Code != 0 {
t.Fatalf("%d OK or 0 expected, received %d\n", http.StatusOK, r.Code) |
60ddcaa1 |
} |
24816a8b |
} |
60ddcaa1 |
|
24816a8b |
func TestGetVersion(t *testing.T) {
runtime, err := newTestRuntime() |
60ddcaa1 |
if err != nil {
t.Fatal(err)
} |
24816a8b |
defer nuke(runtime) |
60ddcaa1 |
|
24816a8b |
srv := &Server{runtime: runtime}
|
b9944683 |
r := httptest.NewRecorder()
|
fd224ee5 |
if err := getVersion(srv, APIVERSION, r, nil, nil); err != nil { |
60ddcaa1 |
t.Fatal(err)
}
|
fd224ee5 |
v := &APIVersion{} |
b9944683 |
if err = json.Unmarshal(r.Body.Bytes(), v); err != nil { |
60ddcaa1 |
t.Fatal(err)
} |
24816a8b |
if v.Version != VERSION {
t.Errorf("Excepted version %s, %s found", VERSION, v.Version) |
60ddcaa1 |
}
}
|
24816a8b |
func TestGetInfo(t *testing.T) { |
b2b59ddb |
runtime, err := newTestRuntime() |
60ddcaa1 |
if err != nil {
t.Fatal(err)
} |
b2b59ddb |
defer nuke(runtime) |
60ddcaa1 |
|
b2b59ddb |
srv := &Server{runtime: runtime} |
60ddcaa1 |
|
b9944683 |
r := httptest.NewRecorder()
|
fd224ee5 |
if err := getInfo(srv, APIVERSION, r, nil, nil); err != nil { |
60ddcaa1 |
t.Fatal(err)
} |
b9944683 |
|
fd224ee5 |
infos := &APIInfo{} |
b9944683 |
err = json.Unmarshal(r.Body.Bytes(), infos) |
60ddcaa1 |
if err != nil {
t.Fatal(err)
} |
8243f251 |
if infos.Images != 1 {
t.Errorf("Excepted images: %d, %d found", 1, infos.Images) |
60ddcaa1 |
}
}
|
fd224ee5 |
func TestGetImagesJSON(t *testing.T) { |
7e8b413b |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
60ddcaa1 |
|
7e8b413b |
srv := &Server{runtime: runtime} |
60ddcaa1 |
|
1990c49a |
// all=0
req, err := http.NewRequest("GET", "/images/json?all=0", nil) |
7e8b413b |
if err != nil {
t.Fatal(err)
}
|
b9944683 |
r := httptest.NewRecorder()
|
fd224ee5 |
if err := getImagesJSON(srv, APIVERSION, r, req, nil); err != nil { |
7e8b413b |
t.Fatal(err)
}
|
fd224ee5 |
images := []APIImages{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), &images); err != nil { |
7e8b413b |
t.Fatal(err)
} |
60ddcaa1 |
|
7e8b413b |
if len(images) != 1 {
t.Errorf("Excepted 1 image, %d found", len(images))
}
|
5bec9275 |
if images[0].Repository != unitTestImageName {
t.Errorf("Excepted image %s, %s found", unitTestImageName, images[0].Repository) |
7e8b413b |
} |
53a8229c |
|
b9944683 |
r2 := httptest.NewRecorder()
|
1990c49a |
// all=1 |
0c544357 |
req2, err := http.NewRequest("GET", "/images/json?all=true", nil) |
53a8229c |
if err != nil {
t.Fatal(err)
}
|
fd224ee5 |
if err := getImagesJSON(srv, APIVERSION, r2, req2, nil); err != nil { |
53a8229c |
t.Fatal(err)
}
|
fd224ee5 |
images2 := []APIImages{} |
b9944683 |
if err := json.Unmarshal(r2.Body.Bytes(), &images2); err != nil { |
53a8229c |
t.Fatal(err)
}
if len(images2) != 1 {
t.Errorf("Excepted 1 image, %d found", len(images2))
}
|
fd224ee5 |
if images2[0].ID != GetTestImage(runtime).ID {
t.Errorf("Retrieved image Id differs, expected %s, received %s", GetTestImage(runtime).ID, images2[0].ID) |
53a8229c |
}
|
b9944683 |
r3 := httptest.NewRecorder()
|
53a8229c |
// filter=a
req3, err := http.NewRequest("GET", "/images/json?filter=a", nil)
if err != nil {
t.Fatal(err)
}
|
fd224ee5 |
if err := getImagesJSON(srv, APIVERSION, r3, req3, nil); err != nil { |
53a8229c |
t.Fatal(err)
}
|
fd224ee5 |
images3 := []APIImages{} |
b9944683 |
if err := json.Unmarshal(r3.Body.Bytes(), &images3); err != nil { |
53a8229c |
t.Fatal(err)
}
if len(images3) != 0 {
t.Errorf("Excepted 1 image, %d found", len(images3))
} |
0c544357 |
r4 := httptest.NewRecorder()
// all=foobar
req4, err := http.NewRequest("GET", "/images/json?all=foobar", nil)
if err != nil {
t.Fatal(err)
}
|
fd224ee5 |
err = getImagesJSON(srv, APIVERSION, r4, req4, nil) |
0c544357 |
if err == nil {
t.Fatalf("Error expected, received none")
}
httpError(r4, err)
if r4.Code != http.StatusBadRequest {
t.Fatalf("%d Bad Request expected, received %d\n", http.StatusBadRequest, r4.Code)
} |
7e8b413b |
}
|
24816a8b |
func TestGetImagesViz(t *testing.T) { |
53a8229c |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
r := httptest.NewRecorder() |
fd224ee5 |
if err := getImagesViz(srv, APIVERSION, r, nil, nil); err != nil { |
53a8229c |
t.Fatal(err)
}
if r.Code != http.StatusOK {
t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
}
reader := bufio.NewReader(r.Body)
line, err := reader.ReadString('\n')
if err != nil {
t.Fatal(err)
}
if line != "digraph docker {\n" {
t.Errorf("Excepted digraph docker {\n, %s found", line)
} |
24816a8b |
}
func TestGetImagesSearch(t *testing.T) { |
7e8b413b |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
|
e7077320 |
srv := &Server{ |
b76d6120 |
runtime: runtime, |
e7077320 |
} |
7e8b413b |
|
b9944683 |
r := httptest.NewRecorder()
|
24816a8b |
req, err := http.NewRequest("GET", "/images/search?term=redis", nil) |
7e8b413b |
if err != nil {
t.Fatal(err)
} |
24816a8b |
|
fd224ee5 |
if err := getImagesSearch(srv, APIVERSION, r, req, nil); err != nil { |
7e8b413b |
t.Fatal(err)
} |
24816a8b |
|
fd224ee5 |
results := []APISearch{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), &results); err != nil { |
24816a8b |
t.Fatal(err)
}
if len(results) < 2 {
t.Errorf("Excepted at least 2 lines, %d found", len(results)) |
7e8b413b |
}
} |
60ddcaa1 |
|
24816a8b |
func TestGetImagesHistory(t *testing.T) { |
ede0793d |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
|
b9944683 |
r := httptest.NewRecorder()
|
fd224ee5 |
if err := getImagesHistory(srv, APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { |
ede0793d |
t.Fatal(err)
}
|
fd224ee5 |
history := []APIHistory{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), &history); err != nil { |
ede0793d |
t.Fatal(err)
}
if len(history) != 1 {
t.Errorf("Excepted 1 line, %d found", len(history))
}
}
|
24816a8b |
func TestGetImagesByName(t *testing.T) { |
ede0793d |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
|
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := getImagesByName(srv, APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { |
ede0793d |
t.Fatal(err)
}
|
24816a8b |
img := &Image{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), img); err != nil { |
ede0793d |
t.Fatal(err)
} |
fd224ee5 |
if img.ID != GetTestImage(runtime).ID || img.Comment != "Imported from http://get.docker.io/images/busybox" { |
24816a8b |
t.Errorf("Error inspecting image")
}
} |
ede0793d |
|
fd224ee5 |
func TestGetContainersJSON(t *testing.T) { |
24816a8b |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
ede0793d |
|
24816a8b |
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
24816a8b |
Cmd: []string{"echo", "test"},
}) |
ede0793d |
if err != nil {
t.Fatal(err)
} |
24816a8b |
defer runtime.Destroy(container)
|
4f944392 |
req, err := http.NewRequest("GET", "/containers/json?all=1", nil) |
24816a8b |
if err != nil {
t.Fatal(err)
}
|
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := getContainersJSON(srv, APIVERSION, r, req, nil); err != nil { |
24816a8b |
t.Fatal(err)
} |
fd224ee5 |
containers := []APIContainers{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), &containers); err != nil { |
24816a8b |
t.Fatal(err)
}
if len(containers) != 1 {
t.Fatalf("Excepted %d container, %d found", 1, len(containers))
} |
fd224ee5 |
if containers[0].ID != container.ID {
t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", container.ID, containers[0].ID) |
ede0793d |
}
}
|
24816a8b |
func TestGetContainersExport(t *testing.T) { |
53a8229c |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
5bec9275 |
Cmd: []string{"touch", "/test"}, |
53a8229c |
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
if err := container.Run(); err != nil {
t.Fatal(err)
}
r := httptest.NewRecorder() |
fd224ee5 |
if err = getContainersExport(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { |
53a8229c |
t.Fatal(err)
}
if r.Code != http.StatusOK {
t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
}
|
5bec9275 |
found := false
for tarReader := tar.NewReader(r.Body); ; {
h, err := tarReader.Next()
if err != nil {
if err == io.EOF {
break
}
t.Fatal(err)
}
if h.Name == "./test" {
found = true
break
}
}
if !found {
t.Fatalf("The created test file has not been found in the exported image") |
53a8229c |
} |
24816a8b |
}
|
310fec48 |
func TestGetContainersChanges(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime} |
24816a8b |
|
310fec48 |
builder := NewBuilder(runtime) |
24816a8b |
|
310fec48 |
// Create a container and remove a file
container, err := builder.Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
310fec48 |
Cmd: []string{"/bin/rm", "/etc/passwd"},
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container) |
24816a8b |
|
310fec48 |
if err := container.Run(); err != nil {
t.Fatal(err)
}
|
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := getContainersChanges(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { |
310fec48 |
t.Fatal(err)
}
changes := []Change{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), &changes); err != nil { |
310fec48 |
t.Fatal(err)
}
// Check the changelog
success := false
for _, elem := range changes {
if elem.Path == "/etc/passwd" && elem.Kind == 2 {
success = true
}
}
if !success {
t.Fatalf("/etc/passwd as been removed but is not present in the diff")
}
} |
24816a8b |
|
483c9425 |
func TestGetContainersByName(t *testing.T) { |
53a8229c |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
5bec9275 |
Cmd: []string{"echo", "test"}, |
53a8229c |
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
|
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := getContainersByName(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { |
53a8229c |
t.Fatal(err)
} |
5bec9275 |
outContainer := &Container{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), outContainer); err != nil { |
53a8229c |
t.Fatal(err)
} |
fd224ee5 |
if outContainer.ID != container.ID {
t.Fatalf("Wrong containers retrieved. Expected %s, recieved %s", container.ID, outContainer.ID) |
5bec9275 |
} |
24816a8b |
}
func TestPostCommit(t *testing.T) { |
53a8229c |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
5bec9275 |
Cmd: []string{"touch", "/test"}, |
53a8229c |
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
if err := container.Run(); err != nil {
t.Fatal(err)
}
|
fd224ee5 |
req, err := http.NewRequest("POST", "/commit?repo=testrepo&testtag=tag&container="+container.ID, bytes.NewReader([]byte{})) |
53a8229c |
if err != nil {
t.Fatal(err)
}
|
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := postCommit(srv, APIVERSION, r, req, nil); err != nil { |
53a8229c |
t.Fatal(err)
}
if r.Code != http.StatusCreated {
t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
} |
5bec9275 |
|
fd224ee5 |
apiID := &APIID{}
if err := json.Unmarshal(r.Body.Bytes(), apiID); err != nil { |
5bec9275 |
t.Fatal(err)
} |
fd224ee5 |
if _, err := runtime.graph.Get(apiID.ID); err != nil { |
5bec9275 |
t.Fatalf("The image has not been commited")
} |
24816a8b |
}
func TestPostImagesCreate(t *testing.T) { |
5bec9275 |
// FIXME: Use the staging in order to perform tests
// runtime, err := newTestRuntime()
// if err != nil {
// t.Fatal(err)
// }
// defer nuke(runtime)
// srv := &Server{runtime: runtime}
// stdin, stdinPipe := io.Pipe()
// stdout, stdoutPipe := io.Pipe()
// c1 := make(chan struct{})
// go func() {
// defer close(c1)
// r := &hijackTester{
// ResponseRecorder: httptest.NewRecorder(),
// in: stdin,
// out: stdoutPipe,
// }
// req, err := http.NewRequest("POST", "/images/create?fromImage="+unitTestImageName, bytes.NewReader([]byte{}))
// if err != nil {
// t.Fatal(err)
// }
// body, err := postImagesCreate(srv, r, req, nil)
// if err != nil {
// t.Fatal(err)
// }
// if body != nil {
// t.Fatalf("No body expected, received: %s\n", body)
// }
// }()
// // Acknowledge hijack
// setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
// stdout.Read([]byte{})
// stdout.Read(make([]byte, 4096))
// })
// setTimeout(t, "Waiting for imagesCreate output", 5*time.Second, func() {
// reader := bufio.NewReader(stdout)
// line, err := reader.ReadString('\n')
// if err != nil {
// t.Fatal(err)
// }
// if !strings.HasPrefix(line, "Pulling repository d from") {
// t.Fatalf("Expected Pulling repository docker-ut from..., found %s", line)
// }
// })
// // Close pipes (client disconnects)
// if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
// t.Fatal(err)
// }
// // Wait for imagesCreate to finish, the client disconnected, therefore, Create finished his job
// setTimeout(t, "Waiting for imagesCreate timed out", 10*time.Second, func() {
// <-c1
// }) |
24816a8b |
}
|
3703a654 |
func TestPostImagesInsert(t *testing.T) {
// runtime, err := newTestRuntime()
// if err != nil {
// t.Fatal(err)
// }
// defer nuke(runtime)
// srv := &Server{runtime: runtime}
// stdin, stdinPipe := io.Pipe()
// stdout, stdoutPipe := io.Pipe()
// // Attach to it
// c1 := make(chan struct{})
// go func() {
// defer close(c1)
// r := &hijackTester{
// ResponseRecorder: httptest.NewRecorder(),
// in: stdin,
// out: stdoutPipe,
// }
// req, err := http.NewRequest("POST", "/images/"+unitTestImageName+"/insert?path=%2Ftest&url=https%3A%2F%2Fraw.github.com%2Fdotcloud%2Fdocker%2Fmaster%2FREADME.md", bytes.NewReader([]byte{}))
// if err != nil {
// t.Fatal(err)
// }
// if err := postContainersCreate(srv, r, req, nil); err != nil {
// t.Fatal(err)
// }
// }()
// // Acknowledge hijack
// setTimeout(t, "hijack acknowledge timed out", 5*time.Second, func() {
// stdout.Read([]byte{})
// stdout.Read(make([]byte, 4096))
// })
// id := ""
// setTimeout(t, "Waiting for imagesInsert output", 10*time.Second, func() {
// for {
// reader := bufio.NewReader(stdout)
// id, err = reader.ReadString('\n')
// if err != nil {
// t.Fatal(err)
// }
// }
// })
// // Close pipes (client disconnects)
// if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
// t.Fatal(err)
// }
// // Wait for attach to finish, the client disconnected, therefore, Attach finished his job
// setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() {
// <-c1
// })
// img, err := srv.runtime.repositories.LookupImage(id)
// if err != nil {
// t.Fatalf("New image %s expected but not found", id)
// }
// layer, err := img.layer()
// if err != nil {
// t.Fatal(err)
// }
// if _, err := os.Stat(path.Join(layer, "test")); err != nil {
// t.Fatalf("The test file has not been found")
// }
|
fd224ee5 |
// if err := srv.runtime.graph.Delete(img.ID); err != nil { |
3703a654 |
// t.Fatal(err)
// }
} |
24816a8b |
func TestPostImagesPush(t *testing.T) { |
5bec9275 |
//FIXME: Use staging in order to perform tests
// runtime, err := newTestRuntime()
// if err != nil {
// t.Fatal(err)
// }
// defer nuke(runtime)
// srv := &Server{runtime: runtime}
// stdin, stdinPipe := io.Pipe()
// stdout, stdoutPipe := io.Pipe()
// c1 := make(chan struct{})
// go func() {
// r := &hijackTester{
// ResponseRecorder: httptest.NewRecorder(),
// in: stdin,
// out: stdoutPipe,
// }
// req, err := http.NewRequest("POST", "/images/docker-ut/push", bytes.NewReader([]byte{}))
// if err != nil {
// t.Fatal(err)
// }
// body, err := postImagesPush(srv, r, req, map[string]string{"name": "docker-ut"})
// close(c1)
// if err != nil {
// t.Fatal(err)
// }
// if body != nil {
// t.Fatalf("No body expected, received: %s\n", body)
// }
// }()
// // Acknowledge hijack
// setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
// stdout.Read([]byte{})
// stdout.Read(make([]byte, 4096))
// })
// setTimeout(t, "Waiting for imagesCreate output", 5*time.Second, func() {
// reader := bufio.NewReader(stdout)
// line, err := reader.ReadString('\n')
// if err != nil {
// t.Fatal(err)
// }
// if !strings.HasPrefix(line, "Processing checksum") {
// t.Fatalf("Processing checksum..., found %s", line)
// }
// })
// // Close pipes (client disconnects)
// if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
// t.Fatal(err)
// }
// // Wait for imagesPush to finish, the client disconnected, therefore, Push finished his job
// setTimeout(t, "Waiting for imagesPush timed out", 10*time.Second, func() {
// <-c1
// }) |
24816a8b |
}
func TestPostImagesTag(t *testing.T) { |
5bec9275 |
// FIXME: Use staging in order to perform tests
// runtime, err := newTestRuntime()
// if err != nil {
// t.Fatal(err)
// }
// defer nuke(runtime)
// srv := &Server{runtime: runtime}
// r := httptest.NewRecorder()
// req, err := http.NewRequest("POST", "/images/docker-ut/tag?repo=testrepo&tag=testtag", bytes.NewReader([]byte{}))
// if err != nil {
// t.Fatal(err)
// }
// body, err := postImagesTag(srv, r, req, map[string]string{"name": "docker-ut"})
// if err != nil {
// t.Fatal(err)
// }
// if body != nil {
// t.Fatalf("No body expected, received: %s\n", body)
// }
// if r.Code != http.StatusCreated {
// t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
// } |
24816a8b |
}
|
2a303dab |
func TestPostContainersCreate(t *testing.T) { |
3115c5a2 |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
b2b59ddb |
|
3115c5a2 |
srv := &Server{runtime: runtime} |
b2b59ddb |
|
fd224ee5 |
configJSON, err := json.Marshal(&Config{
Image: GetTestImage(runtime).ID, |
2a303dab |
Memory: 33554432,
Cmd: []string{"touch", "/test"},
}) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
b2b59ddb |
|
fd224ee5 |
req, err := http.NewRequest("POST", "/containers/create", bytes.NewReader(configJSON)) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
b2b59ddb |
|
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := postContainersCreate(srv, APIVERSION, r, req, nil); err != nil { |
3115c5a2 |
t.Fatal(err)
} |
2a303dab |
if r.Code != http.StatusCreated {
t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
} |
b2b59ddb |
|
fd224ee5 |
apiRun := &APIRun{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), apiRun); err != nil { |
3115c5a2 |
t.Fatal(err)
} |
b2b59ddb |
|
fd224ee5 |
container := srv.runtime.Get(apiRun.ID) |
2a303dab |
if container == nil {
t.Fatalf("Container not created") |
3115c5a2 |
}
|
2a303dab |
if err := container.Run(); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(path.Join(container.rwPath(), "test")); err != nil {
if os.IsNotExist(err) { |
2e69e172 |
utils.Debugf("Err: %s", err) |
2a303dab |
t.Fatalf("The test file has not been created")
}
t.Fatal(err) |
3115c5a2 |
}
}
|
24816a8b |
func TestPostContainersKill(t *testing.T) { |
2a303dab |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
3115c5a2 |
|
2a303dab |
srv := &Server{runtime: runtime} |
3115c5a2 |
|
24816a8b |
container, err := NewBuilder(runtime).Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
24816a8b |
Cmd: []string{"/bin/cat"},
OpenStdin: true,
},
) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
2a303dab |
defer runtime.Destroy(container) |
3115c5a2 |
|
24816a8b |
if err := container.Start(); err != nil { |
3115c5a2 |
t.Fatal(err)
}
|
24816a8b |
// Give some time to the process to start
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running {
t.Errorf("Container should be running") |
2a303dab |
} |
24816a8b |
r := httptest.NewRecorder() |
fd224ee5 |
if err := postContainersKill(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { |
3115c5a2 |
t.Fatal(err)
} |
24816a8b |
if r.Code != http.StatusNoContent {
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
}
if container.State.Running {
t.Fatalf("The container hasn't been killed") |
3115c5a2 |
}
}
|
24816a8b |
func TestPostContainersRestart(t *testing.T) { |
2a303dab |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
3115c5a2 |
|
2a303dab |
srv := &Server{runtime: runtime} |
3115c5a2 |
|
2a303dab |
container, err := NewBuilder(runtime).Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
2a303dab |
Cmd: []string{"/bin/cat"},
OpenStdin: true,
},
) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
2a303dab |
defer runtime.Destroy(container)
|
24816a8b |
if err := container.Start(); err != nil {
t.Fatal(err)
}
// Give some time to the process to start
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running {
t.Errorf("Container should be running")
}
|
fd224ee5 |
req, err := http.NewRequest("POST", "/containers/"+container.ID+"/restart?t=1", bytes.NewReader([]byte{})) |
24816a8b |
if err != nil {
t.Fatal(err)
} |
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := postContainersRestart(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { |
3115c5a2 |
t.Fatal(err)
}
if r.Code != http.StatusNoContent {
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
} |
2a303dab |
|
24816a8b |
// Give some time to the process to restart |
2a303dab |
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running { |
24816a8b |
t.Fatalf("Container should be running") |
2a303dab |
}
if err := container.Kill(); err != nil {
t.Fatal(err)
} |
3115c5a2 |
}
|
24816a8b |
func TestPostContainersStart(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
3115c5a2 |
|
24816a8b |
srv := &Server{runtime: runtime} |
3115c5a2 |
|
24816a8b |
container, err := NewBuilder(runtime).Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
24816a8b |
Cmd: []string{"/bin/cat"},
OpenStdin: true,
},
) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
24816a8b |
defer runtime.Destroy(container) |
3115c5a2 |
|
24816a8b |
r := httptest.NewRecorder() |
fd224ee5 |
if err := postContainersStart(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { |
3115c5a2 |
t.Fatal(err)
}
if r.Code != http.StatusNoContent {
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
} |
24816a8b |
// Give some time to the process to start
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running {
t.Errorf("Container should be running")
}
|
b9944683 |
r = httptest.NewRecorder() |
fd224ee5 |
if err = postContainersStart(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err == nil { |
24816a8b |
t.Fatalf("A running containter should be able to be started")
}
if err := container.Kill(); err != nil {
t.Fatal(err)
} |
3115c5a2 |
}
|
2a303dab |
func TestPostContainersStop(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
3115c5a2 |
|
2a303dab |
srv := &Server{runtime: runtime} |
3115c5a2 |
|
2a303dab |
container, err := NewBuilder(runtime).Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
2a303dab |
Cmd: []string{"/bin/cat"},
OpenStdin: true,
},
) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
2a303dab |
defer runtime.Destroy(container) |
3115c5a2 |
|
2a303dab |
if err := container.Start(); err != nil { |
3115c5a2 |
t.Fatal(err)
}
|
2a303dab |
// Give some time to the process to start
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running {
t.Errorf("Container should be running")
}
// Note: as it is a POST request, it requires a body. |
fd224ee5 |
req, err := http.NewRequest("POST", "/containers/"+container.ID+"/stop?t=1", bytes.NewReader([]byte{})) |
2a303dab |
if err != nil {
t.Fatal(err)
} |
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := postContainersStop(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { |
2a303dab |
t.Fatal(err)
} |
3115c5a2 |
if r.Code != http.StatusNoContent {
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
} |
2a303dab |
if container.State.Running {
t.Fatalf("The container hasn't been stopped")
} |
3115c5a2 |
}
|
24816a8b |
func TestPostContainersWait(t *testing.T) {
runtime, err := newTestRuntime() |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
24816a8b |
defer nuke(runtime) |
3115c5a2 |
|
24816a8b |
srv := &Server{runtime: runtime} |
3115c5a2 |
|
24816a8b |
container, err := NewBuilder(runtime).Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
24816a8b |
Cmd: []string{"/bin/sleep", "1"},
OpenStdin: true,
},
) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
24816a8b |
defer runtime.Destroy(container) |
3115c5a2 |
|
24816a8b |
if err := container.Start(); err != nil { |
3115c5a2 |
t.Fatal(err)
}
|
24816a8b |
setTimeout(t, "Wait timed out", 3*time.Second, func() { |
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := postContainersWait(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { |
24816a8b |
t.Fatal(err)
} |
fd224ee5 |
apiWait := &APIWait{} |
b9944683 |
if err := json.Unmarshal(r.Body.Bytes(), apiWait); err != nil { |
24816a8b |
t.Fatal(err)
}
if apiWait.StatusCode != 0 {
t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.StatusCode)
}
}) |
3115c5a2 |
|
24816a8b |
if container.State.Running {
t.Fatalf("The container should be stopped after wait") |
3115c5a2 |
}
}
|
24816a8b |
func TestPostContainersAttach(t *testing.T) { |
15ae314c |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(
&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
15ae314c |
Cmd: []string{"/bin/cat"},
OpenStdin: true,
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
// Start the process
if err := container.Start(); err != nil {
t.Fatal(err)
}
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
// Attach to it
c1 := make(chan struct{})
go func() { |
b9944683 |
defer close(c1) |
15ae314c |
r := &hijackTester{
ResponseRecorder: httptest.NewRecorder(),
in: stdin,
out: stdoutPipe,
}
|
fd224ee5 |
req, err := http.NewRequest("POST", "/containers/"+container.ID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{})) |
15ae314c |
if err != nil {
t.Fatal(err)
}
|
fd224ee5 |
if err := postContainersAttach(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { |
15ae314c |
t.Fatal(err)
}
}()
// Acknowledge hijack
setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
stdout.Read([]byte{})
stdout.Read(make([]byte, 4096))
})
setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 15); err != nil {
t.Fatal(err)
}
})
// Close pipes (client disconnects)
if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
t.Fatal(err)
}
// Wait for attach to finish, the client disconnected, therefore, Attach finished his job
setTimeout(t, "Waiting for CmdAttach timed out", 2*time.Second, func() {
<-c1
})
// We closed stdin, expect /bin/cat to still be running
// Wait a little bit to make sure container.monitor() did his thing
err = container.WaitTimeout(500 * time.Millisecond)
if err == nil || !container.State.Running {
t.Fatalf("/bin/cat is not running after closing stdin")
}
// Try to avoid the timeoout in destroy. Best effort, don't check error
cStdin, _ := container.StdinPipe()
cStdin.Close()
container.Wait() |
24816a8b |
}
|
5bec9275 |
// FIXME: Test deleting running container |
2a303dab |
// FIXME: Test deleting container with volume
// FIXME: Test deleting volume in use by other container
func TestDeleteContainers(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime) |
3115c5a2 |
|
2a303dab |
srv := &Server{runtime: runtime} |
3115c5a2 |
|
2a303dab |
container, err := NewBuilder(runtime).Create(&Config{ |
fd224ee5 |
Image: GetTestImage(runtime).ID, |
2a303dab |
Cmd: []string{"touch", "/test"},
}) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
2a303dab |
defer runtime.Destroy(container)
if err := container.Run(); err != nil {
t.Fatal(err)
}
|
fd224ee5 |
req, err := http.NewRequest("DELETE", "/containers/"+container.ID, nil) |
3115c5a2 |
if err != nil {
t.Fatal(err)
} |
b9944683 |
r := httptest.NewRecorder() |
fd224ee5 |
if err := deleteContainers(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { |
2a303dab |
t.Fatal(err)
} |
3115c5a2 |
if r.Code != http.StatusNoContent {
t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
} |
2a303dab |
|
fd224ee5 |
if c := runtime.Get(container.ID); c != nil { |
2a303dab |
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")
} |
3115c5a2 |
}
|
0a28628c |
func TestOptionsRoute(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime, enableCors: true}
r := httptest.NewRecorder()
router, err := createRouter(srv, false)
if err != nil {
t.Fatal(err)
}
req, err := http.NewRequest("OPTIONS", "/", nil)
if err != nil {
t.Fatal(err)
}
router.ServeHTTP(r, req) |
ac599d65 |
if r.Code != http.StatusOK { |
0a28628c |
t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
}
}
|
6d5bdff3 |
func TestGetEnabledCors(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime, enableCors: true}
r := httptest.NewRecorder()
|
0a28628c |
router, err := createRouter(srv, false)
if err != nil { |
6d5bdff3 |
t.Fatal(err)
}
|
0a28628c |
req, err := http.NewRequest("GET", "/version", nil)
if err != nil {
t.Fatal(err)
}
router.ServeHTTP(r, req) |
ac599d65 |
if r.Code != http.StatusOK { |
0a28628c |
t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
}
|
6d5bdff3 |
allowOrigin := r.Header().Get("Access-Control-Allow-Origin")
allowHeaders := r.Header().Get("Access-Control-Allow-Headers") |
0a28628c |
allowMethods := r.Header().Get("Access-Control-Allow-Methods") |
6d5bdff3 |
if allowOrigin != "*" {
t.Errorf("Expected header Access-Control-Allow-Origin to be \"*\", %s found.", allowOrigin)
}
if allowHeaders != "Origin, X-Requested-With, Content-Type, Accept" {
t.Errorf("Expected header Access-Control-Allow-Headers to be \"Origin, X-Requested-With, Content-Type, Accept\", %s found.", allowHeaders)
} |
0a28628c |
if allowMethods != "GET, POST, DELETE, PUT, OPTIONS" {
t.Errorf("Expected hearder Access-Control-Allow-Methods to be \"GET, POST, DELETE, PUT, OPTIONS\", %s found.", allowMethods)
} |
6d5bdff3 |
}
|
24816a8b |
func TestDeleteImages(t *testing.T) { |
c80448c4 |
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
srv := &Server{runtime: runtime}
if err := srv.runtime.repositories.Set("test", "test", unitTestImageName, true); err != nil {
t.Fatal(err)
}
images, err := srv.Images(false, "")
if err != nil {
t.Fatal(err)
}
if len(images) != 2 {
t.Errorf("Excepted 2 images, %d found", len(images))
}
|
67b20f2c |
req, err := http.NewRequest("DELETE", "/images/test:test", nil)
if err != nil {
t.Fatal(err)
}
|
c80448c4 |
r := httptest.NewRecorder() |
66d9a733 |
if err := deleteImages(srv, APIVERSION, r, req, map[string]string{"name": "test:test"}); err != nil { |
c80448c4 |
t.Fatal(err)
} |
9060b5c2 |
if r.Code != http.StatusOK {
t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code) |
c80448c4 |
}
|
66d9a733 |
var outs []APIRmi |
9060b5c2 |
if err := json.Unmarshal(r.Body.Bytes(), &outs); err != nil {
t.Fatal(err)
}
if len(outs) != 1 {
t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs))
} |
c80448c4 |
images, err = srv.Images(false, "")
if err != nil {
t.Fatal(err)
}
if len(images) != 1 {
t.Errorf("Excepted 1 image, %d found", 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")
} */ |
15ae314c |
}
// Mocked types for tests
type NopConn struct {
io.ReadCloser
io.Writer
}
func (c *NopConn) LocalAddr() net.Addr { return nil }
func (c *NopConn) RemoteAddr() net.Addr { return nil }
func (c *NopConn) SetDeadline(t time.Time) error { return nil }
func (c *NopConn) SetReadDeadline(t time.Time) error { return nil }
func (c *NopConn) SetWriteDeadline(t time.Time) error { return nil }
type hijackTester struct {
*httptest.ResponseRecorder
in io.ReadCloser
out io.Writer
}
func (t *hijackTester) Hijack() (net.Conn, *bufio.ReadWriter, error) {
bufrw := bufio.NewReadWriter(bufio.NewReader(t.in), bufio.NewWriter(t.out))
conn := &NopConn{
ReadCloser: t.in,
Writer: t.out,
}
return conn, bufrw, nil |
3115c5a2 |
} |