2015-04-20 17:07:21 -04:00
|
|
|
package graph
|
2013-11-14 18:17:31 -05:00
|
|
|
|
|
|
|
import (
|
2013-11-25 23:04:57 -05:00
|
|
|
"errors"
|
|
|
|
"io"
|
2013-11-14 18:17:31 -05:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"testing"
|
2013-11-25 23:04:57 -05:00
|
|
|
"time"
|
2015-03-24 07:25:26 -04:00
|
|
|
|
|
|
|
"github.com/docker/docker/daemon/graphdriver"
|
2015-11-09 13:32:46 -05:00
|
|
|
"github.com/docker/docker/dockerversion"
|
2015-03-24 07:25:26 -04:00
|
|
|
"github.com/docker/docker/image"
|
|
|
|
"github.com/docker/docker/pkg/stringid"
|
2013-11-14 18:17:31 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestMount(t *testing.T) {
|
2013-11-19 18:24:14 -05:00
|
|
|
graph, driver := tempGraph(t)
|
2015-06-05 18:31:10 -04:00
|
|
|
defer os.RemoveAll(graph.root)
|
2013-11-19 18:24:14 -05:00
|
|
|
defer driver.Cleanup()
|
|
|
|
|
2013-11-14 18:17:31 -05:00
|
|
|
archive, err := fakeTar()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-03-07 21:04:38 -05:00
|
|
|
image, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
|
2013-11-14 18:17:31 -05:00
|
|
|
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)
|
|
|
|
}
|
2013-11-19 18:24:14 -05:00
|
|
|
|
2014-04-17 19:47:27 -04:00
|
|
|
if _, err := driver.Get(image.ID, ""); err != nil {
|
2013-11-14 18:17:31 -05:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-04-20 17:07:21 -04:00
|
|
|
|
2013-11-14 18:17:31 -05:00
|
|
|
}
|
|
|
|
|
2013-11-25 23:04:57 -05:00
|
|
|
func TestInit(t *testing.T) {
|
|
|
|
graph, _ := tempGraph(t)
|
|
|
|
defer nukeGraph(graph)
|
|
|
|
// Root should exist
|
2015-06-05 18:31:10 -04:00
|
|
|
if _, err := os.Stat(graph.root); err != nil {
|
2013-11-25 23:04:57 -05:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// Map() should be empty
|
2015-06-19 11:01:39 -04:00
|
|
|
l := graph.Map()
|
|
|
|
if len(l) != 0 {
|
2013-11-25 23:04:57 -05:00
|
|
|
t.Fatalf("len(Map()) 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 nukeGraph(graph)
|
|
|
|
badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data
|
2015-07-20 13:57:15 -04:00
|
|
|
image := &image.Image{
|
2015-07-28 20:19:17 -04:00
|
|
|
ID: stringid.GenerateNonCryptoID(),
|
2013-11-25 23:04:57 -05:00
|
|
|
Comment: "testing",
|
|
|
|
Created: time.Now(),
|
|
|
|
}
|
|
|
|
w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling)
|
2015-08-26 17:58:56 -04:00
|
|
|
graph.Register(v1Descriptor{image}, badArchive)
|
2013-11-25 23:04:57 -05:00
|
|
|
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)
|
|
|
|
}
|
2015-08-26 17:58:56 -04:00
|
|
|
if err := graph.Register(v1Descriptor{image}, goodArchive); err != nil {
|
2013-11-25 23:04:57 -05:00
|
|
|
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 nukeGraph(graph)
|
|
|
|
archive, err := fakeTar()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-03-07 21:04:38 -05:00
|
|
|
img, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
|
2013-11-25 23:04:57 -05:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-03-29 17:17:23 -04:00
|
|
|
if err := image.ValidateID(img.ID); err != nil {
|
2013-11-25 23:04:57 -05:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-03-07 20:36:47 -05:00
|
|
|
if img.Comment != "Testing" {
|
|
|
|
t.Fatalf("Wrong comment: should be '%s', not '%s'", "Testing", img.Comment)
|
2013-11-25 23:04:57 -05:00
|
|
|
}
|
2015-11-09 13:32:46 -05:00
|
|
|
if img.DockerVersion != dockerversion.Version {
|
|
|
|
t.Fatalf("Wrong docker_version: should be '%s', not '%s'", dockerversion.Version, img.DockerVersion)
|
2013-11-25 23:04:57 -05:00
|
|
|
}
|
2015-06-19 11:01:39 -04:00
|
|
|
images := graph.Map()
|
|
|
|
if l := len(images); l != 1 {
|
2013-11-25 23:04:57 -05:00
|
|
|
t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
|
|
|
|
}
|
2014-03-07 20:36:47 -05:00
|
|
|
if images[img.ID] == nil {
|
|
|
|
t.Fatalf("Could not find image with id %s", img.ID)
|
2013-11-25 23:04:57 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRegister(t *testing.T) {
|
|
|
|
graph, _ := tempGraph(t)
|
|
|
|
defer nukeGraph(graph)
|
|
|
|
archive, err := fakeTar()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-20 13:57:15 -04:00
|
|
|
image := &image.Image{
|
2015-07-28 20:19:17 -04:00
|
|
|
ID: stringid.GenerateNonCryptoID(),
|
2013-11-25 23:04:57 -05:00
|
|
|
Comment: "testing",
|
|
|
|
Created: time.Now(),
|
|
|
|
}
|
2015-08-26 17:58:56 -04:00
|
|
|
err = graph.Register(v1Descriptor{image}, archive)
|
2013-11-25 23:04:57 -05:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-06-19 11:01:39 -04:00
|
|
|
images := graph.Map()
|
|
|
|
if l := len(images); l != 1 {
|
2013-11-25 23:04:57 -05:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that an image can be deleted by its shorthand prefix
|
|
|
|
func TestDeletePrefix(t *testing.T) {
|
|
|
|
graph, _ := tempGraph(t)
|
|
|
|
defer nukeGraph(graph)
|
|
|
|
img := createTestImage(graph, t)
|
2015-03-24 07:25:26 -04:00
|
|
|
if err := graph.Delete(stringid.TruncateID(img.ID)); err != nil {
|
2013-11-25 23:04:57 -05:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
assertNImages(graph, t, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDelete(t *testing.T) {
|
|
|
|
graph, _ := tempGraph(t)
|
|
|
|
defer nukeGraph(graph)
|
|
|
|
archive, err := fakeTar()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
assertNImages(graph, t, 0)
|
2014-03-07 21:04:38 -05:00
|
|
|
img, err := graph.Create(archive, "", "", "Bla bla", "", nil, nil)
|
2013-11-25 23:04:57 -05:00
|
|
|
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
|
2014-03-07 21:04:38 -05:00
|
|
|
img1, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
|
2013-11-25 23:04:57 -05:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
archive, err = fakeTar()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-03-07 21:04:38 -05:00
|
|
|
if _, err = graph.Create(archive, "", "", "Testing", "", nil, nil); err != nil {
|
2013-11-25 23:04:57 -05:00
|
|
|
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()
|
2013-11-19 18:24:14 -05:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2013-11-25 23:04:57 -05:00
|
|
|
// Test delete twice (pull -> rm -> pull -> rm)
|
2015-08-26 17:58:56 -04:00
|
|
|
if err := graph.Register(v1Descriptor{img1}, archive); err != nil {
|
2013-11-25 23:04:57 -05:00
|
|
|
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 nukeGraph(graph)
|
2015-07-20 13:57:15 -04:00
|
|
|
parentImage := &image.Image{
|
2015-07-28 20:19:17 -04:00
|
|
|
ID: stringid.GenerateNonCryptoID(),
|
2013-11-25 23:04:57 -05:00
|
|
|
Comment: "parent",
|
|
|
|
Created: time.Now(),
|
|
|
|
Parent: "",
|
|
|
|
}
|
2015-07-20 13:57:15 -04:00
|
|
|
childImage1 := &image.Image{
|
2015-07-28 20:19:17 -04:00
|
|
|
ID: stringid.GenerateNonCryptoID(),
|
2013-11-25 23:04:57 -05:00
|
|
|
Comment: "child1",
|
|
|
|
Created: time.Now(),
|
|
|
|
Parent: parentImage.ID,
|
|
|
|
}
|
2015-07-20 13:57:15 -04:00
|
|
|
childImage2 := &image.Image{
|
2015-07-28 20:19:17 -04:00
|
|
|
ID: stringid.GenerateNonCryptoID(),
|
2013-11-25 23:04:57 -05:00
|
|
|
Comment: "child2",
|
|
|
|
Created: time.Now(),
|
|
|
|
Parent: parentImage.ID,
|
|
|
|
}
|
2015-08-26 17:58:56 -04:00
|
|
|
|
|
|
|
err := graph.Register(v1Descriptor{parentImage}, archive1)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
err = graph.Register(v1Descriptor{childImage1}, archive2)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
err = graph.Register(v1Descriptor{childImage2}, archive3)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2013-11-25 23:04:57 -05:00
|
|
|
|
2015-06-19 11:01:39 -04:00
|
|
|
byParent := graph.ByParent()
|
2013-11-25 23:04:57 -05:00
|
|
|
numChildren := len(byParent[parentImage.ID])
|
|
|
|
if numChildren != 2 {
|
|
|
|
t.Fatalf("Expected 2 children, found %d", numChildren)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-20 13:57:15 -04:00
|
|
|
func createTestImage(graph *Graph, t *testing.T) *image.Image {
|
2015-04-20 17:07:21 -04:00
|
|
|
archive, err := fakeTar()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
img, err := graph.Create(archive, "", "", "Test image", "", nil, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return img
|
|
|
|
}
|
2013-11-25 23:04:57 -05:00
|
|
|
|
2015-04-20 17:07:21 -04:00
|
|
|
func assertNImages(graph *Graph, t *testing.T, n int) {
|
2015-06-19 11:01:39 -04:00
|
|
|
images := graph.Map()
|
|
|
|
if actualN := len(images); actualN != n {
|
2013-11-25 23:04:57 -05:00
|
|
|
t.Fatalf("Expected %d images, found %d", n, actualN)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-20 17:07:21 -04:00
|
|
|
func tempGraph(t *testing.T) (*Graph, graphdriver.Driver) {
|
2013-11-29 19:20:59 -05:00
|
|
|
tmp, err := ioutil.TempDir("", "docker-graph-")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-10-08 11:51:41 -04:00
|
|
|
driver, err := graphdriver.New(tmp, nil, nil, nil)
|
2013-11-29 19:20:59 -05:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-10-08 11:51:41 -04:00
|
|
|
graph, err := NewGraph(tmp, driver, nil, nil)
|
2013-11-29 19:20:59 -05:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
return graph, driver
|
2013-11-25 23:04:57 -05:00
|
|
|
}
|
|
|
|
|
2015-04-20 17:07:21 -04:00
|
|
|
func nukeGraph(graph *Graph) {
|
2015-06-05 18:31:10 -04:00
|
|
|
graph.driver.Cleanup()
|
|
|
|
os.RemoveAll(graph.root)
|
2013-11-25 23:04:57 -05:00
|
|
|
}
|