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

     1  // +build linux
     2  
     3  package aufs // import "github.com/docker/docker/daemon/graphdriver/aufs"
     4  
     5  import (
     6  	"crypto/sha256"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"path"
    12  	"path/filepath"
    13  	"sync"
    14  	"testing"
    15  
    16  	"github.com/docker/docker/daemon/graphdriver"
    17  	"github.com/docker/docker/pkg/archive"
    18  	"github.com/docker/docker/pkg/reexec"
    19  	"github.com/docker/docker/pkg/stringid"
    20  	"gotest.tools/v3/assert"
    21  	is "gotest.tools/v3/assert/cmp"
    22  )
    23  
    24  var (
    25  	tmpOuter = path.Join(os.TempDir(), "aufs-tests")
    26  	tmp      = path.Join(tmpOuter, "aufs")
    27  )
    28  
    29  func init() {
    30  	reexec.Init()
    31  }
    32  
    33  func testInit(dir string, t testing.TB) graphdriver.Driver {
    34  	d, err := Init(dir, nil, nil, nil)
    35  	if err != nil {
    36  		if err == graphdriver.ErrNotSupported {
    37  			t.Skip(err)
    38  		} else {
    39  			t.Fatal(err)
    40  		}
    41  	}
    42  	return d
    43  }
    44  
    45  func driverGet(d *Driver, id string, mntLabel string) (string, error) {
    46  	mnt, err := d.Get(id, mntLabel)
    47  	if err != nil {
    48  		return "", err
    49  	}
    50  	return mnt.Path(), nil
    51  }
    52  
    53  func newDriver(t testing.TB) *Driver {
    54  	if err := os.MkdirAll(tmp, 0755); err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	d := testInit(tmp, t)
    59  	return d.(*Driver)
    60  }
    61  
    62  func TestNewDriver(t *testing.T) {
    63  	if err := os.MkdirAll(tmp, 0755); err != nil {
    64  		t.Fatal(err)
    65  	}
    66  
    67  	d := testInit(tmp, t)
    68  	defer os.RemoveAll(tmp)
    69  	if d == nil {
    70  		t.Fatal("Driver should not be nil")
    71  	}
    72  }
    73  
    74  func TestAufsString(t *testing.T) {
    75  	d := newDriver(t)
    76  	defer os.RemoveAll(tmp)
    77  
    78  	if d.String() != "aufs" {
    79  		t.Fatalf("Expected aufs got %s", d.String())
    80  	}
    81  }
    82  
    83  func TestCreateDirStructure(t *testing.T) {
    84  	newDriver(t)
    85  	defer os.RemoveAll(tmp)
    86  
    87  	paths := []string{
    88  		"mnt",
    89  		"layers",
    90  		"diff",
    91  	}
    92  
    93  	for _, p := range paths {
    94  		if _, err := os.Stat(path.Join(tmp, p)); err != nil {
    95  			t.Fatal(err)
    96  		}
    97  	}
    98  }
    99  
   100  // We should be able to create two drivers with the same dir structure
   101  func TestNewDriverFromExistingDir(t *testing.T) {
   102  	if err := os.MkdirAll(tmp, 0755); err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	testInit(tmp, t)
   107  	testInit(tmp, t)
   108  	os.RemoveAll(tmp)
   109  }
   110  
   111  func TestCreateNewDir(t *testing.T) {
   112  	d := newDriver(t)
   113  	defer os.RemoveAll(tmp)
   114  
   115  	if err := d.Create("1", "", nil); err != nil {
   116  		t.Fatal(err)
   117  	}
   118  }
   119  
   120  func TestCreateNewDirStructure(t *testing.T) {
   121  	d := newDriver(t)
   122  	defer os.RemoveAll(tmp)
   123  
   124  	if err := d.Create("1", "", nil); err != nil {
   125  		t.Fatal(err)
   126  	}
   127  
   128  	paths := []string{
   129  		"mnt",
   130  		"diff",
   131  		"layers",
   132  	}
   133  
   134  	for _, p := range paths {
   135  		if _, err := os.Stat(path.Join(tmp, p, "1")); err != nil {
   136  			t.Fatal(err)
   137  		}
   138  	}
   139  }
   140  
   141  func TestRemoveImage(t *testing.T) {
   142  	d := newDriver(t)
   143  	defer os.RemoveAll(tmp)
   144  
   145  	if err := d.Create("1", "", nil); err != nil {
   146  		t.Fatal(err)
   147  	}
   148  
   149  	if err := d.Remove("1"); err != nil {
   150  		t.Fatal(err)
   151  	}
   152  
   153  	paths := []string{
   154  		"mnt",
   155  		"diff",
   156  		"layers",
   157  	}
   158  
   159  	for _, p := range paths {
   160  		if _, err := os.Stat(path.Join(tmp, p, "1")); err == nil {
   161  			t.Fatalf("Error should not be nil because dirs with id 1 should be deleted: %s", p)
   162  		}
   163  		if _, err := os.Stat(path.Join(tmp, p, "1-removing")); err == nil {
   164  			t.Fatalf("Error should not be nil because dirs with id 1-removing should be deleted: %s", p)
   165  		}
   166  	}
   167  }
   168  
   169  func TestGetWithoutParent(t *testing.T) {
   170  	d := newDriver(t)
   171  	defer os.RemoveAll(tmp)
   172  
   173  	if err := d.Create("1", "", nil); err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	diffPath, err := d.Get("1", "")
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  	expected := path.Join(tmp, "diff", "1")
   182  	if diffPath.Path() != expected {
   183  		t.Fatalf("Expected path %s got %s", expected, diffPath)
   184  	}
   185  }
   186  
   187  func TestCleanupWithNoDirs(t *testing.T) {
   188  	d := newDriver(t)
   189  	defer os.RemoveAll(tmp)
   190  
   191  	err := d.Cleanup()
   192  	assert.Check(t, err)
   193  }
   194  
   195  func TestCleanupWithDir(t *testing.T) {
   196  	d := newDriver(t)
   197  	defer os.RemoveAll(tmp)
   198  
   199  	if err := d.Create("1", "", nil); err != nil {
   200  		t.Fatal(err)
   201  	}
   202  
   203  	if err := d.Cleanup(); err != nil {
   204  		t.Fatal(err)
   205  	}
   206  }
   207  
   208  func TestMountedFalseResponse(t *testing.T) {
   209  	d := newDriver(t)
   210  	defer os.RemoveAll(tmp)
   211  
   212  	err := d.Create("1", "", nil)
   213  	assert.NilError(t, err)
   214  
   215  	response, err := d.mounted(d.getDiffPath("1"))
   216  	assert.NilError(t, err)
   217  	assert.Check(t, !response)
   218  }
   219  
   220  func TestMountedTrueResponse(t *testing.T) {
   221  	d := newDriver(t)
   222  	defer os.RemoveAll(tmp)
   223  	defer d.Cleanup()
   224  
   225  	err := d.Create("1", "", nil)
   226  	assert.NilError(t, err)
   227  	err = d.Create("2", "1", nil)
   228  	assert.NilError(t, err)
   229  
   230  	_, err = d.Get("2", "")
   231  	assert.NilError(t, err)
   232  
   233  	response, err := d.mounted(d.pathCache["2"])
   234  	assert.NilError(t, err)
   235  	assert.Check(t, response)
   236  }
   237  
   238  func TestMountWithParent(t *testing.T) {
   239  	d := newDriver(t)
   240  	defer os.RemoveAll(tmp)
   241  
   242  	if err := d.Create("1", "", nil); err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	if err := d.Create("2", "1", nil); err != nil {
   246  		t.Fatal(err)
   247  	}
   248  
   249  	defer func() {
   250  		if err := d.Cleanup(); err != nil {
   251  			t.Fatal(err)
   252  		}
   253  	}()
   254  
   255  	mntPath, err := d.Get("2", "")
   256  	if err != nil {
   257  		t.Fatal(err)
   258  	}
   259  	if mntPath == nil {
   260  		t.Fatal("mntPath should not be nil")
   261  	}
   262  
   263  	expected := path.Join(tmp, "mnt", "2")
   264  	if mntPath.Path() != expected {
   265  		t.Fatalf("Expected %s got %s", expected, mntPath.Path())
   266  	}
   267  }
   268  
   269  func TestRemoveMountedDir(t *testing.T) {
   270  	d := newDriver(t)
   271  	defer os.RemoveAll(tmp)
   272  
   273  	if err := d.Create("1", "", nil); err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	if err := d.Create("2", "1", nil); err != nil {
   277  		t.Fatal(err)
   278  	}
   279  
   280  	defer func() {
   281  		if err := d.Cleanup(); err != nil {
   282  			t.Fatal(err)
   283  		}
   284  	}()
   285  
   286  	mntPath, err := d.Get("2", "")
   287  	if err != nil {
   288  		t.Fatal(err)
   289  	}
   290  	if mntPath == nil {
   291  		t.Fatal("mntPath should not be nil")
   292  	}
   293  
   294  	mounted, err := d.mounted(d.pathCache["2"])
   295  	if err != nil {
   296  		t.Fatal(err)
   297  	}
   298  
   299  	if !mounted {
   300  		t.Fatal("Dir id 2 should be mounted")
   301  	}
   302  
   303  	if err := d.Remove("2"); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  }
   307  
   308  func TestCreateWithInvalidParent(t *testing.T) {
   309  	d := newDriver(t)
   310  	defer os.RemoveAll(tmp)
   311  
   312  	if err := d.Create("1", "docker", nil); err == nil {
   313  		t.Fatal("Error should not be nil with parent does not exist")
   314  	}
   315  }
   316  
   317  func TestGetDiff(t *testing.T) {
   318  	d := newDriver(t)
   319  	defer os.RemoveAll(tmp)
   320  
   321  	if err := d.CreateReadWrite("1", "", nil); err != nil {
   322  		t.Fatal(err)
   323  	}
   324  
   325  	diffPath, err := driverGet(d, "1", "")
   326  	if err != nil {
   327  		t.Fatal(err)
   328  	}
   329  
   330  	// Add a file to the diff path with a fixed size
   331  	size := int64(1024)
   332  
   333  	f, err := os.Create(path.Join(diffPath, "test_file"))
   334  	if err != nil {
   335  		t.Fatal(err)
   336  	}
   337  	if err := f.Truncate(size); err != nil {
   338  		t.Fatal(err)
   339  	}
   340  	f.Close()
   341  
   342  	a, err := d.Diff("1", "")
   343  	if err != nil {
   344  		t.Fatal(err)
   345  	}
   346  	if a == nil {
   347  		t.Fatal("Archive should not be nil")
   348  	}
   349  }
   350  
   351  func TestChanges(t *testing.T) {
   352  	d := newDriver(t)
   353  	defer os.RemoveAll(tmp)
   354  
   355  	if err := d.Create("1", "", nil); err != nil {
   356  		t.Fatal(err)
   357  	}
   358  
   359  	if err := d.CreateReadWrite("2", "1", nil); err != nil {
   360  		t.Fatal(err)
   361  	}
   362  
   363  	defer func() {
   364  		if err := d.Cleanup(); err != nil {
   365  			t.Fatal(err)
   366  		}
   367  	}()
   368  
   369  	mntPoint, err := driverGet(d, "2", "")
   370  	if err != nil {
   371  		t.Fatal(err)
   372  	}
   373  
   374  	// Create a file to save in the mountpoint
   375  	f, err := os.Create(path.Join(mntPoint, "test.txt"))
   376  	if err != nil {
   377  		t.Fatal(err)
   378  	}
   379  
   380  	if _, err := f.WriteString("testline"); err != nil {
   381  		t.Fatal(err)
   382  	}
   383  	if err := f.Close(); err != nil {
   384  		t.Fatal(err)
   385  	}
   386  
   387  	changes, err := d.Changes("2", "")
   388  	if err != nil {
   389  		t.Fatal(err)
   390  	}
   391  	if len(changes) != 1 {
   392  		t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
   393  	}
   394  	change := changes[0]
   395  
   396  	expectedPath := "/test.txt"
   397  	if change.Path != expectedPath {
   398  		t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
   399  	}
   400  
   401  	if change.Kind != archive.ChangeAdd {
   402  		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
   403  	}
   404  
   405  	if err := d.CreateReadWrite("3", "2", nil); err != nil {
   406  		t.Fatal(err)
   407  	}
   408  	mntPoint, err = driverGet(d, "3", "")
   409  	if err != nil {
   410  		t.Fatal(err)
   411  	}
   412  
   413  	// Create a file to save in the mountpoint
   414  	f, err = os.Create(path.Join(mntPoint, "test2.txt"))
   415  	if err != nil {
   416  		t.Fatal(err)
   417  	}
   418  
   419  	if _, err := f.WriteString("testline"); err != nil {
   420  		t.Fatal(err)
   421  	}
   422  	if err := f.Close(); err != nil {
   423  		t.Fatal(err)
   424  	}
   425  
   426  	changes, err = d.Changes("3", "2")
   427  	if err != nil {
   428  		t.Fatal(err)
   429  	}
   430  
   431  	if len(changes) != 1 {
   432  		t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
   433  	}
   434  	change = changes[0]
   435  
   436  	expectedPath = "/test2.txt"
   437  	if change.Path != expectedPath {
   438  		t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
   439  	}
   440  
   441  	if change.Kind != archive.ChangeAdd {
   442  		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
   443  	}
   444  }
   445  
   446  func TestDiffSize(t *testing.T) {
   447  	d := newDriver(t)
   448  	defer os.RemoveAll(tmp)
   449  
   450  	if err := d.CreateReadWrite("1", "", nil); err != nil {
   451  		t.Fatal(err)
   452  	}
   453  
   454  	diffPath, err := driverGet(d, "1", "")
   455  	if err != nil {
   456  		t.Fatal(err)
   457  	}
   458  
   459  	// Add a file to the diff path with a fixed size
   460  	size := int64(1024)
   461  
   462  	f, err := os.Create(path.Join(diffPath, "test_file"))
   463  	if err != nil {
   464  		t.Fatal(err)
   465  	}
   466  	if err := f.Truncate(size); err != nil {
   467  		t.Fatal(err)
   468  	}
   469  	s, err := f.Stat()
   470  	if err != nil {
   471  		t.Fatal(err)
   472  	}
   473  	size = s.Size()
   474  	if err := f.Close(); err != nil {
   475  		t.Fatal(err)
   476  	}
   477  
   478  	diffSize, err := d.DiffSize("1", "")
   479  	if err != nil {
   480  		t.Fatal(err)
   481  	}
   482  	if diffSize != size {
   483  		t.Fatalf("Expected size to be %d got %d", size, diffSize)
   484  	}
   485  }
   486  
   487  func TestChildDiffSize(t *testing.T) {
   488  	d := newDriver(t)
   489  	defer os.RemoveAll(tmp)
   490  	defer d.Cleanup()
   491  
   492  	if err := d.CreateReadWrite("1", "", nil); err != nil {
   493  		t.Fatal(err)
   494  	}
   495  
   496  	diffPath, err := driverGet(d, "1", "")
   497  	if err != nil {
   498  		t.Fatal(err)
   499  	}
   500  
   501  	// Add a file to the diff path with a fixed size
   502  	size := int64(1024)
   503  
   504  	f, err := os.Create(path.Join(diffPath, "test_file"))
   505  	if err != nil {
   506  		t.Fatal(err)
   507  	}
   508  	if err := f.Truncate(size); err != nil {
   509  		t.Fatal(err)
   510  	}
   511  	s, err := f.Stat()
   512  	if err != nil {
   513  		t.Fatal(err)
   514  	}
   515  	size = s.Size()
   516  	if err := f.Close(); err != nil {
   517  		t.Fatal(err)
   518  	}
   519  
   520  	diffSize, err := d.DiffSize("1", "")
   521  	if err != nil {
   522  		t.Fatal(err)
   523  	}
   524  	if diffSize != size {
   525  		t.Fatalf("Expected size to be %d got %d", size, diffSize)
   526  	}
   527  
   528  	if err := d.Create("2", "1", nil); err != nil {
   529  		t.Fatal(err)
   530  	}
   531  
   532  	diffSize, err = d.DiffSize("2", "1")
   533  	if err != nil {
   534  		t.Fatal(err)
   535  	}
   536  	// The diff size for the child should be zero
   537  	if diffSize != 0 {
   538  		t.Fatalf("Expected size to be %d got %d", 0, diffSize)
   539  	}
   540  }
   541  
   542  func TestExists(t *testing.T) {
   543  	d := newDriver(t)
   544  	defer os.RemoveAll(tmp)
   545  	defer d.Cleanup()
   546  
   547  	if err := d.Create("1", "", nil); err != nil {
   548  		t.Fatal(err)
   549  	}
   550  
   551  	if d.Exists("none") {
   552  		t.Fatal("id none should not exist in the driver")
   553  	}
   554  
   555  	if !d.Exists("1") {
   556  		t.Fatal("id 1 should exist in the driver")
   557  	}
   558  }
   559  
   560  func TestStatus(t *testing.T) {
   561  	d := newDriver(t)
   562  	defer os.RemoveAll(tmp)
   563  	defer d.Cleanup()
   564  
   565  	if err := d.Create("1", "", nil); err != nil {
   566  		t.Fatal(err)
   567  	}
   568  
   569  	status := d.Status()
   570  	assert.Check(t, is.Len(status, 4))
   571  
   572  	rootDir := status[0]
   573  	dirs := status[2]
   574  	if rootDir[0] != "Root Dir" {
   575  		t.Fatalf("Expected Root Dir got %s", rootDir[0])
   576  	}
   577  	if rootDir[1] != d.rootPath() {
   578  		t.Fatalf("Expected %s got %s", d.rootPath(), rootDir[1])
   579  	}
   580  	if dirs[0] != "Dirs" {
   581  		t.Fatalf("Expected Dirs got %s", dirs[0])
   582  	}
   583  	if dirs[1] != "1" {
   584  		t.Fatalf("Expected 1 got %s", dirs[1])
   585  	}
   586  }
   587  
   588  func TestApplyDiff(t *testing.T) {
   589  	d := newDriver(t)
   590  	defer os.RemoveAll(tmp)
   591  	defer d.Cleanup()
   592  
   593  	if err := d.CreateReadWrite("1", "", nil); err != nil {
   594  		t.Fatal(err)
   595  	}
   596  
   597  	diffPath, err := driverGet(d, "1", "")
   598  	if err != nil {
   599  		t.Fatal(err)
   600  	}
   601  
   602  	// Add a file to the diff path with a fixed size
   603  	size := int64(1024)
   604  
   605  	f, err := os.Create(path.Join(diffPath, "test_file"))
   606  	if err != nil {
   607  		t.Fatal(err)
   608  	}
   609  	if err := f.Truncate(size); err != nil {
   610  		t.Fatal(err)
   611  	}
   612  	f.Close()
   613  
   614  	diff, err := d.Diff("1", "")
   615  	if err != nil {
   616  		t.Fatal(err)
   617  	}
   618  
   619  	if err := d.Create("2", "", nil); err != nil {
   620  		t.Fatal(err)
   621  	}
   622  	if err := d.Create("3", "2", nil); err != nil {
   623  		t.Fatal(err)
   624  	}
   625  
   626  	if err := d.applyDiff("3", diff); err != nil {
   627  		t.Fatal(err)
   628  	}
   629  
   630  	// Ensure that the file is in the mount point for id 3
   631  
   632  	mountPoint, err := driverGet(d, "3", "")
   633  	if err != nil {
   634  		t.Fatal(err)
   635  	}
   636  	if _, err := os.Stat(path.Join(mountPoint, "test_file")); err != nil {
   637  		t.Fatal(err)
   638  	}
   639  }
   640  
   641  func hash(c string) string {
   642  	h := sha256.New()
   643  	fmt.Fprint(h, c)
   644  	return hex.EncodeToString(h.Sum(nil))
   645  }
   646  
   647  func testMountMoreThan42Layers(t *testing.T, mountPath string) {
   648  	if err := os.MkdirAll(mountPath, 0755); err != nil {
   649  		t.Fatal(err)
   650  	}
   651  
   652  	defer os.RemoveAll(mountPath)
   653  	d := testInit(mountPath, t).(*Driver)
   654  	defer d.Cleanup()
   655  	var last string
   656  	var expected int
   657  
   658  	for i := 1; i < 127; i++ {
   659  		expected++
   660  		var (
   661  			parent  = fmt.Sprintf("%d", i-1)
   662  			current = fmt.Sprintf("%d", i)
   663  		)
   664  
   665  		if parent == "0" {
   666  			parent = ""
   667  		} else {
   668  			parent = hash(parent)
   669  		}
   670  		current = hash(current)
   671  
   672  		err := d.CreateReadWrite(current, parent, nil)
   673  		assert.NilError(t, err, "current layer %d", i)
   674  
   675  		point, err := driverGet(d, current, "")
   676  		assert.NilError(t, err, "current layer %d", i)
   677  
   678  		f, err := os.Create(path.Join(point, current))
   679  		assert.NilError(t, err, "current layer %d", i)
   680  		f.Close()
   681  
   682  		if i%10 == 0 {
   683  			err := os.Remove(path.Join(point, parent))
   684  			assert.NilError(t, err, "current layer %d", i)
   685  			expected--
   686  		}
   687  		last = current
   688  	}
   689  
   690  	// Perform the actual mount for the top most image
   691  	point, err := driverGet(d, last, "")
   692  	assert.NilError(t, err)
   693  	files, err := ioutil.ReadDir(point)
   694  	assert.NilError(t, err)
   695  	assert.Check(t, is.Len(files, expected))
   696  }
   697  
   698  func TestMountMoreThan42Layers(t *testing.T) {
   699  	defer os.RemoveAll(tmpOuter)
   700  	testMountMoreThan42Layers(t, tmp)
   701  }
   702  
   703  func TestMountMoreThan42LayersMatchingPathLength(t *testing.T) {
   704  	defer os.RemoveAll(tmpOuter)
   705  	zeroes := "0"
   706  	for {
   707  		// This finds a mount path so that when combined into aufs mount options
   708  		// 4096 byte boundary would be in between the paths or in permission
   709  		// section. For '/tmp' it will use '/tmp/aufs-tests/00000000/aufs'
   710  		mountPath := path.Join(tmpOuter, zeroes, "aufs")
   711  		pathLength := 77 + len(mountPath)
   712  
   713  		if mod := 4095 % pathLength; mod == 0 || mod > pathLength-2 {
   714  			t.Logf("Using path: %s", mountPath)
   715  			testMountMoreThan42Layers(t, mountPath)
   716  			return
   717  		}
   718  		zeroes += "0"
   719  	}
   720  }
   721  
   722  func BenchmarkConcurrentAccess(b *testing.B) {
   723  	b.StopTimer()
   724  	b.ResetTimer()
   725  
   726  	d := newDriver(b)
   727  	defer os.RemoveAll(tmp)
   728  	defer d.Cleanup()
   729  
   730  	numConcurrent := 256
   731  	// create a bunch of ids
   732  	ids := make([]string, numConcurrent)
   733  	for i := 0; i < numConcurrent; i++ {
   734  		ids[i] = stringid.GenerateRandomID()
   735  	}
   736  
   737  	if err := d.Create(ids[0], "", nil); err != nil {
   738  		b.Fatal(err)
   739  	}
   740  
   741  	if err := d.Create(ids[1], ids[0], nil); err != nil {
   742  		b.Fatal(err)
   743  	}
   744  
   745  	parent := ids[1]
   746  	ids = ids[2:]
   747  
   748  	chErr := make(chan error, numConcurrent)
   749  	var outerGroup sync.WaitGroup
   750  	outerGroup.Add(len(ids))
   751  	b.StartTimer()
   752  
   753  	// here's the actual bench
   754  	for _, id := range ids {
   755  		go func(id string) {
   756  			defer outerGroup.Done()
   757  			if err := d.Create(id, parent, nil); err != nil {
   758  				b.Logf("Create %s failed", id)
   759  				chErr <- err
   760  				return
   761  			}
   762  			var innerGroup sync.WaitGroup
   763  			for i := 0; i < b.N; i++ {
   764  				innerGroup.Add(1)
   765  				go func() {
   766  					d.Get(id, "")
   767  					d.Put(id)
   768  					innerGroup.Done()
   769  				}()
   770  			}
   771  			innerGroup.Wait()
   772  			d.Remove(id)
   773  		}(id)
   774  	}
   775  
   776  	outerGroup.Wait()
   777  	b.StopTimer()
   778  	close(chErr)
   779  	for err := range chErr {
   780  		if err != nil {
   781  			b.Log(err)
   782  			b.Fail()
   783  		}
   784  	}
   785  }
   786  
   787  func TestInitStaleCleanup(t *testing.T) {
   788  	if err := os.MkdirAll(tmp, 0755); err != nil {
   789  		t.Fatal(err)
   790  	}
   791  	defer os.RemoveAll(tmp)
   792  
   793  	for _, d := range []string{"diff", "mnt"} {
   794  		if err := os.MkdirAll(filepath.Join(tmp, d, "123-removing"), 0755); err != nil {
   795  			t.Fatal(err)
   796  		}
   797  	}
   798  
   799  	testInit(tmp, t)
   800  	for _, d := range []string{"diff", "mnt"} {
   801  		if _, err := os.Stat(filepath.Join(tmp, d, "123-removing")); err == nil {
   802  			t.Fatal("cleanup failed")
   803  		}
   804  	}
   805  }