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