github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/volume/local/local_test.go (about)

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