gopkg.in/dotcloud/docker.v1@v1.13.1/daemon/graphdriver/graphtest/testutil.go (about)

     1  package graphtest
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/rand"
     8  	"os"
     9  	"path"
    10  	"sort"
    11  
    12  	"github.com/docker/docker/daemon/graphdriver"
    13  	"github.com/docker/docker/pkg/archive"
    14  	"github.com/docker/docker/pkg/stringid"
    15  )
    16  
    17  func randomContent(size int, seed int64) []byte {
    18  	s := rand.NewSource(seed)
    19  	content := make([]byte, size)
    20  
    21  	for i := 0; i < len(content); i += 7 {
    22  		val := s.Int63()
    23  		for j := 0; i+j < len(content) && j < 7; j++ {
    24  			content[i+j] = byte(val)
    25  			val >>= 8
    26  		}
    27  	}
    28  
    29  	return content
    30  }
    31  
    32  func addFiles(drv graphdriver.Driver, layer string, seed int64) error {
    33  	root, err := drv.Get(layer, "")
    34  	if err != nil {
    35  		return err
    36  	}
    37  	defer drv.Put(layer)
    38  
    39  	if err := ioutil.WriteFile(path.Join(root, "file-a"), randomContent(64, seed), 0755); err != nil {
    40  		return err
    41  	}
    42  	if err := os.MkdirAll(path.Join(root, "dir-b"), 0755); err != nil {
    43  		return err
    44  	}
    45  	if err := ioutil.WriteFile(path.Join(root, "dir-b", "file-b"), randomContent(128, seed+1), 0755); err != nil {
    46  		return err
    47  	}
    48  
    49  	return ioutil.WriteFile(path.Join(root, "file-c"), randomContent(128*128, seed+2), 0755)
    50  }
    51  
    52  func checkFile(drv graphdriver.Driver, layer, filename string, content []byte) error {
    53  	root, err := drv.Get(layer, "")
    54  	if err != nil {
    55  		return err
    56  	}
    57  	defer drv.Put(layer)
    58  
    59  	fileContent, err := ioutil.ReadFile(path.Join(root, filename))
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	if bytes.Compare(fileContent, content) != 0 {
    65  		return fmt.Errorf("mismatched file content %v, expecting %v", fileContent, content)
    66  	}
    67  
    68  	return nil
    69  }
    70  
    71  func addFile(drv graphdriver.Driver, layer, filename string, content []byte) error {
    72  	root, err := drv.Get(layer, "")
    73  	if err != nil {
    74  		return err
    75  	}
    76  	defer drv.Put(layer)
    77  
    78  	return ioutil.WriteFile(path.Join(root, filename), content, 0755)
    79  }
    80  
    81  func addDirectory(drv graphdriver.Driver, layer, dir string) error {
    82  	root, err := drv.Get(layer, "")
    83  	if err != nil {
    84  		return err
    85  	}
    86  	defer drv.Put(layer)
    87  
    88  	return os.MkdirAll(path.Join(root, dir), 0755)
    89  }
    90  
    91  func removeAll(drv graphdriver.Driver, layer string, names ...string) error {
    92  	root, err := drv.Get(layer, "")
    93  	if err != nil {
    94  		return err
    95  	}
    96  	defer drv.Put(layer)
    97  
    98  	for _, filename := range names {
    99  		if err := os.RemoveAll(path.Join(root, filename)); err != nil {
   100  			return err
   101  		}
   102  	}
   103  	return nil
   104  }
   105  
   106  func checkFileRemoved(drv graphdriver.Driver, layer, filename string) error {
   107  	root, err := drv.Get(layer, "")
   108  	if err != nil {
   109  		return err
   110  	}
   111  	defer drv.Put(layer)
   112  
   113  	if _, err := os.Stat(path.Join(root, filename)); err == nil {
   114  		return fmt.Errorf("file still exists: %s", path.Join(root, filename))
   115  	} else if !os.IsNotExist(err) {
   116  		return err
   117  	}
   118  
   119  	return nil
   120  }
   121  
   122  func addManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) error {
   123  	root, err := drv.Get(layer, "")
   124  	if err != nil {
   125  		return err
   126  	}
   127  	defer drv.Put(layer)
   128  
   129  	for i := 0; i < count; i += 100 {
   130  		dir := path.Join(root, fmt.Sprintf("directory-%d", i))
   131  		if err := os.MkdirAll(dir, 0755); err != nil {
   132  			return err
   133  		}
   134  		for j := 0; i+j < count && j < 100; j++ {
   135  			file := path.Join(dir, fmt.Sprintf("file-%d", i+j))
   136  			if err := ioutil.WriteFile(file, randomContent(64, seed+int64(i+j)), 0755); err != nil {
   137  				return err
   138  			}
   139  		}
   140  	}
   141  
   142  	return nil
   143  }
   144  
   145  func changeManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) ([]archive.Change, error) {
   146  	root, err := drv.Get(layer, "")
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	defer drv.Put(layer)
   151  
   152  	changes := []archive.Change{}
   153  	for i := 0; i < count; i += 100 {
   154  		archiveRoot := fmt.Sprintf("/directory-%d", i)
   155  		if err := os.MkdirAll(path.Join(root, archiveRoot), 0755); err != nil {
   156  			return nil, err
   157  		}
   158  		for j := 0; i+j < count && j < 100; j++ {
   159  			if j == 0 {
   160  				changes = append(changes, archive.Change{
   161  					Path: archiveRoot,
   162  					Kind: archive.ChangeModify,
   163  				})
   164  			}
   165  			var change archive.Change
   166  			switch j % 3 {
   167  			// Update file
   168  			case 0:
   169  				change.Path = path.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
   170  				change.Kind = archive.ChangeModify
   171  				if err := ioutil.WriteFile(path.Join(root, change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
   172  					return nil, err
   173  				}
   174  			// Add file
   175  			case 1:
   176  				change.Path = path.Join(archiveRoot, fmt.Sprintf("file-%d-%d", seed, i+j))
   177  				change.Kind = archive.ChangeAdd
   178  				if err := ioutil.WriteFile(path.Join(root, change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
   179  					return nil, err
   180  				}
   181  			// Remove file
   182  			case 2:
   183  				change.Path = path.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
   184  				change.Kind = archive.ChangeDelete
   185  				if err := os.Remove(path.Join(root, change.Path)); err != nil {
   186  					return nil, err
   187  				}
   188  			}
   189  			changes = append(changes, change)
   190  		}
   191  	}
   192  
   193  	return changes, nil
   194  }
   195  
   196  func checkManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) error {
   197  	root, err := drv.Get(layer, "")
   198  	if err != nil {
   199  		return err
   200  	}
   201  	defer drv.Put(layer)
   202  
   203  	for i := 0; i < count; i += 100 {
   204  		dir := path.Join(root, fmt.Sprintf("directory-%d", i))
   205  		for j := 0; i+j < count && j < 100; j++ {
   206  			file := path.Join(dir, fmt.Sprintf("file-%d", i+j))
   207  			fileContent, err := ioutil.ReadFile(file)
   208  			if err != nil {
   209  				return err
   210  			}
   211  
   212  			content := randomContent(64, seed+int64(i+j))
   213  
   214  			if bytes.Compare(fileContent, content) != 0 {
   215  				return fmt.Errorf("mismatched file content %v, expecting %v", fileContent, content)
   216  			}
   217  		}
   218  	}
   219  
   220  	return nil
   221  }
   222  
   223  type changeList []archive.Change
   224  
   225  func (c changeList) Less(i, j int) bool {
   226  	if c[i].Path == c[j].Path {
   227  		return c[i].Kind < c[j].Kind
   228  	}
   229  	return c[i].Path < c[j].Path
   230  }
   231  func (c changeList) Len() int      { return len(c) }
   232  func (c changeList) Swap(i, j int) { c[j], c[i] = c[i], c[j] }
   233  
   234  func checkChanges(expected, actual []archive.Change) error {
   235  	if len(expected) != len(actual) {
   236  		return fmt.Errorf("unexpected number of changes, expected %d, got %d", len(expected), len(actual))
   237  	}
   238  	sort.Sort(changeList(expected))
   239  	sort.Sort(changeList(actual))
   240  
   241  	for i := range expected {
   242  		if expected[i] != actual[i] {
   243  			return fmt.Errorf("unexpected change, expecting %v, got %v", expected[i], actual[i])
   244  		}
   245  	}
   246  
   247  	return nil
   248  }
   249  
   250  func addLayerFiles(drv graphdriver.Driver, layer, parent string, i int) error {
   251  	root, err := drv.Get(layer, "")
   252  	if err != nil {
   253  		return err
   254  	}
   255  	defer drv.Put(layer)
   256  
   257  	if err := ioutil.WriteFile(path.Join(root, "top-id"), []byte(layer), 0755); err != nil {
   258  		return err
   259  	}
   260  	layerDir := path.Join(root, fmt.Sprintf("layer-%d", i))
   261  	if err := os.MkdirAll(layerDir, 0755); err != nil {
   262  		return err
   263  	}
   264  	if err := ioutil.WriteFile(path.Join(layerDir, "layer-id"), []byte(layer), 0755); err != nil {
   265  		return err
   266  	}
   267  	if err := ioutil.WriteFile(path.Join(layerDir, "parent-id"), []byte(parent), 0755); err != nil {
   268  		return err
   269  	}
   270  
   271  	return nil
   272  }
   273  
   274  func addManyLayers(drv graphdriver.Driver, baseLayer string, count int) (string, error) {
   275  	lastLayer := baseLayer
   276  	for i := 1; i <= count; i++ {
   277  		nextLayer := stringid.GenerateRandomID()
   278  		if err := drv.Create(nextLayer, lastLayer, nil); err != nil {
   279  			return "", err
   280  		}
   281  		if err := addLayerFiles(drv, nextLayer, lastLayer, i); err != nil {
   282  			return "", err
   283  		}
   284  
   285  		lastLayer = nextLayer
   286  
   287  	}
   288  	return lastLayer, nil
   289  }
   290  
   291  func checkManyLayers(drv graphdriver.Driver, layer string, count int) error {
   292  	root, err := drv.Get(layer, "")
   293  	if err != nil {
   294  		return err
   295  	}
   296  	defer drv.Put(layer)
   297  
   298  	layerIDBytes, err := ioutil.ReadFile(path.Join(root, "top-id"))
   299  	if err != nil {
   300  		return err
   301  	}
   302  
   303  	if bytes.Compare(layerIDBytes, []byte(layer)) != 0 {
   304  		return fmt.Errorf("mismatched file content %v, expecting %v", layerIDBytes, []byte(layer))
   305  	}
   306  
   307  	for i := count; i > 0; i-- {
   308  		layerDir := path.Join(root, fmt.Sprintf("layer-%d", i))
   309  
   310  		thisLayerIDBytes, err := ioutil.ReadFile(path.Join(layerDir, "layer-id"))
   311  		if err != nil {
   312  			return err
   313  		}
   314  		if bytes.Compare(thisLayerIDBytes, layerIDBytes) != 0 {
   315  			return fmt.Errorf("mismatched file content %v, expecting %v", thisLayerIDBytes, layerIDBytes)
   316  		}
   317  		layerIDBytes, err = ioutil.ReadFile(path.Join(layerDir, "parent-id"))
   318  		if err != nil {
   319  			return err
   320  		}
   321  	}
   322  	return nil
   323  }
   324  
   325  // readDir reads a directory just like ioutil.ReadDir()
   326  // then hides specific files (currently "lost+found")
   327  // so the tests don't "see" it
   328  func readDir(dir string) ([]os.FileInfo, error) {
   329  	a, err := ioutil.ReadDir(dir)
   330  	if err != nil {
   331  		return nil, err
   332  	}
   333  
   334  	b := a[:0]
   335  	for _, x := range a {
   336  		if x.Name() != "lost+found" { // ext4 always have this dir
   337  			b = append(b, x)
   338  		}
   339  	}
   340  
   341  	return b, nil
   342  }