layer/mount_test.go
500e77ba
 package layer
 
 import (
 	"io/ioutil"
e17cb9b7
 	"runtime"
500e77ba
 	"sort"
 	"testing"
 
7a7357da
 	"github.com/containerd/continuity/driver"
500e77ba
 	"github.com/docker/docker/pkg/archive"
7a7357da
 	"github.com/docker/docker/pkg/containerfs"
500e77ba
 )
 
 func TestMountInit(t *testing.T) {
e17cb9b7
 	// TODO Windows: Figure out why this is failing
 	if runtime.GOOS == "windows" {
 		t.Skip("Failing on Windows")
 	}
50a498ea
 	ls, _, cleanup := newTestStore(t)
500e77ba
 	defer cleanup()
 
 	basefile := newTestFile("testfile.txt", []byte("base data!"), 0644)
 	initfile := newTestFile("testfile.txt", []byte("init data!"), 0777)
 
 	li := initWithFiles(basefile)
 	layer, err := createLayer(ls, "", li)
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	mountInit := func(root containerfs.ContainerFS) error {
500e77ba
 		return initfile.ApplyFile(root)
 	}
 
f7f3d342
 	rwLayerOpts := &CreateRWLayerOpts{
 		InitFunc: mountInit,
 	}
 	m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), rwLayerOpts)
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	pathFS, err := m.Mount("")
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	fi, err := pathFS.Stat(pathFS.Join(pathFS.Path(), "testfile.txt"))
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	f, err := pathFS.Open(pathFS.Join(pathFS.Path(), "testfile.txt"))
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
7a7357da
 	defer f.Close()
500e77ba
 
 	b, err := ioutil.ReadAll(f)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	if expected := "init data!"; string(b) != expected {
 		t.Fatalf("Unexpected test file contents %q, expected %q", string(b), expected)
 	}
 
 	if fi.Mode().Perm() != 0777 {
 		t.Fatalf("Unexpected filemode %o, expecting %o", fi.Mode().Perm(), 0777)
 	}
 }
 
 func TestMountSize(t *testing.T) {
e17cb9b7
 	// TODO Windows: Figure out why this is failing
 	if runtime.GOOS == "windows" {
 		t.Skip("Failing on Windows")
 	}
50a498ea
 	ls, _, cleanup := newTestStore(t)
500e77ba
 	defer cleanup()
 
 	content1 := []byte("Base contents")
 	content2 := []byte("Mutable contents")
 	contentInit := []byte("why am I excluded from the size ☹")
 
 	li := initWithFiles(newTestFile("file1", content1, 0644))
 	layer, err := createLayer(ls, "", li)
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	mountInit := func(root containerfs.ContainerFS) error {
500e77ba
 		return newTestFile("file-init", contentInit, 0777).ApplyFile(root)
 	}
f7f3d342
 	rwLayerOpts := &CreateRWLayerOpts{
 		InitFunc: mountInit,
 	}
500e77ba
 
f7f3d342
 	m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), rwLayerOpts)
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	pathFS, err := m.Mount("")
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "file2"), content2, 0755); err != nil {
500e77ba
 		t.Fatal(err)
 	}
 
 	mountSize, err := m.Size()
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	if expected := len(content2); int(mountSize) != expected {
 		t.Fatalf("Unexpected mount size %d, expected %d", int(mountSize), expected)
 	}
 }
 
 func TestMountChanges(t *testing.T) {
e17cb9b7
 	// TODO Windows: Figure out why this is failing
 	if runtime.GOOS == "windows" {
 		t.Skip("Failing on Windows")
 	}
50a498ea
 	ls, _, cleanup := newTestStore(t)
500e77ba
 	defer cleanup()
 
 	basefiles := []FileApplier{
 		newTestFile("testfile1.txt", []byte("base data!"), 0644),
 		newTestFile("testfile2.txt", []byte("base data!"), 0644),
 		newTestFile("testfile3.txt", []byte("base data!"), 0644),
 	}
 	initfile := newTestFile("testfile1.txt", []byte("init data!"), 0777)
 
 	li := initWithFiles(basefiles...)
 	layer, err := createLayer(ls, "", li)
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	mountInit := func(root containerfs.ContainerFS) error {
500e77ba
 		return initfile.ApplyFile(root)
 	}
f7f3d342
 	rwLayerOpts := &CreateRWLayerOpts{
 		InitFunc: mountInit,
 	}
500e77ba
 
f7f3d342
 	m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), rwLayerOpts)
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	pathFS, err := m.Mount("")
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
7a7357da
 	if err := pathFS.Lchmod(pathFS.Join(pathFS.Path(), "testfile1.txt"), 0755); err != nil {
500e77ba
 		t.Fatal(err)
 	}
 
7a7357da
 	if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "testfile1.txt"), []byte("mount data!"), 0755); err != nil {
500e77ba
 		t.Fatal(err)
 	}
 
7a7357da
 	if err := pathFS.Remove(pathFS.Join(pathFS.Path(), "testfile2.txt")); err != nil {
500e77ba
 		t.Fatal(err)
 	}
 
7a7357da
 	if err := pathFS.Lchmod(pathFS.Join(pathFS.Path(), "testfile3.txt"), 0755); err != nil {
500e77ba
 		t.Fatal(err)
 	}
 
7a7357da
 	if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "testfile4.txt"), []byte("mount data!"), 0644); err != nil {
500e77ba
 		t.Fatal(err)
 	}
 
d04fa49a
 	changes, err := m.Changes()
500e77ba
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	if expected := 4; len(changes) != expected {
 		t.Fatalf("Wrong number of changes %d, expected %d", len(changes), expected)
 	}
 
 	sortChanges(changes)
 
 	assertChange(t, changes[0], archive.Change{
 		Path: "/testfile1.txt",
 		Kind: archive.ChangeModify,
 	})
 	assertChange(t, changes[1], archive.Change{
 		Path: "/testfile2.txt",
 		Kind: archive.ChangeDelete,
 	})
 	assertChange(t, changes[2], archive.Change{
 		Path: "/testfile3.txt",
 		Kind: archive.ChangeModify,
 	})
 	assertChange(t, changes[3], archive.Change{
 		Path: "/testfile4.txt",
 		Kind: archive.ChangeAdd,
 	})
 }
 
 func assertChange(t *testing.T, actual, expected archive.Change) {
 	if actual.Path != expected.Path {
 		t.Fatalf("Unexpected change path %s, expected %s", actual.Path, expected.Path)
 	}
 	if actual.Kind != expected.Kind {
 		t.Fatalf("Unexpected change type %s, expected %s", actual.Kind, expected.Kind)
 	}
 }
 
 func sortChanges(changes []archive.Change) {
 	cs := &changeSorter{
 		changes: changes,
 	}
 	sort.Sort(cs)
 }
 
 type changeSorter struct {
 	changes []archive.Change
 }
 
 func (cs *changeSorter) Len() int {
 	return len(cs.changes)
 }
 
 func (cs *changeSorter) Swap(i, j int) {
 	cs.changes[i], cs.changes[j] = cs.changes[j], cs.changes[i]
 }
 
 func (cs *changeSorter) Less(i, j int) bool {
 	return cs.changes[i].Path < cs.changes[j].Path
 }