github.com/MaximeAubanel/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 }