github.com/ojongerius/docker@v1.11.2/daemon/graphdriver/graphtest/graphtest_unix.go (about)

     1  // +build linux freebsd
     2  
     3  package graphtest
     4  
     5  import (
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"path"
    10  	"syscall"
    11  	"testing"
    12  
    13  	"github.com/docker/docker/daemon/graphdriver"
    14  )
    15  
    16  var (
    17  	drv *Driver
    18  )
    19  
    20  // Driver conforms to graphdriver.Driver interface and
    21  // contains information such as root and reference count of the number of clients using it.
    22  // This helps in testing drivers added into the framework.
    23  type Driver struct {
    24  	graphdriver.Driver
    25  	root     string
    26  	refCount int
    27  }
    28  
    29  // InitLoopbacks ensures that the loopback devices are properly created within
    30  // the system running the device mapper tests.
    31  func InitLoopbacks() error {
    32  	statT, err := getBaseLoopStats()
    33  	if err != nil {
    34  		return err
    35  	}
    36  	// create at least 8 loopback files, ya, that is a good number
    37  	for i := 0; i < 8; i++ {
    38  		loopPath := fmt.Sprintf("/dev/loop%d", i)
    39  		// only create new loopback files if they don't exist
    40  		if _, err := os.Stat(loopPath); err != nil {
    41  			if mkerr := syscall.Mknod(loopPath,
    42  				uint32(statT.Mode|syscall.S_IFBLK), int((7<<8)|(i&0xff)|((i&0xfff00)<<12))); mkerr != nil {
    43  				return mkerr
    44  			}
    45  			os.Chown(loopPath, int(statT.Uid), int(statT.Gid))
    46  		}
    47  	}
    48  	return nil
    49  }
    50  
    51  // getBaseLoopStats inspects /dev/loop0 to collect uid,gid, and mode for the
    52  // loop0 device on the system.  If it does not exist we assume 0,0,0660 for the
    53  // stat data
    54  func getBaseLoopStats() (*syscall.Stat_t, error) {
    55  	loop0, err := os.Stat("/dev/loop0")
    56  	if err != nil {
    57  		if os.IsNotExist(err) {
    58  			return &syscall.Stat_t{
    59  				Uid:  0,
    60  				Gid:  0,
    61  				Mode: 0660,
    62  			}, nil
    63  		}
    64  		return nil, err
    65  	}
    66  	return loop0.Sys().(*syscall.Stat_t), nil
    67  }
    68  
    69  func newDriver(t *testing.T, name string) *Driver {
    70  	root, err := ioutil.TempDir("/var/tmp", "docker-graphtest-")
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	if err := os.MkdirAll(root, 0755); err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	d, err := graphdriver.GetDriver(name, root, nil, nil, nil)
    80  	if err != nil {
    81  		t.Logf("graphdriver: %v\n", err)
    82  		if err == graphdriver.ErrNotSupported || err == graphdriver.ErrPrerequisites || err == graphdriver.ErrIncompatibleFS {
    83  			t.Skipf("Driver %s not supported", name)
    84  		}
    85  		t.Fatal(err)
    86  	}
    87  	return &Driver{d, root, 1}
    88  }
    89  
    90  func cleanup(t *testing.T, d *Driver) {
    91  	if err := drv.Cleanup(); err != nil {
    92  		t.Fatal(err)
    93  	}
    94  	os.RemoveAll(d.root)
    95  }
    96  
    97  // GetDriver create a new driver with given name or return a existing driver with the name updating the reference count.
    98  func GetDriver(t *testing.T, name string) graphdriver.Driver {
    99  	if drv == nil {
   100  		drv = newDriver(t, name)
   101  	} else {
   102  		drv.refCount++
   103  	}
   104  	return drv
   105  }
   106  
   107  // PutDriver removes the driver if it is no longer used and updates the reference count.
   108  func PutDriver(t *testing.T) {
   109  	if drv == nil {
   110  		t.Skip("No driver to put!")
   111  	}
   112  	drv.refCount--
   113  	if drv.refCount == 0 {
   114  		cleanup(t, drv)
   115  		drv = nil
   116  	}
   117  }
   118  
   119  func verifyFile(t *testing.T, path string, mode os.FileMode, uid, gid uint32) {
   120  	fi, err := os.Stat(path)
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	if fi.Mode()&os.ModeType != mode&os.ModeType {
   126  		t.Fatalf("Expected %s type 0x%x, got 0x%x", path, mode&os.ModeType, fi.Mode()&os.ModeType)
   127  	}
   128  
   129  	if fi.Mode()&os.ModePerm != mode&os.ModePerm {
   130  		t.Fatalf("Expected %s mode %o, got %o", path, mode&os.ModePerm, fi.Mode()&os.ModePerm)
   131  	}
   132  
   133  	if fi.Mode()&os.ModeSticky != mode&os.ModeSticky {
   134  		t.Fatalf("Expected %s sticky 0x%x, got 0x%x", path, mode&os.ModeSticky, fi.Mode()&os.ModeSticky)
   135  	}
   136  
   137  	if fi.Mode()&os.ModeSetuid != mode&os.ModeSetuid {
   138  		t.Fatalf("Expected %s setuid 0x%x, got 0x%x", path, mode&os.ModeSetuid, fi.Mode()&os.ModeSetuid)
   139  	}
   140  
   141  	if fi.Mode()&os.ModeSetgid != mode&os.ModeSetgid {
   142  		t.Fatalf("Expected %s setgid 0x%x, got 0x%x", path, mode&os.ModeSetgid, fi.Mode()&os.ModeSetgid)
   143  	}
   144  
   145  	if stat, ok := fi.Sys().(*syscall.Stat_t); ok {
   146  		if stat.Uid != uid {
   147  			t.Fatalf("%s no owned by uid %d", path, uid)
   148  		}
   149  		if stat.Gid != gid {
   150  			t.Fatalf("%s not owned by gid %d", path, gid)
   151  		}
   152  	}
   153  
   154  }
   155  
   156  // readDir reads a directory just like ioutil.ReadDir()
   157  // then hides specific files (currently "lost+found")
   158  // so the tests don't "see" it
   159  func readDir(dir string) ([]os.FileInfo, error) {
   160  	a, err := ioutil.ReadDir(dir)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	b := a[:0]
   166  	for _, x := range a {
   167  		if x.Name() != "lost+found" { // ext4 always have this dir
   168  			b = append(b, x)
   169  		}
   170  	}
   171  
   172  	return b, nil
   173  }
   174  
   175  // DriverTestCreateEmpty creates an new image and verifies it is empty and the right metadata
   176  func DriverTestCreateEmpty(t *testing.T, drivername string) {
   177  	driver := GetDriver(t, drivername)
   178  	defer PutDriver(t)
   179  
   180  	if err := driver.Create("empty", "", ""); err != nil {
   181  		t.Fatal(err)
   182  	}
   183  
   184  	if !driver.Exists("empty") {
   185  		t.Fatal("Newly created image doesn't exist")
   186  	}
   187  
   188  	dir, err := driver.Get("empty", "")
   189  	if err != nil {
   190  		t.Fatal(err)
   191  	}
   192  
   193  	verifyFile(t, dir, 0755|os.ModeDir, 0, 0)
   194  
   195  	// Verify that the directory is empty
   196  	fis, err := readDir(dir)
   197  	if err != nil {
   198  		t.Fatal(err)
   199  	}
   200  
   201  	if len(fis) != 0 {
   202  		t.Fatal("New directory not empty")
   203  	}
   204  
   205  	driver.Put("empty")
   206  
   207  	if err := driver.Remove("empty"); err != nil {
   208  		t.Fatal(err)
   209  	}
   210  
   211  }
   212  
   213  func createBase(t *testing.T, driver graphdriver.Driver, name string) {
   214  	// We need to be able to set any perms
   215  	oldmask := syscall.Umask(0)
   216  	defer syscall.Umask(oldmask)
   217  
   218  	if err := driver.Create(name, "", ""); err != nil {
   219  		t.Fatal(err)
   220  	}
   221  
   222  	dir, err := driver.Get(name, "")
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  	defer driver.Put(name)
   227  
   228  	subdir := path.Join(dir, "a subdir")
   229  	if err := os.Mkdir(subdir, 0705|os.ModeSticky); err != nil {
   230  		t.Fatal(err)
   231  	}
   232  	if err := os.Chown(subdir, 1, 2); err != nil {
   233  		t.Fatal(err)
   234  	}
   235  
   236  	file := path.Join(dir, "a file")
   237  	if err := ioutil.WriteFile(file, []byte("Some data"), 0222|os.ModeSetuid); err != nil {
   238  		t.Fatal(err)
   239  	}
   240  }
   241  
   242  func verifyBase(t *testing.T, driver graphdriver.Driver, name string) {
   243  	dir, err := driver.Get(name, "")
   244  	if err != nil {
   245  		t.Fatal(err)
   246  	}
   247  	defer driver.Put(name)
   248  
   249  	subdir := path.Join(dir, "a subdir")
   250  	verifyFile(t, subdir, 0705|os.ModeDir|os.ModeSticky, 1, 2)
   251  
   252  	file := path.Join(dir, "a file")
   253  	verifyFile(t, file, 0222|os.ModeSetuid, 0, 0)
   254  
   255  	fis, err := readDir(dir)
   256  	if err != nil {
   257  		t.Fatal(err)
   258  	}
   259  
   260  	if len(fis) != 2 {
   261  		t.Fatal("Unexpected files in base image")
   262  	}
   263  
   264  }
   265  
   266  // DriverTestCreateBase create a base driver and verify.
   267  func DriverTestCreateBase(t *testing.T, drivername string) {
   268  	driver := GetDriver(t, drivername)
   269  	defer PutDriver(t)
   270  
   271  	createBase(t, driver, "Base")
   272  	verifyBase(t, driver, "Base")
   273  
   274  	if err := driver.Remove("Base"); err != nil {
   275  		t.Fatal(err)
   276  	}
   277  }
   278  
   279  // DriverTestCreateSnap Create a driver and snap and verify.
   280  func DriverTestCreateSnap(t *testing.T, drivername string) {
   281  	driver := GetDriver(t, drivername)
   282  	defer PutDriver(t)
   283  
   284  	createBase(t, driver, "Base")
   285  
   286  	if err := driver.Create("Snap", "Base", ""); err != nil {
   287  		t.Fatal(err)
   288  	}
   289  
   290  	verifyBase(t, driver, "Snap")
   291  
   292  	if err := driver.Remove("Snap"); err != nil {
   293  		t.Fatal(err)
   294  	}
   295  
   296  	if err := driver.Remove("Base"); err != nil {
   297  		t.Fatal(err)
   298  	}
   299  }