github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/volume/service/store_test.go (about) 1 package service // import "github.com/docker/docker/volume/service" 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net" 8 "os" 9 "strings" 10 "testing" 11 12 "github.com/docker/docker/volume" 13 volumedrivers "github.com/docker/docker/volume/drivers" 14 "github.com/docker/docker/volume/service/opts" 15 volumetestutils "github.com/docker/docker/volume/testutils" 16 "github.com/google/go-cmp/cmp" 17 "gotest.tools/v3/assert" 18 is "gotest.tools/v3/assert/cmp" 19 ) 20 21 func TestCreate(t *testing.T) { 22 t.Parallel() 23 24 s, cleanup := setupTest(t) 25 defer cleanup() 26 s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake") 27 28 ctx := context.Background() 29 v, err := s.Create(ctx, "fake1", "fake") 30 if err != nil { 31 t.Fatal(err) 32 } 33 if v.Name() != "fake1" { 34 t.Fatalf("Expected fake1 volume, got %v", v) 35 } 36 if l, _, _ := s.Find(ctx, nil); len(l) != 1 { 37 t.Fatalf("Expected 1 volume in the store, got %v: %v", len(l), l) 38 } 39 40 if _, err := s.Create(ctx, "none", "none"); err == nil { 41 t.Fatalf("Expected unknown driver error, got nil") 42 } 43 44 _, err = s.Create(ctx, "fakeerror", "fake", opts.WithCreateOptions(map[string]string{"error": "create error"})) 45 expected := &OpErr{Op: "create", Name: "fakeerror", Err: errors.New("create error")} 46 if err != nil && err.Error() != expected.Error() { 47 t.Fatalf("Expected create fakeError: create error, got %v", err) 48 } 49 } 50 51 func TestRemove(t *testing.T) { 52 t.Parallel() 53 54 s, cleanup := setupTest(t) 55 defer cleanup() 56 57 s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake") 58 s.drivers.Register(volumetestutils.NewFakeDriver("noop"), "noop") 59 60 ctx := context.Background() 61 62 // doing string compare here since this error comes directly from the driver 63 expected := "no such volume" 64 var v volume.Volume = volumetestutils.NoopVolume{} 65 if err := s.Remove(ctx, v); err == nil || !strings.Contains(err.Error(), expected) { 66 t.Fatalf("Expected error %q, got %v", expected, err) 67 } 68 69 v, err := s.Create(ctx, "fake1", "fake", opts.WithCreateReference("fake")) 70 if err != nil { 71 t.Fatal(err) 72 } 73 74 if err := s.Remove(ctx, v); !IsInUse(err) { 75 t.Fatalf("Expected ErrVolumeInUse error, got %v", err) 76 } 77 s.Release(ctx, v.Name(), "fake") 78 if err := s.Remove(ctx, v); err != nil { 79 t.Fatal(err) 80 } 81 if l, _, _ := s.Find(ctx, nil); len(l) != 0 { 82 t.Fatalf("Expected 0 volumes in the store, got %v, %v", len(l), l) 83 } 84 } 85 86 func TestList(t *testing.T) { 87 t.Parallel() 88 89 dir, err := os.MkdirTemp("", "test-list") 90 assert.NilError(t, err) 91 defer os.RemoveAll(dir) 92 93 drivers := volumedrivers.NewStore(nil) 94 drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake") 95 drivers.Register(volumetestutils.NewFakeDriver("fake2"), "fake2") 96 97 s, err := NewStore(dir, drivers) 98 assert.NilError(t, err) 99 100 ctx := context.Background() 101 if _, err := s.Create(ctx, "test", "fake"); err != nil { 102 t.Fatal(err) 103 } 104 if _, err := s.Create(ctx, "test2", "fake2"); err != nil { 105 t.Fatal(err) 106 } 107 108 ls, _, err := s.Find(ctx, nil) 109 if err != nil { 110 t.Fatal(err) 111 } 112 if len(ls) != 2 { 113 t.Fatalf("expected 2 volumes, got: %d", len(ls)) 114 } 115 if err := s.Shutdown(); err != nil { 116 t.Fatal(err) 117 } 118 119 // and again with a new store 120 s, err = NewStore(dir, drivers) 121 if err != nil { 122 t.Fatal(err) 123 } 124 ls, _, err = s.Find(ctx, nil) 125 if err != nil { 126 t.Fatal(err) 127 } 128 if len(ls) != 2 { 129 t.Fatalf("expected 2 volumes, got: %d", len(ls)) 130 } 131 } 132 133 func TestFindByDriver(t *testing.T) { 134 t.Parallel() 135 s, cleanup := setupTest(t) 136 defer cleanup() 137 138 assert.Assert(t, s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake")) 139 assert.Assert(t, s.drivers.Register(volumetestutils.NewFakeDriver("noop"), "noop")) 140 141 ctx := context.Background() 142 _, err := s.Create(ctx, "fake1", "fake") 143 assert.NilError(t, err) 144 145 _, err = s.Create(ctx, "fake2", "fake") 146 assert.NilError(t, err) 147 148 _, err = s.Create(ctx, "fake3", "noop") 149 assert.NilError(t, err) 150 151 l, _, err := s.Find(ctx, ByDriver("fake")) 152 assert.NilError(t, err) 153 assert.Equal(t, len(l), 2) 154 155 l, _, err = s.Find(ctx, ByDriver("noop")) 156 assert.NilError(t, err) 157 assert.Equal(t, len(l), 1) 158 159 l, _, err = s.Find(ctx, ByDriver("nosuchdriver")) 160 assert.NilError(t, err) 161 assert.Equal(t, len(l), 0) 162 } 163 164 func TestFindByReferenced(t *testing.T) { 165 t.Parallel() 166 s, cleanup := setupTest(t) 167 defer cleanup() 168 169 s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake") 170 s.drivers.Register(volumetestutils.NewFakeDriver("noop"), "noop") 171 172 ctx := context.Background() 173 if _, err := s.Create(ctx, "fake1", "fake", opts.WithCreateReference("volReference")); err != nil { 174 t.Fatal(err) 175 } 176 if _, err := s.Create(ctx, "fake2", "fake"); err != nil { 177 t.Fatal(err) 178 } 179 180 dangling, _, err := s.Find(ctx, ByReferenced(false)) 181 assert.NilError(t, err) 182 assert.Assert(t, len(dangling) == 1) 183 assert.Check(t, dangling[0].Name() == "fake2") 184 185 used, _, err := s.Find(ctx, ByReferenced(true)) 186 assert.NilError(t, err) 187 assert.Assert(t, len(used) == 1) 188 assert.Check(t, used[0].Name() == "fake1") 189 } 190 191 func TestDerefMultipleOfSameRef(t *testing.T) { 192 t.Parallel() 193 s, cleanup := setupTest(t) 194 defer cleanup() 195 s.drivers.Register(volumetestutils.NewFakeDriver("fake"), "fake") 196 197 ctx := context.Background() 198 v, err := s.Create(ctx, "fake1", "fake", opts.WithCreateReference("volReference")) 199 if err != nil { 200 t.Fatal(err) 201 } 202 203 if _, err := s.Get(ctx, "fake1", opts.WithGetDriver("fake"), opts.WithGetReference("volReference")); err != nil { 204 t.Fatal(err) 205 } 206 207 s.Release(ctx, v.Name(), "volReference") 208 if err := s.Remove(ctx, v); err != nil { 209 t.Fatal(err) 210 } 211 } 212 213 func TestCreateKeepOptsLabelsWhenExistsRemotely(t *testing.T) { 214 t.Parallel() 215 s, cleanup := setupTest(t) 216 defer cleanup() 217 218 vd := volumetestutils.NewFakeDriver("fake") 219 s.drivers.Register(vd, "fake") 220 221 // Create a volume in the driver directly 222 if _, err := vd.Create("foo", nil); err != nil { 223 t.Fatal(err) 224 } 225 226 ctx := context.Background() 227 v, err := s.Create(ctx, "foo", "fake", opts.WithCreateLabels(map[string]string{"hello": "world"})) 228 if err != nil { 229 t.Fatal(err) 230 } 231 232 switch dv := v.(type) { 233 case volume.DetailedVolume: 234 if dv.Labels()["hello"] != "world" { 235 t.Fatalf("labels don't match") 236 } 237 default: 238 t.Fatalf("got unexpected type: %T", v) 239 } 240 } 241 242 func TestDefererencePluginOnCreateError(t *testing.T) { 243 t.Parallel() 244 245 var ( 246 l net.Listener 247 err error 248 ) 249 250 for i := 32768; l == nil && i < 40000; i++ { 251 l, err = net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", i)) 252 } 253 if l == nil { 254 t.Fatalf("could not create listener: %v", err) 255 } 256 defer l.Close() 257 258 s, cleanup := setupTest(t) 259 defer cleanup() 260 261 d := volumetestutils.NewFakeDriver("TestDefererencePluginOnCreateError") 262 p, err := volumetestutils.MakeFakePlugin(d, l) 263 if err != nil { 264 t.Fatal(err) 265 } 266 267 pg := volumetestutils.NewFakePluginGetter(p) 268 s.drivers = volumedrivers.NewStore(pg) 269 270 ctx := context.Background() 271 // create a good volume so we have a plugin reference 272 _, err = s.Create(ctx, "fake1", d.Name()) 273 if err != nil { 274 t.Fatal(err) 275 } 276 277 // Now create another one expecting an error 278 _, err = s.Create(ctx, "fake2", d.Name(), opts.WithCreateOptions(map[string]string{"error": "some error"})) 279 if err == nil || !strings.Contains(err.Error(), "some error") { 280 t.Fatalf("expected an error on create: %v", err) 281 } 282 283 // There should be only 1 plugin reference 284 if refs := volumetestutils.FakeRefs(p); refs != 1 { 285 t.Fatalf("expected 1 plugin reference, got: %d", refs) 286 } 287 } 288 289 func TestRefDerefRemove(t *testing.T) { 290 t.Parallel() 291 292 driverName := "test-ref-deref-remove" 293 s, cleanup := setupTest(t) 294 defer cleanup() 295 s.drivers.Register(volumetestutils.NewFakeDriver(driverName), driverName) 296 297 ctx := context.Background() 298 v, err := s.Create(ctx, "test", driverName, opts.WithCreateReference("test-ref")) 299 assert.NilError(t, err) 300 301 err = s.Remove(ctx, v) 302 assert.Assert(t, is.ErrorContains(err, "")) 303 assert.Equal(t, errVolumeInUse, err.(*OpErr).Err) 304 305 s.Release(ctx, v.Name(), "test-ref") 306 err = s.Remove(ctx, v) 307 assert.NilError(t, err) 308 } 309 310 func TestGet(t *testing.T) { 311 t.Parallel() 312 313 driverName := "test-get" 314 s, cleanup := setupTest(t) 315 defer cleanup() 316 s.drivers.Register(volumetestutils.NewFakeDriver(driverName), driverName) 317 318 ctx := context.Background() 319 _, err := s.Get(ctx, "not-exist") 320 assert.Assert(t, is.ErrorContains(err, "")) 321 assert.Equal(t, errNoSuchVolume, err.(*OpErr).Err) 322 323 v1, err := s.Create(ctx, "test", driverName, opts.WithCreateLabels(map[string]string{"a": "1"})) 324 assert.NilError(t, err) 325 326 v2, err := s.Get(ctx, "test") 327 assert.NilError(t, err) 328 assert.DeepEqual(t, v1, v2, cmpVolume) 329 330 dv := v2.(volume.DetailedVolume) 331 assert.Equal(t, "1", dv.Labels()["a"]) 332 333 err = s.Remove(ctx, v1) 334 assert.NilError(t, err) 335 } 336 337 func TestGetWithReference(t *testing.T) { 338 t.Parallel() 339 340 driverName := "test-get-with-ref" 341 s, cleanup := setupTest(t) 342 defer cleanup() 343 s.drivers.Register(volumetestutils.NewFakeDriver(driverName), driverName) 344 345 ctx := context.Background() 346 _, err := s.Get(ctx, "not-exist", opts.WithGetDriver(driverName), opts.WithGetReference("test-ref")) 347 assert.Assert(t, is.ErrorContains(err, "")) 348 349 v1, err := s.Create(ctx, "test", driverName, opts.WithCreateLabels(map[string]string{"a": "1"})) 350 assert.NilError(t, err) 351 352 v2, err := s.Get(ctx, "test", opts.WithGetDriver(driverName), opts.WithGetReference("test-ref")) 353 assert.NilError(t, err) 354 assert.DeepEqual(t, v1, v2, cmpVolume) 355 356 err = s.Remove(ctx, v2) 357 assert.Assert(t, is.ErrorContains(err, "")) 358 assert.Equal(t, errVolumeInUse, err.(*OpErr).Err) 359 360 s.Release(ctx, v2.Name(), "test-ref") 361 err = s.Remove(ctx, v2) 362 assert.NilError(t, err) 363 } 364 365 var cmpVolume = cmp.AllowUnexported(volumetestutils.FakeVolume{}, volumeWrapper{}) 366 367 func setupTest(t *testing.T) (*VolumeStore, func()) { 368 t.Helper() 369 370 dirName := strings.Replace(t.Name(), string(os.PathSeparator), "_", -1) 371 dir, err := os.MkdirTemp("", dirName) 372 assert.NilError(t, err) 373 374 cleanup := func() { 375 t.Helper() 376 err := os.RemoveAll(dir) 377 assert.Check(t, err) 378 } 379 380 s, err := NewStore(dir, volumedrivers.NewStore(nil)) 381 assert.Check(t, err) 382 return s, func() { 383 s.Shutdown() 384 cleanup() 385 } 386 } 387 388 func TestFilterFunc(t *testing.T) { 389 testDriver := volumetestutils.NewFakeDriver("test") 390 testVolume, err := testDriver.Create("test", nil) 391 assert.NilError(t, err) 392 testVolume2, err := testDriver.Create("test2", nil) 393 assert.NilError(t, err) 394 testVolume3, err := testDriver.Create("test3", nil) 395 assert.NilError(t, err) 396 397 for _, test := range []struct { 398 vols []volume.Volume 399 fn filterFunc 400 desc string 401 expect []volume.Volume 402 }{ 403 {desc: "test nil list", vols: nil, expect: nil, fn: func(volume.Volume) bool { return true }}, 404 {desc: "test empty list", vols: []volume.Volume{}, expect: []volume.Volume{}, fn: func(volume.Volume) bool { return true }}, 405 {desc: "test filter non-empty to empty", vols: []volume.Volume{testVolume}, expect: []volume.Volume{}, fn: func(volume.Volume) bool { return false }}, 406 {desc: "test nothing to fitler non-empty list", vols: []volume.Volume{testVolume}, expect: []volume.Volume{testVolume}, fn: func(volume.Volume) bool { return true }}, 407 {desc: "test filter some", vols: []volume.Volume{testVolume, testVolume2}, expect: []volume.Volume{testVolume}, fn: func(v volume.Volume) bool { return v.Name() == testVolume.Name() }}, 408 {desc: "test filter middle", vols: []volume.Volume{testVolume, testVolume2, testVolume3}, expect: []volume.Volume{testVolume, testVolume3}, fn: func(v volume.Volume) bool { return v.Name() != testVolume2.Name() }}, 409 {desc: "test filter middle and last", vols: []volume.Volume{testVolume, testVolume2, testVolume3}, expect: []volume.Volume{testVolume}, fn: func(v volume.Volume) bool { return v.Name() != testVolume2.Name() && v.Name() != testVolume3.Name() }}, 410 {desc: "test filter first and last", vols: []volume.Volume{testVolume, testVolume2, testVolume3}, expect: []volume.Volume{testVolume2}, fn: func(v volume.Volume) bool { return v.Name() != testVolume.Name() && v.Name() != testVolume3.Name() }}, 411 } { 412 t.Run(test.desc, func(t *testing.T) { 413 test := test 414 t.Parallel() 415 416 filter(&test.vols, test.fn) 417 assert.DeepEqual(t, test.vols, test.expect, cmpVolume) 418 }) 419 } 420 }