123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- package docker
- import (
- "archive/tar"
- "bytes"
- "errors"
- "github.com/dotcloud/docker/utils"
- "io"
- "io/ioutil"
- "os"
- "path"
- "testing"
- "time"
- )
- func TestInit(t *testing.T) {
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- // Root should exist
- if _, err := os.Stat(graph.Root); err != nil {
- t.Fatal(err)
- }
- // All() should be empty
- if l, err := graph.All(); err != nil {
- t.Fatal(err)
- } else if len(l) != 0 {
- t.Fatalf("List() should return %d, not %d", 0, len(l))
- }
- }
- // Test that Register can be interrupted cleanly without side effects
- func TestInterruptedRegister(t *testing.T) {
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data
- image := &Image{
- ID: GenerateID(),
- Comment: "testing",
- Created: time.Now(),
- }
- go graph.Register(nil, badArchive, image)
- time.Sleep(200 * time.Millisecond)
- w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling)
- if _, err := graph.Get(image.ID); err == nil {
- t.Fatal("Image should not exist after Register is interrupted")
- }
- // Registering the same image again should succeed if the first register was interrupted
- goodArchive, err := fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- if err := graph.Register(nil, goodArchive, image); err != nil {
- t.Fatal(err)
- }
- }
- // FIXME: Do more extensive tests (ex: create multiple, delete, recreate;
- // create multiple, check the amount of images and paths, etc..)
- func TestGraphCreate(t *testing.T) {
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- archive, err := fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- image, err := graph.Create(archive, nil, "Testing", "", nil)
- if err != nil {
- t.Fatal(err)
- }
- if err := ValidateID(image.ID); err != nil {
- t.Fatal(err)
- }
- if image.Comment != "Testing" {
- t.Fatalf("Wrong comment: should be '%s', not '%s'", "Testing", image.Comment)
- }
- if image.DockerVersion != VERSION {
- t.Fatalf("Wrong docker_version: should be '%s', not '%s'", VERSION, image.DockerVersion)
- }
- if images, err := graph.All(); err != nil {
- t.Fatal(err)
- } else if l := len(images); l != 1 {
- t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
- }
- }
- func TestRegister(t *testing.T) {
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- archive, err := fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- image := &Image{
- ID: GenerateID(),
- Comment: "testing",
- Created: time.Now(),
- }
- err = graph.Register(nil, archive, image)
- if err != nil {
- t.Fatal(err)
- }
- if images, err := graph.All(); err != nil {
- t.Fatal(err)
- } else if l := len(images); l != 1 {
- t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
- }
- if resultImg, err := graph.Get(image.ID); err != nil {
- t.Fatal(err)
- } else {
- if resultImg.ID != image.ID {
- t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.ID, resultImg.ID)
- }
- if resultImg.Comment != image.Comment {
- t.Fatalf("Wrong image comment. Should be '%s', not '%s'", image.Comment, resultImg.Comment)
- }
- }
- }
- func TestMount(t *testing.T) {
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- archive, err := fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- image, err := graph.Create(archive, nil, "Testing", "", nil)
- if err != nil {
- t.Fatal(err)
- }
- tmp, err := ioutil.TempDir("", "docker-test-graph-mount-")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tmp)
- rootfs := path.Join(tmp, "rootfs")
- if err := os.MkdirAll(rootfs, 0700); err != nil {
- t.Fatal(err)
- }
- rw := path.Join(tmp, "rw")
- if err := os.MkdirAll(rw, 0700); err != nil {
- t.Fatal(err)
- }
- if err := image.Mount(rootfs, rw); err != nil {
- t.Fatal(err)
- }
- // FIXME: test for mount contents
- defer func() {
- if err := Unmount(rootfs); err != nil {
- t.Error(err)
- }
- }()
- }
- // Test that an image can be deleted by its shorthand prefix
- func TestDeletePrefix(t *testing.T) {
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- img := createTestImage(graph, t)
- if err := graph.Delete(utils.TruncateID(img.ID)); err != nil {
- t.Fatal(err)
- }
- assertNImages(graph, t, 0)
- }
- func createTestImage(graph *Graph, t *testing.T) *Image {
- archive, err := fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- img, err := graph.Create(archive, nil, "Test image", "", nil)
- if err != nil {
- t.Fatal(err)
- }
- return img
- }
- func TestDelete(t *testing.T) {
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- archive, err := fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- assertNImages(graph, t, 0)
- img, err := graph.Create(archive, nil, "Bla bla", "", nil)
- if err != nil {
- t.Fatal(err)
- }
- assertNImages(graph, t, 1)
- if err := graph.Delete(img.ID); err != nil {
- t.Fatal(err)
- }
- assertNImages(graph, t, 0)
- archive, err = fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- // Test 2 create (same name) / 1 delete
- img1, err := graph.Create(archive, nil, "Testing", "", nil)
- if err != nil {
- t.Fatal(err)
- }
- archive, err = fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- if _, err = graph.Create(archive, nil, "Testing", "", nil); err != nil {
- t.Fatal(err)
- }
- assertNImages(graph, t, 2)
- if err := graph.Delete(img1.ID); err != nil {
- t.Fatal(err)
- }
- assertNImages(graph, t, 1)
- // Test delete wrong name
- if err := graph.Delete("Not_foo"); err == nil {
- t.Fatalf("Deleting wrong ID should return an error")
- }
- assertNImages(graph, t, 1)
- archive, err = fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- // Test delete twice (pull -> rm -> pull -> rm)
- if err := graph.Register(nil, archive, img1); err != nil {
- t.Fatal(err)
- }
- if err := graph.Delete(img1.ID); err != nil {
- t.Fatal(err)
- }
- assertNImages(graph, t, 1)
- }
- func TestByParent(t *testing.T) {
- archive1, _ := fakeTar()
- archive2, _ := fakeTar()
- archive3, _ := fakeTar()
- graph := tempGraph(t)
- defer os.RemoveAll(graph.Root)
- parentImage := &Image{
- ID: GenerateID(),
- Comment: "parent",
- Created: time.Now(),
- Parent: "",
- }
- childImage1 := &Image{
- ID: GenerateID(),
- Comment: "child1",
- Created: time.Now(),
- Parent: parentImage.ID,
- }
- childImage2 := &Image{
- ID: GenerateID(),
- Comment: "child2",
- Created: time.Now(),
- Parent: parentImage.ID,
- }
- _ = graph.Register(nil, archive1, parentImage)
- _ = graph.Register(nil, archive2, childImage1)
- _ = graph.Register(nil, archive3, childImage2)
- byParent, err := graph.ByParent()
- if err != nil {
- t.Fatal(err)
- }
- numChildren := len(byParent[parentImage.ID])
- if numChildren != 2 {
- t.Fatalf("Expected 2 children, found %d", numChildren)
- }
- }
- func assertNImages(graph *Graph, t *testing.T, n int) {
- if images, err := graph.All(); err != nil {
- t.Fatal(err)
- } else if actualN := len(images); actualN != n {
- t.Fatalf("Expected %d images, found %d", n, actualN)
- }
- }
- /*
- * HELPER FUNCTIONS
- */
- func tempGraph(t *testing.T) *Graph {
- tmp, err := ioutil.TempDir("", "docker-graph-")
- if err != nil {
- t.Fatal(err)
- }
- graph, err := NewGraph(tmp)
- if err != nil {
- t.Fatal(err)
- }
- return graph
- }
- func testArchive(t *testing.T) Archive {
- archive, err := fakeTar()
- if err != nil {
- t.Fatal(err)
- }
- return archive
- }
- func fakeTar() (io.Reader, error) {
- content := []byte("Hello world!\n")
- buf := new(bytes.Buffer)
- tw := tar.NewWriter(buf)
- for _, name := range []string{"/etc/postgres/postgres.conf", "/etc/passwd", "/var/log/postgres/postgres.conf"} {
- hdr := new(tar.Header)
- hdr.Size = int64(len(content))
- hdr.Name = name
- if err := tw.WriteHeader(hdr); err != nil {
- return nil, err
- }
- tw.Write([]byte(content))
- }
- tw.Close()
- return buf, nil
- }
|