github.com/anuvu/storage@v1.12.13/drivers/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/containers/storage/drivers"
    13  	"github.com/containers/storage/pkg/archive"
    14  	"github.com/containers/storage/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, graphdriver.MountOpts{})
    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, graphdriver.MountOpts{})
    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, graphdriver.MountOpts{})
    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, graphdriver.MountOpts{})
    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, graphdriver.MountOpts{})
    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, graphdriver.MountOpts{})
   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, graphdriver.MountOpts{})
   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, graphdriver.MountOpts{})
   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  				var originalFileInfo, updatedFileInfo os.FileInfo
   170  				change.Path = path.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
   171  				change.Kind = archive.ChangeModify
   172  				if originalFileInfo, err = os.Stat(path.Join(root, change.Path)); err != nil {
   173  					return nil, err
   174  				}
   175  				for updatedFileInfo == nil || updatedFileInfo.ModTime().Equal(originalFileInfo.ModTime()) {
   176  					if err := ioutil.WriteFile(path.Join(root, change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
   177  						return nil, err
   178  					}
   179  					if updatedFileInfo, err = os.Stat(path.Join(root, change.Path)); err != nil {
   180  						return nil, err
   181  					}
   182  				}
   183  			// Add file
   184  			case 1:
   185  				change.Path = path.Join(archiveRoot, fmt.Sprintf("file-%d-%d", seed, i+j))
   186  				change.Kind = archive.ChangeAdd
   187  				if err := ioutil.WriteFile(path.Join(root, change.Path), randomContent(64, seed+int64(i+j)), 0755); err != nil {
   188  					return nil, err
   189  				}
   190  			// Remove file
   191  			case 2:
   192  				change.Path = path.Join(archiveRoot, fmt.Sprintf("file-%d", i+j))
   193  				change.Kind = archive.ChangeDelete
   194  				if err := os.Remove(path.Join(root, change.Path)); err != nil {
   195  					return nil, err
   196  				}
   197  			}
   198  			changes = append(changes, change)
   199  		}
   200  	}
   201  
   202  	return changes, nil
   203  }
   204  
   205  func checkManyFiles(drv graphdriver.Driver, layer string, count int, seed int64) error {
   206  	root, err := drv.Get(layer, graphdriver.MountOpts{})
   207  	if err != nil {
   208  		return err
   209  	}
   210  	defer drv.Put(layer)
   211  
   212  	for i := 0; i < count; i += 100 {
   213  		dir := path.Join(root, fmt.Sprintf("directory-%d", i))
   214  		for j := 0; i+j < count && j < 100; j++ {
   215  			file := path.Join(dir, fmt.Sprintf("file-%d", i+j))
   216  			fileContent, err := ioutil.ReadFile(file)
   217  			if err != nil {
   218  				return err
   219  			}
   220  
   221  			content := randomContent(64, seed+int64(i+j))
   222  
   223  			if bytes.Compare(fileContent, content) != 0 {
   224  				return fmt.Errorf("mismatched file content %v, expecting %v", fileContent, content)
   225  			}
   226  		}
   227  	}
   228  
   229  	return nil
   230  }
   231  
   232  type changeList []archive.Change
   233  
   234  func (c changeList) Less(i, j int) bool {
   235  	if c[i].Path == c[j].Path {
   236  		return c[i].Kind < c[j].Kind
   237  	}
   238  	return c[i].Path < c[j].Path
   239  }
   240  func (c changeList) Len() int      { return len(c) }
   241  func (c changeList) Swap(i, j int) { c[j], c[i] = c[i], c[j] }
   242  
   243  func checkChanges(expected, actual []archive.Change) error {
   244  	if len(expected) != len(actual) {
   245  		return fmt.Errorf("unexpected number of changes, expected %d, got %d", len(expected), len(actual))
   246  	}
   247  	sort.Sort(changeList(expected))
   248  	sort.Sort(changeList(actual))
   249  
   250  	for i := range expected {
   251  		if expected[i] != actual[i] {
   252  			return fmt.Errorf("unexpected change, expecting %v, got %v", expected[i], actual[i])
   253  		}
   254  	}
   255  
   256  	return nil
   257  }
   258  
   259  func addLayerFiles(drv graphdriver.Driver, layer, parent string, i int) error {
   260  	root, err := drv.Get(layer, graphdriver.MountOpts{})
   261  	if err != nil {
   262  		return err
   263  	}
   264  	defer drv.Put(layer)
   265  
   266  	if err := ioutil.WriteFile(path.Join(root, "top-id"), []byte(layer), 0755); err != nil {
   267  		return err
   268  	}
   269  	layerDir := path.Join(root, fmt.Sprintf("layer-%d", i))
   270  	if err := os.MkdirAll(layerDir, 0755); err != nil {
   271  		return err
   272  	}
   273  	if err := ioutil.WriteFile(path.Join(layerDir, "layer-id"), []byte(layer), 0755); err != nil {
   274  		return err
   275  	}
   276  	if err := ioutil.WriteFile(path.Join(layerDir, "parent-id"), []byte(parent), 0755); err != nil {
   277  		return err
   278  	}
   279  
   280  	return nil
   281  }
   282  
   283  func addManyLayers(drv graphdriver.Driver, baseLayer string, count int) (string, error) {
   284  	lastLayer := baseLayer
   285  	for i := 1; i <= count; i++ {
   286  		nextLayer := stringid.GenerateRandomID()
   287  		if err := drv.Create(nextLayer, lastLayer, nil); err != nil {
   288  			return "", err
   289  		}
   290  		if err := addLayerFiles(drv, nextLayer, lastLayer, i); err != nil {
   291  			return "", err
   292  		}
   293  
   294  		lastLayer = nextLayer
   295  
   296  	}
   297  	return lastLayer, nil
   298  }
   299  
   300  func checkManyLayers(drv graphdriver.Driver, layer string, count int) error {
   301  	root, err := drv.Get(layer, graphdriver.MountOpts{})
   302  	if err != nil {
   303  		return err
   304  	}
   305  	defer drv.Put(layer)
   306  
   307  	layerIDBytes, err := ioutil.ReadFile(path.Join(root, "top-id"))
   308  	if err != nil {
   309  		return err
   310  	}
   311  
   312  	if bytes.Compare(layerIDBytes, []byte(layer)) != 0 {
   313  		return fmt.Errorf("mismatched file content %v, expecting %v", layerIDBytes, []byte(layer))
   314  	}
   315  
   316  	for i := count; i > 0; i-- {
   317  		layerDir := path.Join(root, fmt.Sprintf("layer-%d", i))
   318  
   319  		thisLayerIDBytes, err := ioutil.ReadFile(path.Join(layerDir, "layer-id"))
   320  		if err != nil {
   321  			return err
   322  		}
   323  		if bytes.Compare(thisLayerIDBytes, layerIDBytes) != 0 {
   324  			return fmt.Errorf("mismatched file content %v, expecting %v", thisLayerIDBytes, layerIDBytes)
   325  		}
   326  		layerIDBytes, err = ioutil.ReadFile(path.Join(layerDir, "parent-id"))
   327  		if err != nil {
   328  			return err
   329  		}
   330  	}
   331  	return nil
   332  }
   333  
   334  // readDir reads a directory just like ioutil.ReadDir()
   335  // then hides specific files (currently "lost+found")
   336  // so the tests don't "see" it
   337  func readDir(dir string) ([]os.FileInfo, error) {
   338  	a, err := ioutil.ReadDir(dir)
   339  	if err != nil {
   340  		return nil, err
   341  	}
   342  
   343  	b := a[:0]
   344  	for _, x := range a {
   345  		if x.Name() != "lost+found" { // ext4 always have this dir
   346  			b = append(b, x)
   347  		}
   348  	}
   349  
   350  	return b, nil
   351  }