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