10 type TrashWorkerTestData struct {
32 /* Delete block that does not exist in any of the keep volumes.
35 func TestTrashWorkerIntegration_GetNonExistingLocator(t *testing.T) {
36 theConfig.EnableDelete = true
37 testData := TrashWorkerTestData{
38 Locator1: "5d41402abc4b2a76b9719d911017c592",
39 Block1: []byte("hello"),
41 Locator2: "5d41402abc4b2a76b9719d911017c592",
42 Block2: []byte("hello"),
46 DeleteLocator: "5d41402abc4b2a76b9719d911017c592",
48 ExpectLocator1: false,
49 ExpectLocator2: false,
51 performTrashWorkerTest(testData, t)
54 /* Delete a block that exists on volume 1 of the keep servers.
55 Expect the second locator in volume 2 to be unaffected.
57 func TestTrashWorkerIntegration_LocatorInVolume1(t *testing.T) {
58 theConfig.EnableDelete = true
59 testData := TrashWorkerTestData{
68 DeleteLocator: TestHash, // first locator
70 ExpectLocator1: false,
73 performTrashWorkerTest(testData, t)
76 /* Delete a block that exists on volume 2 of the keep servers.
77 Expect the first locator in volume 1 to be unaffected.
79 func TestTrashWorkerIntegration_LocatorInVolume2(t *testing.T) {
80 theConfig.EnableDelete = true
81 testData := TrashWorkerTestData{
90 DeleteLocator: TestHash2, // locator 2
93 ExpectLocator2: false,
95 performTrashWorkerTest(testData, t)
98 /* Delete a block with matching mtime for locator in both volumes.
99 Expect locator to be deleted from both volumes.
101 func TestTrashWorkerIntegration_LocatorInBothVolumes(t *testing.T) {
102 theConfig.EnableDelete = true
103 testData := TrashWorkerTestData{
112 DeleteLocator: TestHash,
114 ExpectLocator1: false,
115 ExpectLocator2: false,
117 performTrashWorkerTest(testData, t)
120 /* Same locator with different Mtimes exists in both volumes.
121 Delete the second and expect the first to be still around.
123 func TestTrashWorkerIntegration_MtimeMatchesForLocator1ButNotForLocator2(t *testing.T) {
124 theConfig.EnableDelete = true
125 testData := TrashWorkerTestData{
133 DifferentMtimes: true,
135 DeleteLocator: TestHash,
137 ExpectLocator1: true,
138 ExpectLocator2: false,
140 performTrashWorkerTest(testData, t)
143 // Delete a block that exists on both volumes with matching mtimes,
144 // but specify a MountUUID in the request so it only gets deleted from
146 func TestTrashWorkerIntegration_SpecifyMountUUID(t *testing.T) {
147 theConfig.EnableDelete = true
148 testData := TrashWorkerTestData{
157 DeleteLocator: TestHash,
158 SpecifyMountUUID: true,
160 ExpectLocator1: true,
161 ExpectLocator2: true,
163 performTrashWorkerTest(testData, t)
166 /* Two different locators in volume 1.
168 Expect the other unaffected.
170 func TestTrashWorkerIntegration_TwoDifferentLocatorsInVolume1(t *testing.T) {
171 theConfig.EnableDelete = true
172 testData := TrashWorkerTestData{
180 CreateInVolume1: true,
182 DeleteLocator: TestHash, // locator 1
184 ExpectLocator1: false,
185 ExpectLocator2: true,
187 performTrashWorkerTest(testData, t)
190 /* Allow default Trash Life time to be used. Thus, the newly created block
191 will not be deleted because its Mtime is within the trash life time.
193 func TestTrashWorkerIntegration_SameLocatorInTwoVolumesWithDefaultTrashLifeTime(t *testing.T) {
194 theConfig.EnableDelete = true
195 testData := TrashWorkerTestData{
203 CreateInVolume1: true,
205 UseTrashLifeTime: true,
207 DeleteLocator: TestHash, // locator 1
209 // Since trash life time is in effect, block won't be deleted.
210 ExpectLocator1: true,
211 ExpectLocator2: true,
213 performTrashWorkerTest(testData, t)
216 /* Delete a block with matching mtime for locator in both volumes, but EnableDelete is false,
217 so block won't be deleted.
219 func TestTrashWorkerIntegration_DisabledDelete(t *testing.T) {
220 theConfig.EnableDelete = false
221 testData := TrashWorkerTestData{
230 DeleteLocator: TestHash,
232 ExpectLocator1: true,
233 ExpectLocator2: true,
235 performTrashWorkerTest(testData, t)
238 /* Perform the test */
239 func performTrashWorkerTest(testData TrashWorkerTestData, t *testing.T) {
240 // Create Keep Volumes
241 KeepVM = MakeTestVolumeManager(2)
245 vols := KeepVM.AllWritable()
246 if testData.CreateData {
247 vols[0].Put(context.Background(), testData.Locator1, testData.Block1)
248 vols[0].Put(context.Background(), testData.Locator1+".meta", []byte("metadata"))
250 if testData.CreateInVolume1 {
251 vols[0].Put(context.Background(), testData.Locator2, testData.Block2)
252 vols[0].Put(context.Background(), testData.Locator2+".meta", []byte("metadata"))
254 vols[1].Put(context.Background(), testData.Locator2, testData.Block2)
255 vols[1].Put(context.Background(), testData.Locator2+".meta", []byte("metadata"))
259 oldBlockTime := time.Now().Add(-theConfig.BlobSignatureTTL.Duration() - time.Minute)
261 // Create TrashRequest for the test
262 trashRequest := TrashRequest{
263 Locator: testData.DeleteLocator,
264 BlockMtime: oldBlockTime.UnixNano(),
266 if testData.SpecifyMountUUID {
267 trashRequest.MountUUID = KeepVM.Mounts()[0].UUID
270 // Run trash worker and put the trashRequest on trashq
271 trashList := list.New()
272 trashList.PushBack(trashRequest)
273 trashq = NewWorkQueue()
276 if !testData.UseTrashLifeTime {
277 // Trash worker would not delete block if its Mtime is
278 // within trash life time. Back-date the block to
279 // allow the deletion to succeed.
280 for _, v := range vols {
281 v.(*MockVolume).Timestamps[testData.DeleteLocator] = oldBlockTime
282 if testData.DifferentMtimes {
283 oldBlockTime = oldBlockTime.Add(time.Second)
287 go RunTrashWorker(trashq)
289 // Install gate so all local operations block until we say go
290 gate := make(chan struct{})
291 for _, v := range vols {
292 v.(*MockVolume).Gate = gate
295 assertStatusItem := func(k string, expect float64) {
296 if v := getStatusItem("TrashQueue", k); v != expect {
297 t.Errorf("Got %s %v, expected %v", k, v, expect)
301 assertStatusItem("InProgress", 0)
302 assertStatusItem("Queued", 0)
304 listLen := trashList.Len()
305 trashq.ReplaceQueue(trashList)
307 // Wait for worker to take request(s)
308 expectEqualWithin(t, time.Second, listLen, func() interface{} { return trashq.Status().InProgress })
310 // Ensure status.json also reports work is happening
311 assertStatusItem("InProgress", float64(1))
312 assertStatusItem("Queued", float64(listLen-1))
314 // Let worker proceed
317 // Wait for worker to finish
318 expectEqualWithin(t, time.Second, 0, func() interface{} { return trashq.Status().InProgress })
320 // Verify Locator1 to be un/deleted as expected
321 buf := make([]byte, BlockSize)
322 size, err := GetBlock(context.Background(), testData.Locator1, buf, nil)
323 if testData.ExpectLocator1 {
324 if size == 0 || err != nil {
325 t.Errorf("Expected Locator1 to be still present: %s", testData.Locator1)
328 if size > 0 || err == nil {
329 t.Errorf("Expected Locator1 to be deleted: %s", testData.Locator1)
333 // Verify Locator2 to be un/deleted as expected
334 if testData.Locator1 != testData.Locator2 {
335 size, err = GetBlock(context.Background(), testData.Locator2, buf, nil)
336 if testData.ExpectLocator2 {
337 if size == 0 || err != nil {
338 t.Errorf("Expected Locator2 to be still present: %s", testData.Locator2)
341 if size > 0 || err == nil {
342 t.Errorf("Expected Locator2 to be deleted: %s", testData.Locator2)
347 // The DifferentMtimes test puts the same locator in two
348 // different volumes, but only one copy has an Mtime matching
349 // the trash request.
350 if testData.DifferentMtimes {
352 for _, volume := range KeepVM.AllReadable() {
353 buf := make([]byte, BlockSize)
354 if _, err := volume.Get(context.Background(), testData.Locator1, buf); err == nil {
355 locatorFoundIn = locatorFoundIn + 1
358 if locatorFoundIn != 1 {
359 t.Errorf("Found %d copies of %s, expected 1", locatorFoundIn, testData.Locator1)