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