graph_test.go
ef711962
 package docker
33f6a0aa
 
 import (
3eff6239
 	"archive/tar"
 	"bytes"
13d9e26e
 	"errors"
e7077320
 	"github.com/dotcloud/docker/utils"
3eff6239
 	"io"
33f6a0aa
 	"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))
 	}
 }
 
13d9e26e
 // 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{
fd224ee5
 		ID:      GenerateID(),
13d9e26e
 		Comment: "testing",
 		Created: time.Now(),
 	}
074a5661
 	go graph.Register(badArchive, false, image)
13d9e26e
 	time.Sleep(200 * time.Millisecond)
 	w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling)
fd224ee5
 	if _, err := graph.Get(image.ID); err == nil {
13d9e26e
 		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)
 	}
074a5661
 	if err := graph.Register(goodArchive, false, image); err != nil {
13d9e26e
 		t.Fatal(err)
 	}
 }
 
33f6a0aa
 // FIXME: Do more extensive tests (ex: create multiple, delete, recreate;
 //       create multiple, check the amount of images and paths, etc..)
ef711962
 func TestGraphCreate(t *testing.T) {
33f6a0aa
 	graph := tempGraph(t)
 	defer os.RemoveAll(graph.Root)
3eff6239
 	archive, err := fakeTar()
33f6a0aa
 	if err != nil {
 		t.Fatal(err)
 	}
724e2d6b
 	image, err := graph.Create(archive, nil, "Testing", "", nil)
33f6a0aa
 	if err != nil {
 		t.Fatal(err)
 	}
fd224ee5
 	if err := ValidateID(image.ID); err != nil {
33f6a0aa
 		t.Fatal(err)
 	}
 	if image.Comment != "Testing" {
 		t.Fatalf("Wrong comment: should be '%s', not '%s'", "Testing", image.Comment)
 	}
8bfbdd7a
 	if image.DockerVersion != VERSION {
 		t.Fatalf("Wrong docker_version: should be '%s', not '%s'", VERSION, image.DockerVersion)
 	}
33f6a0aa
 	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)
3eff6239
 	archive, err := fakeTar()
33f6a0aa
 	if err != nil {
 		t.Fatal(err)
 	}
 	image := &Image{
fd224ee5
 		ID:      GenerateID(),
33f6a0aa
 		Comment: "testing",
 		Created: time.Now(),
 	}
074a5661
 	err = graph.Register(archive, false, image)
33f6a0aa
 	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)
 	}
fd224ee5
 	if resultImg, err := graph.Get(image.ID); err != nil {
33f6a0aa
 		t.Fatal(err)
 	} else {
fd224ee5
 		if resultImg.ID != image.ID {
 			t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.ID, resultImg.ID)
33f6a0aa
 		}
 		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)
3eff6239
 	archive, err := fakeTar()
33f6a0aa
 	if err != nil {
 		t.Fatal(err)
 	}
724e2d6b
 	image, err := graph.Create(archive, nil, "Testing", "", nil)
33f6a0aa
 	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)
 		}
 	}()
 }
 
7ad2e022
 // 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)
fd224ee5
 	if err := graph.Delete(utils.TruncateID(img.ID)); err != nil {
7ad2e022
 		t.Fatal(err)
 	}
 	assertNImages(graph, t, 0)
 }
 
 func createTestImage(graph *Graph, t *testing.T) *Image {
 	archive, err := fakeTar()
 	if err != nil {
 		t.Fatal(err)
 	}
724e2d6b
 	img, err := graph.Create(archive, nil, "Test image", "", nil)
7ad2e022
 	if err != nil {
 		t.Fatal(err)
 	}
 	return img
 }
 
3c1db4ca
 func TestDelete(t *testing.T) {
 	graph := tempGraph(t)
 	defer os.RemoveAll(graph.Root)
3eff6239
 	archive, err := fakeTar()
3c1db4ca
 	if err != nil {
 		t.Fatal(err)
 	}
 	assertNImages(graph, t, 0)
724e2d6b
 	img, err := graph.Create(archive, nil, "Bla bla", "", nil)
3c1db4ca
 	if err != nil {
 		t.Fatal(err)
 	}
 	assertNImages(graph, t, 1)
fd224ee5
 	if err := graph.Delete(img.ID); err != nil {
3c1db4ca
 		t.Fatal(err)
 	}
 	assertNImages(graph, t, 0)
 
42ce6889
 	archive, err = fakeTar()
 	if err != nil {
 		t.Fatal(err)
 	}
3c1db4ca
 	// Test 2 create (same name) / 1 delete
724e2d6b
 	img1, err := graph.Create(archive, nil, "Testing", "", nil)
3c1db4ca
 	if err != nil {
 		t.Fatal(err)
 	}
42ce6889
 	archive, err = fakeTar()
 	if err != nil {
 		t.Fatal(err)
 	}
724e2d6b
 	if _, err = graph.Create(archive, nil, "Testing", "", nil); err != nil {
3c1db4ca
 		t.Fatal(err)
 	}
 	assertNImages(graph, t, 2)
fd224ee5
 	if err := graph.Delete(img1.ID); err != nil {
3c1db4ca
 		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)
 
42ce6889
 	archive, err = fakeTar()
 	if err != nil {
 		t.Fatal(err)
 	}
baea0a98
 	// Test delete twice (pull -> rm -> pull -> rm)
074a5661
 	if err := graph.Register(archive, false, img1); err != nil {
baea0a98
 		t.Fatal(err)
 	}
fd224ee5
 	if err := graph.Delete(img1.ID); err != nil {
baea0a98
 		t.Fatal(err)
 	}
 	assertNImages(graph, t, 1)
3c1db4ca
 }
 
 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)
 	}
 }
 
33f6a0aa
 /*
  * HELPER FUNCTIONS
  */
 
 func tempGraph(t *testing.T) *Graph {
 	tmp, err := ioutil.TempDir("", "docker-graph-")
 	if err != nil {
 		t.Fatal(err)
 	}
ef711962
 	graph, err := NewGraph(tmp)
33f6a0aa
 	if err != nil {
 		t.Fatal(err)
 	}
 	return graph
 }
 
 func testArchive(t *testing.T) Archive {
3eff6239
 	archive, err := fakeTar()
33f6a0aa
 	if err != nil {
 		t.Fatal(err)
 	}
 	return archive
 }
3eff6239
 
 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
 }