github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/volume/local/local_test.go (about)

     1  package local
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"reflect"
     8  	"runtime"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/docker/docker/pkg/mount"
    13  )
    14  
    15  func TestRemove(t *testing.T) {
    16  	// TODO Windows: Investigate why this test fails on Windows under CI
    17  	//               but passes locally.
    18  	if runtime.GOOS == "windows" {
    19  		t.Skip("Test failing on Windows CI")
    20  	}
    21  	rootDir, err := ioutil.TempDir("", "local-volume-test")
    22  	if err != nil {
    23  		t.Fatal(err)
    24  	}
    25  	defer os.RemoveAll(rootDir)
    26  
    27  	r, err := New(rootDir, 0, 0)
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	vol, err := r.Create("testing", nil)
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  
    37  	if err := r.Remove(vol); err != nil {
    38  		t.Fatal(err)
    39  	}
    40  
    41  	vol, err = r.Create("testing2", nil)
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	if err := os.RemoveAll(vol.Path()); err != nil {
    46  		t.Fatal(err)
    47  	}
    48  
    49  	if err := r.Remove(vol); err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	if _, err := os.Stat(vol.Path()); err != nil && !os.IsNotExist(err) {
    54  		t.Fatal("volume dir not removed")
    55  	}
    56  
    57  	if l, _ := r.List(); len(l) != 0 {
    58  		t.Fatal("expected there to be no volumes")
    59  	}
    60  }
    61  
    62  func TestInitializeWithVolumes(t *testing.T) {
    63  	rootDir, err := ioutil.TempDir("", "local-volume-test")
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	defer os.RemoveAll(rootDir)
    68  
    69  	r, err := New(rootDir, 0, 0)
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	vol, err := r.Create("testing", nil)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	r, err = New(rootDir, 0, 0)
    80  	if err != nil {
    81  		t.Fatal(err)
    82  	}
    83  
    84  	v, err := r.Get(vol.Name())
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  
    89  	if v.Path() != vol.Path() {
    90  		t.Fatal("expected to re-initialize root with existing volumes")
    91  	}
    92  }
    93  
    94  func TestCreate(t *testing.T) {
    95  	rootDir, err := ioutil.TempDir("", "local-volume-test")
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  	defer os.RemoveAll(rootDir)
   100  
   101  	r, err := New(rootDir, 0, 0)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	cases := map[string]bool{
   107  		"name":                  true,
   108  		"name-with-dash":        true,
   109  		"name_with_underscore":  true,
   110  		"name/with/slash":       false,
   111  		"name/with/../../slash": false,
   112  		"./name":                false,
   113  		"../name":               false,
   114  		"./":                    false,
   115  		"../":                   false,
   116  		"~":                     false,
   117  		".":                     false,
   118  		"..":                    false,
   119  		"...":                   false,
   120  	}
   121  
   122  	for name, success := range cases {
   123  		v, err := r.Create(name, nil)
   124  		if success {
   125  			if err != nil {
   126  				t.Fatal(err)
   127  			}
   128  			if v.Name() != name {
   129  				t.Fatalf("Expected volume with name %s, got %s", name, v.Name())
   130  			}
   131  		} else {
   132  			if err == nil {
   133  				t.Fatalf("Expected error creating volume with name %s, got nil", name)
   134  			}
   135  		}
   136  	}
   137  
   138  	r, err = New(rootDir, 0, 0)
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  }
   143  
   144  func TestValidateName(t *testing.T) {
   145  	r := &Root{}
   146  	names := map[string]bool{
   147  		"x":           false,
   148  		"/testvol":    false,
   149  		"thing.d":     true,
   150  		"hello-world": true,
   151  		"./hello":     false,
   152  		".hello":      false,
   153  	}
   154  
   155  	for vol, expected := range names {
   156  		err := r.validateName(vol)
   157  		if expected && err != nil {
   158  			t.Fatalf("expected %s to be valid got %v", vol, err)
   159  		}
   160  		if !expected && err == nil {
   161  			t.Fatalf("expected %s to be invalid", vol)
   162  		}
   163  	}
   164  }
   165  
   166  func TestCreateWithOpts(t *testing.T) {
   167  	if runtime.GOOS == "windows" {
   168  		t.Skip()
   169  	}
   170  
   171  	rootDir, err := ioutil.TempDir("", "local-volume-test")
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	defer os.RemoveAll(rootDir)
   176  
   177  	r, err := New(rootDir, 0, 0)
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  
   182  	if _, err := r.Create("test", map[string]string{"invalidopt": "notsupported"}); err == nil {
   183  		t.Fatal("expected invalid opt to cause error")
   184  	}
   185  
   186  	vol, err := r.Create("test", map[string]string{"device": "tmpfs", "type": "tmpfs", "o": "size=1m,uid=1000"})
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	v := vol.(*localVolume)
   191  
   192  	dir, err := v.Mount("1234")
   193  	if err != nil {
   194  		t.Fatal(err)
   195  	}
   196  	defer func() {
   197  		if err := v.Unmount("1234"); err != nil {
   198  			t.Fatal(err)
   199  		}
   200  	}()
   201  
   202  	mountInfos, err := mount.GetMounts()
   203  	if err != nil {
   204  		t.Fatal(err)
   205  	}
   206  
   207  	var found bool
   208  	for _, info := range mountInfos {
   209  		if info.Mountpoint == dir {
   210  			found = true
   211  			if info.Fstype != "tmpfs" {
   212  				t.Fatalf("expected tmpfs mount, got %q", info.Fstype)
   213  			}
   214  			if info.Source != "tmpfs" {
   215  				t.Fatalf("expected tmpfs mount, got %q", info.Source)
   216  			}
   217  			if !strings.Contains(info.VfsOpts, "uid=1000") {
   218  				t.Fatalf("expected mount info to have uid=1000: %q", info.VfsOpts)
   219  			}
   220  			if !strings.Contains(info.VfsOpts, "size=1024k") {
   221  				t.Fatalf("expected mount info to have size=1024k: %q", info.VfsOpts)
   222  			}
   223  			break
   224  		}
   225  	}
   226  
   227  	if !found {
   228  		t.Fatal("mount not found")
   229  	}
   230  
   231  	if v.active.count != 1 {
   232  		t.Fatalf("Expected active mount count to be 1, got %d", v.active.count)
   233  	}
   234  
   235  	// test double mount
   236  	if _, err := v.Mount("1234"); err != nil {
   237  		t.Fatal(err)
   238  	}
   239  	if v.active.count != 2 {
   240  		t.Fatalf("Expected active mount count to be 2, got %d", v.active.count)
   241  	}
   242  
   243  	if err := v.Unmount("1234"); err != nil {
   244  		t.Fatal(err)
   245  	}
   246  	if v.active.count != 1 {
   247  		t.Fatalf("Expected active mount count to be 1, got %d", v.active.count)
   248  	}
   249  
   250  	mounted, err := mount.Mounted(v.path)
   251  	if err != nil {
   252  		t.Fatal(err)
   253  	}
   254  	if !mounted {
   255  		t.Fatal("expected mount to still be active")
   256  	}
   257  
   258  	r, err = New(rootDir, 0, 0)
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	v2, exists := r.volumes["test"]
   264  	if !exists {
   265  		t.Fatal("missing volume on restart")
   266  	}
   267  
   268  	if !reflect.DeepEqual(v.opts, v2.opts) {
   269  		t.Fatal("missing volume options on restart")
   270  	}
   271  }
   272  
   273  func TestRealodNoOpts(t *testing.T) {
   274  	rootDir, err := ioutil.TempDir("", "volume-test-reload-no-opts")
   275  	if err != nil {
   276  		t.Fatal(err)
   277  	}
   278  	defer os.RemoveAll(rootDir)
   279  
   280  	r, err := New(rootDir, 0, 0)
   281  	if err != nil {
   282  		t.Fatal(err)
   283  	}
   284  
   285  	if _, err := r.Create("test1", nil); err != nil {
   286  		t.Fatal(err)
   287  	}
   288  	if _, err := r.Create("test2", nil); err != nil {
   289  		t.Fatal(err)
   290  	}
   291  	// make sure a file with `null` (.e.g. empty opts map from older daemon) is ok
   292  	if err := ioutil.WriteFile(filepath.Join(rootDir, "test2"), []byte("null"), 600); err != nil {
   293  		t.Fatal(err)
   294  	}
   295  
   296  	if _, err := r.Create("test3", nil); err != nil {
   297  		t.Fatal(err)
   298  	}
   299  	// make sure an empty opts file doesn't break us too
   300  	if err := ioutil.WriteFile(filepath.Join(rootDir, "test3"), nil, 600); err != nil {
   301  		t.Fatal(err)
   302  	}
   303  
   304  	if _, err := r.Create("test4", map[string]string{}); err != nil {
   305  		t.Fatal(err)
   306  	}
   307  
   308  	r, err = New(rootDir, 0, 0)
   309  	if err != nil {
   310  		t.Fatal(err)
   311  	}
   312  
   313  	for _, name := range []string{"test1", "test2", "test3", "test4"} {
   314  		v, err := r.Get(name)
   315  		if err != nil {
   316  			t.Fatal(err)
   317  		}
   318  		lv, ok := v.(*localVolume)
   319  		if !ok {
   320  			t.Fatalf("expected *localVolume got: %v", reflect.TypeOf(v))
   321  		}
   322  		if lv.opts != nil {
   323  			t.Fatalf("expected opts to be nil, got: %v", lv.opts)
   324  		}
   325  		if _, err := lv.Mount("1234"); err != nil {
   326  			t.Fatal(err)
   327  		}
   328  	}
   329  }