github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/inode/dir_stress_test.go (about) 1 package inode 2 3 import ( 4 "fmt" 5 "sync" 6 "testing" 7 "time" 8 9 "github.com/swiftstack/ProxyFS/headhunter" 10 "github.com/swiftstack/ProxyFS/trackedlock" 11 ) 12 13 const ( 14 testDirStressBasenamePrefix = "__TestDirStress_" // To be appended with Nonce + "_" + ThreadIndex + "_" + LinkIndex (for this Thread) 15 16 testDirStressDelayBetweenLinkAndUnlink time.Duration = 1 * time.Microsecond 17 testDirStressDelayBetweenThreadStarts time.Duration = 1 * time.Microsecond 18 19 testDirStressNumIterations uint64 = 3 20 testDirStressNumLinksPerIteration uint64 = 3 21 testDirStressNumThreads uint64 = 30 22 23 testDirStressVolumeName = "TestVolume" 24 ) 25 26 type testDirStressGlobalsStruct struct { 27 trackedlock.Mutex // Used to emulate the exclusive lock used in package fs on RootDirInodeNumber 28 nonce uint64 29 waitGroup sync.WaitGroup 30 err []error 31 } 32 33 var testDirStressGlobals = &testDirStressGlobalsStruct{} 34 35 func TestDirStressWhileStarved(t *testing.T) { 36 testDirStress(t, true) 37 } 38 39 func TestDirStressWhileNotStarved(t *testing.T) { 40 testDirStress(t, false) 41 } 42 43 func testDirStress(t *testing.T, starvationMode bool) { 44 var ( 45 err error 46 headhunterVolumeHandle headhunter.VolumeHandle 47 threadIndex uint64 48 ) 49 50 testSetup(t, starvationMode) 51 52 headhunterVolumeHandle, err = headhunter.FetchVolumeHandle(testDirStressVolumeName) 53 if nil != err { 54 t.Fatalf("headhunter.FetchVolumeHandle(\"%s\") failed: %v", testDirStressVolumeName, err) 55 } 56 57 testDirStressGlobals.nonce = headhunterVolumeHandle.FetchNonce() 58 59 testDirStressGlobals.waitGroup.Add(int(testDirStressNumThreads)) 60 61 testDirStressGlobals.err = make([]error, testDirStressNumThreads) 62 63 for threadIndex = uint64(0); threadIndex < testDirStressNumThreads; threadIndex++ { 64 time.Sleep(testDirStressDelayBetweenThreadStarts) 65 66 go testDirStressThread(threadIndex) 67 } 68 69 testDirStressGlobals.waitGroup.Wait() 70 71 for _, err = range testDirStressGlobals.err { 72 if nil != err { 73 t.Fatal(err) 74 } 75 } 76 77 testTeardown(t) 78 } 79 80 func testDirStressThread(threadIndex uint64) { 81 var ( 82 basename string 83 err error 84 fileInodeNumber InodeNumber 85 iteration uint64 86 linkIndex uint64 87 volumeHandle VolumeHandle 88 ) 89 90 defer testDirStressGlobals.waitGroup.Done() 91 92 volumeHandle, err = FetchVolumeHandle(testDirStressVolumeName) 93 if nil != err { 94 testDirStressGlobals.Lock() 95 testDirStressGlobals.err[threadIndex] = fmt.Errorf("FetchVolumeHandle(\"%s\") failed: %v", testDirStressVolumeName, err) 96 testDirStressGlobals.Unlock() 97 return 98 } 99 100 for iteration = uint64(0); iteration < testDirStressNumIterations; iteration++ { 101 fileInodeNumber, err = volumeHandle.CreateFile(PosixModePerm, InodeUserID(0), InodeGroupID(0)) 102 if nil != err { 103 testDirStressGlobals.Lock() 104 testDirStressGlobals.err[threadIndex] = fmt.Errorf("volumeHandle.CreateFile(PosixModePerm, InodeUserID(0), InodeGroupID(0)) failed: %v", err) 105 testDirStressGlobals.Unlock() 106 return 107 } 108 109 for linkIndex = uint64(0); linkIndex < testDirStressNumLinksPerIteration; linkIndex++ { 110 basename = fmt.Sprintf("%s%016X_%016X_%016X", testDirStressBasenamePrefix, testDirStressGlobals.nonce, threadIndex, linkIndex) 111 112 testDirStressGlobals.Lock() 113 err = volumeHandle.Link(RootDirInodeNumber, basename, fileInodeNumber, false) 114 if nil != err { 115 testDirStressGlobals.err[threadIndex] = fmt.Errorf("volumeHandle.Link(RootDirInodeNumber, \"%s\", fileInodeNumber, false) failed: %v", basename, err) 116 testDirStressGlobals.Unlock() 117 return 118 } 119 testDirStressGlobals.Unlock() 120 121 time.Sleep(testDirStressDelayBetweenLinkAndUnlink) 122 123 testDirStressGlobals.Lock() 124 err = volumeHandle.Unlink(RootDirInodeNumber, basename, false) 125 if nil != err { 126 testDirStressGlobals.err[threadIndex] = fmt.Errorf("volumeHandle.Unlink(RootDirInodeNumber, \"%s\", false) failed: %v", basename, err) 127 testDirStressGlobals.Unlock() 128 return 129 } 130 testDirStressGlobals.Unlock() 131 } 132 133 err = volumeHandle.Destroy(fileInodeNumber) 134 if nil != err { 135 testDirStressGlobals.Lock() 136 testDirStressGlobals.err[threadIndex] = fmt.Errorf("volumeHandle.Destroy(fileInodeNumber) failed: %v", err) 137 testDirStressGlobals.Unlock() 138 return 139 } 140 } 141 142 testDirStressGlobals.Lock() 143 testDirStressGlobals.err[threadIndex] = nil 144 testDirStressGlobals.Unlock() 145 }