moby/layer/mount_test.go
Akash Gupta 7a7357dae1 LCOW: Implemented support for docker cp + build
This enables docker cp and ADD/COPY docker build support for LCOW.
Originally, the graphdriver.Get() interface returned a local path
to the container root filesystem. This does not work for LCOW, so
the Get() method now returns an interface that LCOW implements to
support copying to and from the container.

Signed-off-by: Akash Gupta <akagup@microsoft.com>
2017-09-14 12:07:52 -07:00

239 lines
5.5 KiB
Go

package layer
import (
"io/ioutil"
"runtime"
"sort"
"testing"
"github.com/containerd/continuity/driver"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/containerfs"
)
func TestMountInit(t *testing.T) {
// TODO Windows: Figure out why this is failing
if runtime.GOOS == "windows" {
t.Skip("Failing on Windows")
}
ls, _, cleanup := newTestStore(t)
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)
}
mountInit := func(root containerfs.ContainerFS) error {
return initfile.ApplyFile(root)
}
rwLayerOpts := &CreateRWLayerOpts{
InitFunc: mountInit,
}
m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), rwLayerOpts)
if err != nil {
t.Fatal(err)
}
pathFS, err := m.Mount("")
if err != nil {
t.Fatal(err)
}
fi, err := pathFS.Stat(pathFS.Join(pathFS.Path(), "testfile.txt"))
if err != nil {
t.Fatal(err)
}
f, err := pathFS.Open(pathFS.Join(pathFS.Path(), "testfile.txt"))
if err != nil {
t.Fatal(err)
}
defer f.Close()
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) {
// TODO Windows: Figure out why this is failing
if runtime.GOOS == "windows" {
t.Skip("Failing on Windows")
}
ls, _, cleanup := newTestStore(t)
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)
}
mountInit := func(root containerfs.ContainerFS) error {
return newTestFile("file-init", contentInit, 0777).ApplyFile(root)
}
rwLayerOpts := &CreateRWLayerOpts{
InitFunc: mountInit,
}
m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), rwLayerOpts)
if err != nil {
t.Fatal(err)
}
pathFS, err := m.Mount("")
if err != nil {
t.Fatal(err)
}
if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "file2"), content2, 0755); err != nil {
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) {
// TODO Windows: Figure out why this is failing
if runtime.GOOS == "windows" {
t.Skip("Failing on Windows")
}
ls, _, cleanup := newTestStore(t)
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)
}
mountInit := func(root containerfs.ContainerFS) error {
return initfile.ApplyFile(root)
}
rwLayerOpts := &CreateRWLayerOpts{
InitFunc: mountInit,
}
m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), rwLayerOpts)
if err != nil {
t.Fatal(err)
}
pathFS, err := m.Mount("")
if err != nil {
t.Fatal(err)
}
if err := pathFS.Lchmod(pathFS.Join(pathFS.Path(), "testfile1.txt"), 0755); err != nil {
t.Fatal(err)
}
if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "testfile1.txt"), []byte("mount data!"), 0755); err != nil {
t.Fatal(err)
}
if err := pathFS.Remove(pathFS.Join(pathFS.Path(), "testfile2.txt")); err != nil {
t.Fatal(err)
}
if err := pathFS.Lchmod(pathFS.Join(pathFS.Path(), "testfile3.txt"), 0755); err != nil {
t.Fatal(err)
}
if err := driver.WriteFile(pathFS, pathFS.Join(pathFS.Path(), "testfile4.txt"), []byte("mount data!"), 0644); err != nil {
t.Fatal(err)
}
changes, err := m.Changes()
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
}