github.com/fcwu/docker@v1.4.2-0.20150115145920-2a69ca89f0df/daemon/graphdriver/aufs/aufs_test.go (about)

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