mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
7a7357dae1
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>
341 lines
8.5 KiB
Go
341 lines
8.5 KiB
Go
package graphtest
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"math/rand"
|
|
"os"
|
|
"sort"
|
|
|
|
"github.com/containerd/continuity/driver"
|
|
"github.com/docker/docker/daemon/graphdriver"
|
|
"github.com/docker/docker/pkg/archive"
|
|
"github.com/docker/docker/pkg/stringid"
|
|
)
|
|
|
|
func randomContent(size int, seed int64) []byte {
|
|
s := rand.NewSource(seed)
|
|
content := make([]byte, size)
|
|
|
|
for i := 0; i < len(content); i += 7 {
|
|
val := s.Int63()
|
|
for j := 0; i+j < len(content) && j < 7; j++ {
|
|
content[i+j] = byte(val)
|
|
val >>= 8
|
|
}
|
|
}
|
|
|
|
return content
|
|
}
|
|
|
|
func addFiles(drv graphdriver.Driver, layer string, seed int64) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
if err := driver.WriteFile(root, root.Join(root.Path(), "file-a"), randomContent(64, seed), 0755); err != nil {
|
|
return err
|
|
}
|
|
if err := root.MkdirAll(root.Join(root.Path(), "dir-b"), 0755); err != nil {
|
|
return err
|
|
}
|
|
if err := driver.WriteFile(root, root.Join(root.Path(), "dir-b", "file-b"), randomContent(128, seed+1), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
return driver.WriteFile(root, root.Join(root.Path(), "file-c"), randomContent(128*128, seed+2), 0755)
|
|
}
|
|
|
|
func checkFile(drv graphdriver.Driver, layer, filename string, content []byte) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
fileContent, err := driver.ReadFile(root, root.Join(root.Path(), filename))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !bytes.Equal(fileContent, content) {
|
|
return fmt.Errorf("mismatched file content %v, expecting %v", fileContent, content)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func addFile(drv graphdriver.Driver, layer, filename string, content []byte) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
return driver.WriteFile(root, root.Join(root.Path(), filename), content, 0755)
|
|
}
|
|
|
|
func addDirectory(drv graphdriver.Driver, layer, dir string) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
return root.MkdirAll(root.Join(root.Path(), dir), 0755)
|
|
}
|
|
|
|
func removeAll(drv graphdriver.Driver, layer string, names ...string) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
for _, filename := range names {
|
|
if err := root.RemoveAll(root.Join(root.Path(), filename)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func checkFileRemoved(drv graphdriver.Driver, layer, filename string) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
if _, err := root.Stat(root.Join(root.Path(), filename)); err == nil {
|
|
return fmt.Errorf("file still exists: %s", root.Join(root.Path(), filename))
|
|
} else if !os.IsNotExist(err) {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func addManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
for i := 0; i < count; i += 100 {
|
|
dir := root.Join(root.Path(), fmt.Sprintf("directory-%d", i))
|
|
if err := root.MkdirAll(dir, 0755); err != nil {
|
|
return err
|
|
}
|
|
for j := 0; i+j < count && j < 100; j++ {
|
|
file := root.Join(dir, fmt.Sprintf("file-%d", i+j))
|
|
if err := driver.WriteFile(root, file, randomContent(64, seed+int64(i+j)), 0755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func changeManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) ([]archive.Change, error) {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
changes := []archive.Change{}
|
|
for i := 0; i < count; i += 100 {
|
|
archiveRoot := fmt.Sprintf("/directory-%d", i)
|
|
if err := root.MkdirAll(root.Join(root.Path(), archiveRoot), 0755); err != nil {
|
|
return nil, err
|
|
}
|
|
for j := 0; i+j < count && j < 100; j++ {
|
|
if j == 0 {
|
|
changes = append(changes, archive.Change{
|
|
Path: archiveRoot,
|
|
Kind: archive.ChangeModify,
|
|
})
|
|
}
|
|
var change archive.Change
|
|
switch j % 3 {
|
|
// Update file
|
|
case 0:
|
|
change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
|
|
change.Kind = archive.ChangeModify
|
|
if err := driver.WriteFile(root, root.Join(root.Path(), change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
|
|
return nil, err
|
|
}
|
|
// Add file
|
|
case 1:
|
|
change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d-%d", seed, i+j))
|
|
change.Kind = archive.ChangeAdd
|
|
if err := driver.WriteFile(root, root.Join(root.Path(), change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
|
|
return nil, err
|
|
}
|
|
// Remove file
|
|
case 2:
|
|
change.Path = root.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
|
|
change.Kind = archive.ChangeDelete
|
|
if err := root.Remove(root.Join(root.Path(), change.Path)); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
changes = append(changes, change)
|
|
}
|
|
}
|
|
|
|
return changes, nil
|
|
}
|
|
|
|
func checkManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
for i := 0; i < count; i += 100 {
|
|
dir := root.Join(root.Path(), fmt.Sprintf("directory-%d", i))
|
|
for j := 0; i+j < count && j < 100; j++ {
|
|
file := root.Join(dir, fmt.Sprintf("file-%d", i+j))
|
|
fileContent, err := driver.ReadFile(root, file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
content := randomContent(64, seed+int64(i+j))
|
|
|
|
if !bytes.Equal(fileContent, content) {
|
|
return fmt.Errorf("mismatched file content %v, expecting %v", fileContent, content)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type changeList []archive.Change
|
|
|
|
func (c changeList) Less(i, j int) bool {
|
|
if c[i].Path == c[j].Path {
|
|
return c[i].Kind < c[j].Kind
|
|
}
|
|
return c[i].Path < c[j].Path
|
|
}
|
|
func (c changeList) Len() int { return len(c) }
|
|
func (c changeList) Swap(i, j int) { c[j], c[i] = c[i], c[j] }
|
|
|
|
func checkChanges(expected, actual []archive.Change) error {
|
|
if len(expected) != len(actual) {
|
|
return fmt.Errorf("unexpected number of changes, expected %d, got %d", len(expected), len(actual))
|
|
}
|
|
sort.Sort(changeList(expected))
|
|
sort.Sort(changeList(actual))
|
|
|
|
for i := range expected {
|
|
if expected[i] != actual[i] {
|
|
return fmt.Errorf("unexpected change, expecting %v, got %v", expected[i], actual[i])
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func addLayerFiles(drv graphdriver.Driver, layer, parent string, i int) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
if err := driver.WriteFile(root, root.Join(root.Path(), "top-id"), []byte(layer), 0755); err != nil {
|
|
return err
|
|
}
|
|
layerDir := root.Join(root.Path(), fmt.Sprintf("layer-%d", i))
|
|
if err := root.MkdirAll(layerDir, 0755); err != nil {
|
|
return err
|
|
}
|
|
if err := driver.WriteFile(root, root.Join(layerDir, "layer-id"), []byte(layer), 0755); err != nil {
|
|
return err
|
|
}
|
|
if err := driver.WriteFile(root, root.Join(layerDir, "parent-id"), []byte(parent), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func addManyLayers(drv graphdriver.Driver, baseLayer string, count int) (string, error) {
|
|
lastLayer := baseLayer
|
|
for i := 1; i <= count; i++ {
|
|
nextLayer := stringid.GenerateRandomID()
|
|
if err := drv.Create(nextLayer, lastLayer, nil); err != nil {
|
|
return "", err
|
|
}
|
|
if err := addLayerFiles(drv, nextLayer, lastLayer, i); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
lastLayer = nextLayer
|
|
|
|
}
|
|
return lastLayer, nil
|
|
}
|
|
|
|
func checkManyLayers(drv graphdriver.Driver, layer string, count int) error {
|
|
root, err := drv.Get(layer, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer drv.Put(layer)
|
|
|
|
layerIDBytes, err := driver.ReadFile(root, root.Join(root.Path(), "top-id"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !bytes.Equal(layerIDBytes, []byte(layer)) {
|
|
return fmt.Errorf("mismatched file content %v, expecting %v", layerIDBytes, []byte(layer))
|
|
}
|
|
|
|
for i := count; i > 0; i-- {
|
|
layerDir := root.Join(root.Path(), fmt.Sprintf("layer-%d", i))
|
|
|
|
thisLayerIDBytes, err := driver.ReadFile(root, root.Join(layerDir, "layer-id"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !bytes.Equal(thisLayerIDBytes, layerIDBytes) {
|
|
return fmt.Errorf("mismatched file content %v, expecting %v", thisLayerIDBytes, layerIDBytes)
|
|
}
|
|
layerIDBytes, err = driver.ReadFile(root, root.Join(layerDir, "parent-id"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// readDir reads a directory just like driver.ReadDir()
|
|
// then hides specific files (currently "lost+found")
|
|
// so the tests don't "see" it
|
|
func readDir(r driver.Driver, dir string) ([]os.FileInfo, error) {
|
|
a, err := driver.ReadDir(r, dir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
b := a[:0]
|
|
for _, x := range a {
|
|
if x.Name() != "lost+found" { // ext4 always have this dir
|
|
b = append(b, x)
|
|
}
|
|
}
|
|
|
|
return b, nil
|
|
}
|