github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/pfsagentd/functional_test.go (about) 1 // Copyright (c) 2015-2021, NVIDIA CORPORATION. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package main 5 6 import ( 7 "bytes" 8 "io/ioutil" 9 "math" 10 "math/rand" 11 "os" 12 "testing" 13 ) 14 15 var ( 16 testFile *os.File 17 testFileContents []byte 18 testFilePath string 19 testFileLastByte byte 20 ) 21 22 func TestSimpleWriteReadClose(t *testing.T) { 23 const ( 24 testFileName = "testSimpleWriteReadCloseFileName" 25 totalBytes int64 = 100 26 randSeed int64 = 0x0123456789ABCDEF 27 ) 28 var ( 29 err error 30 readBackBuf []byte 31 writtenBuf []byte 32 ) 33 34 testSetup(t) 35 36 testFilePath = globals.config.FUSEMountPointPath + "/" + testFileName 37 38 testFile, err = os.Create(testFilePath) 39 if nil != err { 40 t.Fatalf("os.Create(\"%s\") failed: %v", testFilePath, err) 41 } 42 43 writtenBuf = make([]byte, totalBytes) 44 45 rand.Seed(randSeed) 46 47 _, _ = rand.Read(writtenBuf) 48 49 _, err = testFile.WriteAt(writtenBuf, 0) 50 if nil != err { 51 t.Fatalf("testFile.WriteAt(writtenBuf, 0) failed: %v", err) 52 } 53 54 readBackBuf = make([]byte, totalBytes) 55 56 _, err = testFile.ReadAt(readBackBuf, 0) 57 if nil != err { 58 t.Fatalf("testFile.ReadAt(readBackBuf, 0) after Sync() failed: %v", err) 59 } 60 61 if 0 != bytes.Compare(writtenBuf, readBackBuf) { 62 t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's") 63 } 64 65 err = testFile.Close() 66 if nil != err { 67 t.Fatalf("testFile.Close() failed: %v", err) 68 } 69 70 err = os.Remove(testFilePath) 71 if nil != err { 72 t.Fatalf("os.Remove(testFilePath) failed: %v", err) 73 } 74 75 testTeardown(t) 76 } 77 78 func TestRandomOverwrites(t *testing.T) { 79 const ( 80 testFileName = "testRandomeOverwritesFileName" 81 totalBytes int64 = 1000 82 minWriteSize int64 = 1 83 maxWriteSize int64 = 10 84 numWrites int64 = 10000 85 randSeed int64 = 0x0123456789ABCDEF 86 ) 87 var ( 88 err error 89 readBackBuf []byte 90 toWriteBuf []byte 91 toWriteBufLen int64 92 toWriteOffset int64 93 writeNumber int64 94 writtenBuf []byte 95 ) 96 97 testSetup(t) 98 99 testFilePath = globals.config.FUSEMountPointPath + "/" + testFileName 100 101 testFile, err = os.Create(testFilePath) 102 if nil != err { 103 t.Fatalf("os.Create(\"%s\") failed: %v", testFilePath, err) 104 } 105 106 writtenBuf = make([]byte, totalBytes) 107 108 rand.Seed(randSeed) 109 110 _, _ = rand.Read(writtenBuf) 111 112 _, err = testFile.WriteAt(writtenBuf, 0) 113 if nil != err { 114 t.Fatalf("testFile.WriteAt(writtenBuf, 0) failed: %v", err) 115 } 116 117 toWriteBuf = make([]byte, maxWriteSize) 118 119 for writeNumber = 0; writeNumber < numWrites; writeNumber++ { 120 toWriteBufLen = minWriteSize + rand.Int63n(maxWriteSize-minWriteSize+1) 121 toWriteOffset = rand.Int63n(totalBytes - toWriteBufLen + 1) 122 _, _ = rand.Read(toWriteBuf[:toWriteBufLen]) 123 124 _, err = testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset) 125 if nil != err { 126 t.Fatalf("testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset) after Create() failed: %v", err) 127 } 128 129 _ = copy(writtenBuf[toWriteOffset:(toWriteOffset+toWriteBufLen)], toWriteBuf[:toWriteBufLen]) 130 } 131 132 readBackBuf = make([]byte, totalBytes) 133 134 _, err = testFile.ReadAt(readBackBuf, 0) 135 if nil != err { 136 t.Fatalf("testFile.ReadAt(readBackBuf, 0) before Sync() failed: %v", err) 137 } 138 139 if 0 != bytes.Compare(writtenBuf, readBackBuf) { 140 t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's before Sync()") 141 } 142 143 err = testFile.Sync() 144 if nil != err { 145 t.Fatalf("testFile.Sync() after write pass 1 failed: %v", err) 146 } 147 148 _, err = testFile.ReadAt(readBackBuf, 0) 149 if nil != err { 150 t.Fatalf("testFile.ReadAt(readBackBuf, 0) after Sync() failed: %v", err) 151 } 152 153 if 0 != bytes.Compare(writtenBuf, readBackBuf) { 154 t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's after Sync()") 155 } 156 157 err = testFile.Close() 158 if nil != err { 159 t.Fatalf("testFile.Close() after Sync() failed: %v", err) 160 } 161 162 testFile, err = os.OpenFile(testFilePath, os.O_RDWR, 0) 163 if nil != err { 164 t.Fatalf("os.OpenFile(\"%s\",,) failed: %v", testFilePath, err) 165 } 166 167 _, err = testFile.ReadAt(readBackBuf, 0) 168 if nil != err { 169 t.Fatalf("testFile.ReadAt(readBackBuf, 0) after Open() failed: %v", err) 170 } 171 172 if 0 != bytes.Compare(writtenBuf, readBackBuf) { 173 t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's after Sync()") 174 } 175 176 for writeNumber = 0; writeNumber < numWrites; writeNumber++ { 177 toWriteBufLen = minWriteSize + rand.Int63n(maxWriteSize-minWriteSize+1) 178 toWriteOffset = rand.Int63n(totalBytes - toWriteBufLen + 1) 179 _, _ = rand.Read(toWriteBuf[:toWriteBufLen]) 180 181 _, err = testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset) 182 if nil != err { 183 t.Fatalf("testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset) after Open() failed: %v", err) 184 } 185 186 _ = copy(writtenBuf[toWriteOffset:(toWriteOffset+toWriteBufLen)], toWriteBuf[:toWriteBufLen]) 187 } 188 189 _, err = testFile.ReadAt(readBackBuf, 0) 190 if nil != err { 191 t.Fatalf("testFile.ReadAt(readBackBuf, 0) after overwrite failed: %v", err) 192 } 193 194 if 0 != bytes.Compare(writtenBuf, readBackBuf) { 195 t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's after overwrite") 196 } 197 198 err = testFile.Sync() 199 if nil != err { 200 t.Fatalf("testFile.Sync() after write pass 2 failed: %v", err) 201 } 202 203 err = testFile.Close() 204 if nil != err { 205 t.Fatalf("testFile.Close() after Open() failed: %v", err) 206 } 207 208 err = os.Remove(testFilePath) 209 if nil != err { 210 t.Fatalf("os.Remove(testFilePath) failed: %v", err) 211 } 212 213 testTeardown(t) 214 } 215 216 func optionallyReopenTestFile(t *testing.T, prefix string, reopenBeforeEachWrite bool, step string) { 217 var ( 218 err error 219 ) 220 221 err = testFile.Close() 222 if nil != err { 223 t.Fatalf("%s: testFile.Close() before \"%s\" failed: %v", prefix, step, err) 224 } 225 226 testFile, err = os.OpenFile(testFilePath, os.O_RDWR, 0) 227 if nil != err { 228 t.Fatalf("%s: os.OpenFile(\"%s\",,) before \"%s\" failed: %v", prefix, testFilePath, step, err) 229 } 230 } 231 232 func writeNextByteSlice(t *testing.T, prefix string, offset int, toWriteLen int, step string) { 233 var ( 234 err error 235 extension int 236 index int 237 toWriteBuf []byte 238 ) 239 240 extension = (offset + toWriteLen) - len(testFileContents) 241 242 if 0 < extension { 243 testFileContents = append(testFileContents, make([]byte, extension)...) 244 } 245 246 toWriteBuf = make([]byte, toWriteLen) 247 248 for index = 0; index < toWriteLen; index++ { 249 if math.MaxUint8 == testFileLastByte { 250 testFileLastByte = 1 251 } else { 252 testFileLastByte++ 253 } 254 toWriteBuf[index] = testFileLastByte 255 testFileContents[offset+index] = testFileLastByte 256 } 257 258 _, err = testFile.WriteAt(toWriteBuf, int64(offset)) 259 if nil != err { 260 t.Fatalf("%s: testFile.WriteAt(,0) for \"%s\" failed: %v", prefix, step, err) 261 } 262 } 263 264 func optionallyFlushTestFile(t *testing.T, prefix string, flushAfterEachWrite bool, step string) { 265 var ( 266 err error 267 ) 268 269 if flushAfterEachWrite { 270 err = testFile.Sync() 271 if nil != err { 272 t.Fatalf("%s: testFile.Sync() for \"%s\" failed: %v", prefix, step, err) 273 } 274 } 275 } 276 277 func verifyTestFileContents(t *testing.T, prefix string, step string) { 278 var ( 279 err error 280 readBackBuf []byte 281 ) 282 283 _, err = testFile.Seek(0, os.SEEK_SET) 284 if nil != err { 285 t.Fatalf("%s: testFile.Seek(0, os.SEEK_SET) for \"%s\" failed: %v", prefix, step, err) 286 } 287 readBackBuf, err = ioutil.ReadAll(testFile) 288 if nil != err { 289 t.Fatalf("%s: ioutil.ReadAll(testFile) for \"%s\" failed: %v", prefix, step, err) 290 } 291 if 0 != bytes.Compare(readBackBuf, testFileContents) { 292 t.Fatalf("%s: bytes.Compare(readBackBuf, testFileContents) for \"%s\" reports unequal bufs", prefix, step) 293 } 294 } 295 296 func testExhaustiveOverwrites(t *testing.T, prefix string, reopenBeforeEachWrite bool, flushAfterEachWrite bool) { 297 // Non-overlapping extent 298 299 optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Non-overlapping extent") 300 writeNextByteSlice(t, prefix, 0, 3, "Non-overlapping extent") 301 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Non-overlapping extent") 302 verifyTestFileContents(t, prefix, "Non-overlapping extent") 303 304 // Overlapping existing extent precisely 305 306 optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping existing extent precisely") 307 writeNextByteSlice(t, prefix, 0, 3, "Overlapping existing extent precisely") 308 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping existing extent precisely") 309 verifyTestFileContents(t, prefix, "Overlapping existing extent precisely") 310 311 // Overlapping the right of an existing extent 312 313 optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping the right of an existing extent") 314 writeNextByteSlice(t, prefix, 2, 3, "Overlapping the right of an existing extent") 315 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the right of an existing extent") 316 verifyTestFileContents(t, prefix, "Overlapping the right of an existing extent") 317 318 // Overlapping the middle of an existing extent 319 320 optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping the middle of an existing extent") 321 writeNextByteSlice(t, prefix, 1, 3, "Overlapping the middle of an existing extent") 322 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the middle of an existing extent") 323 verifyTestFileContents(t, prefix, "Overlapping the middle of an existing extent") 324 325 // Overlapping the left of an existing extent 326 327 optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping the left of an existing extent") 328 writeNextByteSlice(t, prefix, 8, 3, "Overlapping the left of an existing extent") 329 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the left of an existing extent") 330 verifyTestFileContents(t, prefix, "Overlapping the left of an existing extent") 331 writeNextByteSlice(t, prefix, 6, 3, "Overlapping the left of an existing extent") 332 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the left of an existing extent") 333 verifyTestFileContents(t, prefix, "Overlapping the left of an existing extent") 334 335 // Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left 336 337 optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left") 338 writeNextByteSlice(t, prefix, 12, 3, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left") 339 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left") 340 verifyTestFileContents(t, prefix, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left") 341 writeNextByteSlice(t, prefix, 1, 13, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left") 342 optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left") 343 verifyTestFileContents(t, prefix, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left") 344 } 345 346 func TestExhaustiveOverwrites(t *testing.T) { 347 const ( 348 testFileName = "testExhaustiveOverwritesFileName" 349 ) 350 var ( 351 err error 352 ) 353 354 testSetup(t) 355 356 testFilePath = globals.config.FUSEMountPointPath + "/" + testFileName 357 358 testFile, err = os.Create(testFilePath) 359 if nil != err { 360 t.Fatalf("os.Create(\"%s\") failed: %v", testFilePath, err) 361 } 362 err = testFile.Close() 363 if nil != err { 364 t.Fatalf("testFile.Close() failed: %v", err) 365 } 366 testFile, err = os.OpenFile(testFilePath, os.O_RDWR, 0) 367 if nil != err { 368 t.Fatalf("os.OpenFile(\"%s\",,) failed: %v", testFilePath, err) 369 } 370 371 testFileContents = []byte{} 372 373 testExhaustiveOverwrites(t, "Phase1", false, false) 374 testExhaustiveOverwrites(t, "Phase2", false, true) 375 testExhaustiveOverwrites(t, "Phase2", true, false) 376 testExhaustiveOverwrites(t, "Phase2", true, true) 377 378 err = testFile.Close() 379 if nil != err { 380 t.Fatalf("testFile.Close() failed: %v", err) 381 } 382 383 err = os.Remove(testFilePath) 384 if nil != err { 385 t.Fatalf("os.Remove(testFilePath) failed: %v", err) 386 } 387 388 testTeardown(t) 389 }