github.com/psychoss/docker@v1.9.0/daemon/graphdriver/graphtest/graphtest.go (about)

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