github.com/afein/docker@v1.8.2/daemon/graphdriver/aufs/aufs_test.go (about)

     1  // +build linux
     2  
     3  package aufs
     4  
     5  import (
     6  	"crypto/sha256"
     7  	"encoding/hex"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"path"
    12  	"testing"
    13  
    14  	"github.com/docker/docker/daemon/graphdriver"
    15  	"github.com/docker/docker/pkg/archive"
    16  	"github.com/docker/docker/pkg/reexec"
    17  )
    18  
    19  var (
    20  	tmpOuter = path.Join(os.TempDir(), "aufs-tests")
    21  	tmp      = path.Join(tmpOuter, "aufs")
    22  )
    23  
    24  func init() {
    25  	reexec.Init()
    26  }
    27  
    28  func testInit(dir string, t *testing.T) graphdriver.Driver {
    29  	d, err := Init(dir, nil)
    30  	if err != nil {
    31  		if err == graphdriver.ErrNotSupported {
    32  			t.Skip(err)
    33  		} else {
    34  			t.Fatal(err)
    35  		}
    36  	}
    37  	return d
    38  }
    39  
    40  func newDriver(t *testing.T) *Driver {
    41  	if err := os.MkdirAll(tmp, 0755); err != nil {
    42  		t.Fatal(err)
    43  	}
    44  
    45  	d := testInit(tmp, t)
    46  	return d.(*Driver)
    47  }
    48  
    49  func TestNewDriver(t *testing.T) {
    50  	if err := os.MkdirAll(tmp, 0755); err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	d := testInit(tmp, t)
    55  	defer os.RemoveAll(tmp)
    56  	if d == nil {
    57  		t.Fatalf("Driver should not be nil")
    58  	}
    59  }
    60  
    61  func TestAufsString(t *testing.T) {
    62  	d := newDriver(t)
    63  	defer os.RemoveAll(tmp)
    64  
    65  	if d.String() != "aufs" {
    66  		t.Fatalf("Expected aufs got %s", d.String())
    67  	}
    68  }
    69  
    70  func TestCreateDirStructure(t *testing.T) {
    71  	newDriver(t)
    72  	defer os.RemoveAll(tmp)
    73  
    74  	paths := []string{
    75  		"mnt",
    76  		"layers",
    77  		"diff",
    78  	}
    79  
    80  	for _, p := range paths {
    81  		if _, err := os.Stat(path.Join(tmp, p)); err != nil {
    82  			t.Fatal(err)
    83  		}
    84  	}
    85  }
    86  
    87  // We should be able to create two drivers with the same dir structure
    88  func TestNewDriverFromExistingDir(t *testing.T) {
    89  	if err := os.MkdirAll(tmp, 0755); err != nil {
    90  		t.Fatal(err)
    91  	}
    92  
    93  	testInit(tmp, t)
    94  	testInit(tmp, t)
    95  	os.RemoveAll(tmp)
    96  }
    97  
    98  func TestCreateNewDir(t *testing.T) {
    99  	d := newDriver(t)
   100  	defer os.RemoveAll(tmp)
   101  
   102  	if err := d.Create("1", ""); err != nil {
   103  		t.Fatal(err)
   104  	}
   105  }
   106  
   107  func TestCreateNewDirStructure(t *testing.T) {
   108  	d := newDriver(t)
   109  	defer os.RemoveAll(tmp)
   110  
   111  	if err := d.Create("1", ""); err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	paths := []string{
   116  		"mnt",
   117  		"diff",
   118  		"layers",
   119  	}
   120  
   121  	for _, p := range paths {
   122  		if _, err := os.Stat(path.Join(tmp, p, "1")); err != nil {
   123  			t.Fatal(err)
   124  		}
   125  	}
   126  }
   127  
   128  func TestRemoveImage(t *testing.T) {
   129  	d := newDriver(t)
   130  	defer os.RemoveAll(tmp)
   131  
   132  	if err := d.Create("1", ""); err != nil {
   133  		t.Fatal(err)
   134  	}
   135  
   136  	if err := d.Remove("1"); err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	paths := []string{
   141  		"mnt",
   142  		"diff",
   143  		"layers",
   144  	}
   145  
   146  	for _, p := range paths {
   147  		if _, err := os.Stat(path.Join(tmp, p, "1")); err == nil {
   148  			t.Fatalf("Error should not be nil because dirs with id 1 should be delted: %s", p)
   149  		}
   150  	}
   151  }
   152  
   153  func TestGetWithoutParent(t *testing.T) {
   154  	d := newDriver(t)
   155  	defer os.RemoveAll(tmp)
   156  
   157  	if err := d.Create("1", ""); err != nil {
   158  		t.Fatal(err)
   159  	}
   160  
   161  	diffPath, err := d.Get("1", "")
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	expected := path.Join(tmp, "diff", "1")
   166  	if diffPath != expected {
   167  		t.Fatalf("Expected path %s got %s", expected, diffPath)
   168  	}
   169  }
   170  
   171  func TestCleanupWithNoDirs(t *testing.T) {
   172  	d := newDriver(t)
   173  	defer os.RemoveAll(tmp)
   174  
   175  	if err := d.Cleanup(); err != nil {
   176  		t.Fatal(err)
   177  	}
   178  }
   179  
   180  func TestCleanupWithDir(t *testing.T) {
   181  	d := newDriver(t)
   182  	defer os.RemoveAll(tmp)
   183  
   184  	if err := d.Create("1", ""); err != nil {
   185  		t.Fatal(err)
   186  	}
   187  
   188  	if err := d.Cleanup(); err != nil {
   189  		t.Fatal(err)
   190  	}
   191  }
   192  
   193  func TestMountedFalseResponse(t *testing.T) {
   194  	d := newDriver(t)
   195  	defer os.RemoveAll(tmp)
   196  
   197  	if err := d.Create("1", ""); err != nil {
   198  		t.Fatal(err)
   199  	}
   200  
   201  	response, err := d.mounted("1")
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  	if response != false {
   207  		t.Fatalf("Response if dir id 1 is mounted should be false")
   208  	}
   209  }
   210  
   211  func TestMountedTrueReponse(t *testing.T) {
   212  	d := newDriver(t)
   213  	defer os.RemoveAll(tmp)
   214  	defer d.Cleanup()
   215  
   216  	if err := d.Create("1", ""); err != nil {
   217  		t.Fatal(err)
   218  	}
   219  	if err := d.Create("2", "1"); err != nil {
   220  		t.Fatal(err)
   221  	}
   222  
   223  	_, err := d.Get("2", "")
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  
   228  	response, err := d.mounted("2")
   229  	if err != nil {
   230  		t.Fatal(err)
   231  	}
   232  
   233  	if response != true {
   234  		t.Fatalf("Response if dir id 2 is mounted should be true")
   235  	}
   236  }
   237  
   238  func TestMountWithParent(t *testing.T) {
   239  	d := newDriver(t)
   240  	defer os.RemoveAll(tmp)
   241  
   242  	if err := d.Create("1", ""); err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	if err := d.Create("2", "1"); 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 == "" {
   260  		t.Fatal("mntPath should not be empty string")
   261  	}
   262  
   263  	expected := path.Join(tmp, "mnt", "2")
   264  	if mntPath != expected {
   265  		t.Fatalf("Expected %s got %s", expected, mntPath)
   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", ""); err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	if err := d.Create("2", "1"); 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 == "" {
   291  		t.Fatal("mntPath should not be empty string")
   292  	}
   293  
   294  	mounted, err := d.mounted("2")
   295  	if err != nil {
   296  		t.Fatal(err)
   297  	}
   298  
   299  	if !mounted {
   300  		t.Fatalf("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"); err == nil {
   313  		t.Fatalf("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.Create("1", ""); err != nil {
   322  		t.Fatal(err)
   323  	}
   324  
   325  	diffPath, err := d.Get("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.Fatalf("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", ""); err != nil {
   356  		t.Fatal(err)
   357  	}
   358  	if err := d.Create("2", "1"); err != nil {
   359  		t.Fatal(err)
   360  	}
   361  
   362  	defer func() {
   363  		if err := d.Cleanup(); err != nil {
   364  			t.Fatal(err)
   365  		}
   366  	}()
   367  
   368  	mntPoint, err := d.Get("2", "")
   369  	if err != nil {
   370  		t.Fatal(err)
   371  	}
   372  
   373  	// Create a file to save in the mountpoint
   374  	f, err := os.Create(path.Join(mntPoint, "test.txt"))
   375  	if err != nil {
   376  		t.Fatal(err)
   377  	}
   378  
   379  	if _, err := f.WriteString("testline"); err != nil {
   380  		t.Fatal(err)
   381  	}
   382  	if err := f.Close(); err != nil {
   383  		t.Fatal(err)
   384  	}
   385  
   386  	changes, err := d.Changes("2", "")
   387  	if err != nil {
   388  		t.Fatal(err)
   389  	}
   390  	if len(changes) != 1 {
   391  		t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
   392  	}
   393  	change := changes[0]
   394  
   395  	expectedPath := "/test.txt"
   396  	if change.Path != expectedPath {
   397  		t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
   398  	}
   399  
   400  	if change.Kind != archive.ChangeAdd {
   401  		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
   402  	}
   403  
   404  	if err := d.Create("3", "2"); err != nil {
   405  		t.Fatal(err)
   406  	}
   407  	mntPoint, err = d.Get("3", "")
   408  	if err != nil {
   409  		t.Fatal(err)
   410  	}
   411  
   412  	// Create a file to save in the mountpoint
   413  	f, err = os.Create(path.Join(mntPoint, "test2.txt"))
   414  	if err != nil {
   415  		t.Fatal(err)
   416  	}
   417  
   418  	if _, err := f.WriteString("testline"); err != nil {
   419  		t.Fatal(err)
   420  	}
   421  	if err := f.Close(); err != nil {
   422  		t.Fatal(err)
   423  	}
   424  
   425  	changes, err = d.Changes("3", "")
   426  	if err != nil {
   427  		t.Fatal(err)
   428  	}
   429  
   430  	if len(changes) != 1 {
   431  		t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
   432  	}
   433  	change = changes[0]
   434  
   435  	expectedPath = "/test2.txt"
   436  	if change.Path != expectedPath {
   437  		t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
   438  	}
   439  
   440  	if change.Kind != archive.ChangeAdd {
   441  		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
   442  	}
   443  }
   444  
   445  func TestDiffSize(t *testing.T) {
   446  	d := newDriver(t)
   447  	defer os.RemoveAll(tmp)
   448  
   449  	if err := d.Create("1", ""); err != nil {
   450  		t.Fatal(err)
   451  	}
   452  
   453  	diffPath, err := d.Get("1", "")
   454  	if err != nil {
   455  		t.Fatal(err)
   456  	}
   457  
   458  	// Add a file to the diff path with a fixed size
   459  	size := int64(1024)
   460  
   461  	f, err := os.Create(path.Join(diffPath, "test_file"))
   462  	if err != nil {
   463  		t.Fatal(err)
   464  	}
   465  	if err := f.Truncate(size); err != nil {
   466  		t.Fatal(err)
   467  	}
   468  	s, err := f.Stat()
   469  	if err != nil {
   470  		t.Fatal(err)
   471  	}
   472  	size = s.Size()
   473  	if err := f.Close(); err != nil {
   474  		t.Fatal(err)
   475  	}
   476  
   477  	diffSize, err := d.DiffSize("1", "")
   478  	if err != nil {
   479  		t.Fatal(err)
   480  	}
   481  	if diffSize != size {
   482  		t.Fatalf("Expected size to be %d got %d", size, diffSize)
   483  	}
   484  }
   485  
   486  func TestChildDiffSize(t *testing.T) {
   487  	d := newDriver(t)
   488  	defer os.RemoveAll(tmp)
   489  	defer d.Cleanup()
   490  
   491  	if err := d.Create("1", ""); err != nil {
   492  		t.Fatal(err)
   493  	}
   494  
   495  	diffPath, err := d.Get("1", "")
   496  	if err != nil {
   497  		t.Fatal(err)
   498  	}
   499  
   500  	// Add a file to the diff path with a fixed size
   501  	size := int64(1024)
   502  
   503  	f, err := os.Create(path.Join(diffPath, "test_file"))
   504  	if err != nil {
   505  		t.Fatal(err)
   506  	}
   507  	if err := f.Truncate(size); err != nil {
   508  		t.Fatal(err)
   509  	}
   510  	s, err := f.Stat()
   511  	if err != nil {
   512  		t.Fatal(err)
   513  	}
   514  	size = s.Size()
   515  	if err := f.Close(); err != nil {
   516  		t.Fatal(err)
   517  	}
   518  
   519  	diffSize, err := d.DiffSize("1", "")
   520  	if err != nil {
   521  		t.Fatal(err)
   522  	}
   523  	if diffSize != size {
   524  		t.Fatalf("Expected size to be %d got %d", size, diffSize)
   525  	}
   526  
   527  	if err := d.Create("2", "1"); err != nil {
   528  		t.Fatal(err)
   529  	}
   530  
   531  	diffSize, err = d.DiffSize("2", "")
   532  	if err != nil {
   533  		t.Fatal(err)
   534  	}
   535  	// The diff size for the child should be zero
   536  	if diffSize != 0 {
   537  		t.Fatalf("Expected size to be %d got %d", 0, diffSize)
   538  	}
   539  }
   540  
   541  func TestExists(t *testing.T) {
   542  	d := newDriver(t)
   543  	defer os.RemoveAll(tmp)
   544  	defer d.Cleanup()
   545  
   546  	if err := d.Create("1", ""); err != nil {
   547  		t.Fatal(err)
   548  	}
   549  
   550  	if d.Exists("none") {
   551  		t.Fatal("id name should not exist in the driver")
   552  	}
   553  
   554  	if !d.Exists("1") {
   555  		t.Fatal("id 1 should exist in the driver")
   556  	}
   557  }
   558  
   559  func TestStatus(t *testing.T) {
   560  	d := newDriver(t)
   561  	defer os.RemoveAll(tmp)
   562  	defer d.Cleanup()
   563  
   564  	if err := d.Create("1", ""); err != nil {
   565  		t.Fatal(err)
   566  	}
   567  
   568  	status := d.Status()
   569  	if status == nil || len(status) == 0 {
   570  		t.Fatal("Status should not be nil or empty")
   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.Create("1", ""); err != nil {
   594  		t.Fatal(err)
   595  	}
   596  
   597  	diffPath, err := d.Get("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", ""); err != nil {
   620  		t.Fatal(err)
   621  	}
   622  	if err := d.Create("3", "2"); 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 := d.Get("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  		if err := d.Create(current, parent); err != nil {
   673  			t.Logf("Current layer %d", i)
   674  			t.Error(err)
   675  		}
   676  		point, err := d.Get(current, "")
   677  		if err != nil {
   678  			t.Logf("Current layer %d", i)
   679  			t.Error(err)
   680  		}
   681  		f, err := os.Create(path.Join(point, current))
   682  		if err != nil {
   683  			t.Logf("Current layer %d", i)
   684  			t.Error(err)
   685  		}
   686  		f.Close()
   687  
   688  		if i%10 == 0 {
   689  			if err := os.Remove(path.Join(point, parent)); err != nil {
   690  				t.Logf("Current layer %d", i)
   691  				t.Error(err)
   692  			}
   693  			expected--
   694  		}
   695  		last = current
   696  	}
   697  
   698  	// Perform the actual mount for the top most image
   699  	point, err := d.Get(last, "")
   700  	if err != nil {
   701  		t.Error(err)
   702  	}
   703  	files, err := ioutil.ReadDir(point)
   704  	if err != nil {
   705  		t.Error(err)
   706  	}
   707  	if len(files) != expected {
   708  		t.Errorf("Expected %d got %d", expected, len(files))
   709  	}
   710  }
   711  
   712  func TestMountMoreThan42Layers(t *testing.T) {
   713  	os.RemoveAll(tmpOuter)
   714  	testMountMoreThan42Layers(t, tmp)
   715  }
   716  
   717  func TestMountMoreThan42LayersMatchingPathLength(t *testing.T) {
   718  	defer os.RemoveAll(tmpOuter)
   719  	zeroes := "0"
   720  	for {
   721  		// This finds a mount path so that when combined into aufs mount options
   722  		// 4096 byte boundary would be in between the paths or in permission
   723  		// section. For '/tmp' it will use '/tmp/aufs-tests/00000000/aufs'
   724  		mountPath := path.Join(tmpOuter, zeroes, "aufs")
   725  		pathLength := 77 + len(mountPath)
   726  
   727  		if mod := 4095 % pathLength; mod == 0 || mod > pathLength-2 {
   728  			t.Logf("Using path: %s", mountPath)
   729  			testMountMoreThan42Layers(t, mountPath)
   730  			return
   731  		}
   732  		zeroes += "0"
   733  	}
   734  }