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 }