github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/inode/gc_test.go (about) 1 package inode 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/swiftstack/ProxyFS/swiftclient" 8 ) 9 10 type testObjectLocationStruct struct { 11 accountName string 12 containerName string 13 objectName string 14 } 15 16 func TestEmptySegmentDeletion(t *testing.T) { 17 testSetup(t, false) 18 19 testVolumeHandle, err := FetchVolumeHandle("TestVolume") 20 if nil != err { 21 t.Fatalf("FetchVolumeHandle(\"TestVolume\") failed: %v", err) 22 } 23 24 volume := testVolumeHandle.(*volumeStruct) 25 26 ino, err := testVolumeHandle.CreateFile(PosixModePerm, 0, 0) 27 if nil != err { 28 t.Fatalf("CreateFile() failed: %v", err) 29 } 30 31 // '$$$$$$$$$$$$$$$$' 32 ourBytes := []byte{0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24} 33 34 // repeatedly write and flush to create some log segments 35 for i := 0; i < 5; i++ { 36 err := testVolumeHandle.Write(ino, uint64(i*16), ourBytes, nil) 37 if err != nil { 38 t.Fatalf("failed to write: %v", err) 39 } 40 41 err = testVolumeHandle.Flush(ino, false) 42 if err != nil { 43 t.Fatalf("failed to flush: %v", err) 44 } 45 } 46 47 // inspect log segment map 48 ourInode, ok, err := volume.fetchInode(ino) 49 if nil != err { 50 t.Fatalf("fetchInode(ino==0x%016X) failed: %v", ino, err) 51 } 52 if !ok { 53 t.Fatalf("fetchInode(ino==0x%016X) returned !ok", ino) 54 } 55 segmentNumbers := make([]uint64, 0, 5) 56 segmentObjectLocations := make([]testObjectLocationStruct, 0, 5) 57 for segmentNumber := range ourInode.LogSegmentMap { 58 segmentNumbers = append(segmentNumbers, segmentNumber) 59 containerName, objectName, _, getObjectLocationErr := volume.getObjectLocationFromLogSegmentNumber(segmentNumber) 60 if nil != getObjectLocationErr { 61 t.Fatalf("expected to be able to get log segment 0x%016X", segmentNumber) 62 } 63 segmentObjectLocations = append(segmentObjectLocations, testObjectLocationStruct{volume.accountName, containerName, objectName}) 64 } 65 66 // overwrite it 67 err = testVolumeHandle.Write(ino, 0, make([]byte, 16*5), nil) 68 if err != nil { 69 t.Fatalf("expected to be able to write to inode #%v", ino) 70 } 71 err = testVolumeHandle.Flush(ino, false) 72 if err != nil { 73 t.Fatalf("expected to be able to flush inode #%v", ino) 74 } 75 76 // wait for headhunter checkpoint which blocks deletes 77 err = volume.headhunterVolumeHandle.DoCheckpoint() 78 if nil != err { 79 t.Errorf("expected volume.headhunterVolumeHandle.DoCheckpoint() to succeed: got %v", err) 80 } 81 82 // the deletions are async; give them a (literal) second 83 time.Sleep(1 * time.Second) 84 85 for _, deletedSegmentNumber := range segmentNumbers { 86 _, getLogSegmentContainerErr := volume.getLogSegmentContainer(deletedSegmentNumber) 87 if getLogSegmentContainerErr == nil { 88 t.Errorf("expected volume.getLogSegmentContainer() to fail for allegedly-deleted log segment 0x%016X", deletedSegmentNumber) 89 } 90 } 91 92 // the headhunter records got deleted, and ... 93 for _, segmentObjectLocation := range segmentObjectLocations { 94 var objectContentLengthErr error 95 96 // wait for up to 20 sec for the object to be (async) deleted 97 for try := 0; try < 20; try++ { 98 _, objectContentLengthErr = swiftclient.ObjectContentLength(segmentObjectLocation.accountName, segmentObjectLocation.containerName, segmentObjectLocation.objectName) 99 //t.Logf("verifying object delete for %v/%v try %d err '%v'\n", segmentObjectLocation.containerName, segmentObjectLocation.objectName, try, objectContentLengthErr) 100 if objectContentLengthErr != nil { 101 break 102 } 103 time.Sleep(time.Second) 104 } 105 if objectContentLengthErr == nil { 106 t.Errorf("expected ObjectContentLength() to fail for allegedly-deleted log segment object at %s/%s/%s", segmentObjectLocation.accountName, segmentObjectLocation.containerName, segmentObjectLocation.objectName) 107 } 108 } 109 // the underlying log segment objects got deleted!! Yaaay~! ☆✦❤ 110 111 testTeardown(t) 112 }