github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/daemon/graphdriver/graphtest/testutil.go (about)

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