github.com/dpiddy/docker@v1.12.2-rc1/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  		"/testvol":    false,
   148  		"thing.d":     true,
   149  		"hello-world": true,
   150  		"./hello":     false,
   151  		".hello":      false,
   152  	}
   153  
   154  	for vol, expected := range names {
   155  		err := r.validateName(vol)
   156  		if expected && err != nil {
   157  			t.Fatalf("expected %s to be valid got %v", vol, err)
   158  		}
   159  		if !expected && err == nil {
   160  			t.Fatalf("expected %s to be invalid", vol)
   161  		}
   162  	}
   163  }
   164  
   165  func TestCreateWithOpts(t *testing.T) {
   166  	if runtime.GOOS == "windows" {
   167  		t.Skip()
   168  	}
   169  
   170  	rootDir, err := ioutil.TempDir("", "local-volume-test")
   171  	if err != nil {
   172  		t.Fatal(err)
   173  	}
   174  	defer os.RemoveAll(rootDir)
   175  
   176  	r, err := New(rootDir, 0, 0)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  
   181  	if _, err := r.Create("test", map[string]string{"invalidopt": "notsupported"}); err == nil {
   182  		t.Fatal("expected invalid opt to cause error")
   183  	}
   184  
   185  	vol, err := r.Create("test", map[string]string{"device": "tmpfs", "type": "tmpfs", "o": "size=1m,uid=1000"})
   186  	if err != nil {
   187  		t.Fatal(err)
   188  	}
   189  	v := vol.(*localVolume)
   190  
   191  	dir, err := v.Mount("1234")
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  	defer func() {
   196  		if err := v.Unmount("1234"); err != nil {
   197  			t.Fatal(err)
   198  		}
   199  	}()
   200  
   201  	mountInfos, err := mount.GetMounts()
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  	var found bool
   207  	for _, info := range mountInfos {
   208  		if info.Mountpoint == dir {
   209  			found = true
   210  			if info.Fstype != "tmpfs" {
   211  				t.Fatalf("expected tmpfs mount, got %q", info.Fstype)
   212  			}
   213  			if info.Source != "tmpfs" {
   214  				t.Fatalf("expected tmpfs mount, got %q", info.Source)
   215  			}
   216  			if !strings.Contains(info.VfsOpts, "uid=1000") {
   217  				t.Fatalf("expected mount info to have uid=1000: %q", info.VfsOpts)
   218  			}
   219  			if !strings.Contains(info.VfsOpts, "size=1024k") {
   220  				t.Fatalf("expected mount info to have size=1024k: %q", info.VfsOpts)
   221  			}
   222  			break
   223  		}
   224  	}
   225  
   226  	if !found {
   227  		t.Fatal("mount not found")
   228  	}
   229  
   230  	if v.active.count != 1 {
   231  		t.Fatalf("Expected active mount count to be 1, got %d", v.active.count)
   232  	}
   233  
   234  	// test double mount
   235  	if _, err := v.Mount("1234"); err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	if v.active.count != 2 {
   239  		t.Fatalf("Expected active mount count to be 2, got %d", v.active.count)
   240  	}
   241  
   242  	if err := v.Unmount("1234"); err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	if v.active.count != 1 {
   246  		t.Fatalf("Expected active mount count to be 1, got %d", v.active.count)
   247  	}
   248  
   249  	mounted, err := mount.Mounted(v.path)
   250  	if err != nil {
   251  		t.Fatal(err)
   252  	}
   253  	if !mounted {
   254  		t.Fatal("expected mount to still be active")
   255  	}
   256  
   257  	r, err = New(rootDir, 0, 0)
   258  	if err != nil {
   259  		t.Fatal(err)
   260  	}
   261  
   262  	v2, exists := r.volumes["test"]
   263  	if !exists {
   264  		t.Fatal("missing volume on restart")
   265  	}
   266  
   267  	if !reflect.DeepEqual(v.opts, v2.opts) {
   268  		t.Fatal("missing volume options on restart")
   269  	}
   270  }
   271  
   272  func TestRealodNoOpts(t *testing.T) {
   273  	rootDir, err := ioutil.TempDir("", "volume-test-reload-no-opts")
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  	defer os.RemoveAll(rootDir)
   278  
   279  	r, err := New(rootDir, 0, 0)
   280  	if err != nil {
   281  		t.Fatal(err)
   282  	}
   283  
   284  	if _, err := r.Create("test1", nil); err != nil {
   285  		t.Fatal(err)
   286  	}
   287  	if _, err := r.Create("test2", nil); err != nil {
   288  		t.Fatal(err)
   289  	}
   290  	// make sure a file with `null` (.e.g. empty opts map from older daemon) is ok
   291  	if err := ioutil.WriteFile(filepath.Join(rootDir, "test2"), []byte("null"), 600); err != nil {
   292  		t.Fatal(err)
   293  	}
   294  
   295  	if _, err := r.Create("test3", nil); err != nil {
   296  		t.Fatal(err)
   297  	}
   298  	// make sure an empty opts file doesn't break us too
   299  	if err := ioutil.WriteFile(filepath.Join(rootDir, "test3"), nil, 600); err != nil {
   300  		t.Fatal(err)
   301  	}
   302  
   303  	if _, err := r.Create("test4", map[string]string{}); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  
   307  	r, err = New(rootDir, 0, 0)
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	for _, name := range []string{"test1", "test2", "test3", "test4"} {
   313  		v, err := r.Get(name)
   314  		if err != nil {
   315  			t.Fatal(err)
   316  		}
   317  		lv, ok := v.(*localVolume)
   318  		if !ok {
   319  			t.Fatalf("expected *localVolume got: %v", reflect.TypeOf(v))
   320  		}
   321  		if lv.opts != nil {
   322  			t.Fatalf("expected opts to be nil, got: %v", lv.opts)
   323  		}
   324  		if _, err := lv.Mount("1234"); err != nil {
   325  			t.Fatal(err)
   326  		}
   327  	}
   328  }