@@ -366,17 +366,18 @@ class FaultyFsTest : public ::testing::Test {
366
366
fs_ = std::dynamic_pointer_cast<tests::utils::FaultyFileSystem>(
367
367
filesystems::getFileSystem (dir_->getPath (), {}));
368
368
VELOX_CHECK_NOT_NULL (fs_);
369
- filePath_ = fmt::format (" {}/faultyTestFile" , dir_->getPath ());
369
+ readFilePath_ = fmt::format (" {}/faultyTestReadFile" , dir_->getPath ());
370
+ writeFilePath_ = fmt::format (" {}/faultyTestWriteFile" , dir_->getPath ());
370
371
const int bufSize = 1024 ;
371
372
buffer_.resize (bufSize);
372
373
for (int i = 0 ; i < bufSize; ++i) {
373
374
buffer_[i] = i % 256 ;
374
375
}
375
376
{
376
- auto writeFile = fs_->openFileForWrite (filePath_ , {});
377
+ auto writeFile = fs_->openFileForWrite (readFilePath_ , {});
377
378
writeData (writeFile.get ());
378
379
}
379
- auto readFile = fs_->openFileForRead (filePath_ , {});
380
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
380
381
readData (readFile.get (), true );
381
382
try {
382
383
VELOX_FAIL (" InjectedFaultFileError" );
@@ -411,7 +412,8 @@ class FaultyFsTest : public ::testing::Test {
411
412
}
412
413
413
414
std::shared_ptr<exec::test::TempDirectoryPath> dir_;
414
- std::string filePath_;
415
+ std::string readFilePath_;
416
+ std::string writeFilePath_;
415
417
std::shared_ptr<tests::utils::FaultyFileSystem> fs_;
416
418
std::string buffer_;
417
419
std::exception_ptr fileError_;
@@ -421,46 +423,43 @@ TEST_F(FaultyFsTest, fileReadErrorInjection) {
421
423
// Set read error.
422
424
fs_->setFileInjectionError (fileError_, {FaultFileOperation::Type::kRead });
423
425
{
424
- auto readFile = fs_->openFileForRead (filePath_ , {});
426
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
425
427
VELOX_ASSERT_THROW (
426
428
readData (readFile.get (), false ), " InjectedFaultFileError" );
427
429
}
428
430
{
429
- auto readFile = fs_->openFileForRead (filePath_ , {});
431
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
430
432
// We only inject error for pread API so preadv should be fine.
431
433
readData (readFile.get (), true );
432
434
}
433
435
434
436
// Set readv error
435
437
fs_->setFileInjectionError (fileError_, {FaultFileOperation::Type::kReadv });
436
438
{
437
- auto readFile = fs_->openFileForRead (filePath_ , {});
439
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
438
440
VELOX_ASSERT_THROW (
439
441
readData (readFile.get (), true ), " InjectedFaultFileError" );
440
442
}
441
443
{
442
- auto readFile = fs_->openFileForRead (filePath_ , {});
443
- // We only inject error for pread API so preadv should be fine.
444
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
445
+ // We only inject error for preadv API so pread should be fine.
444
446
readData (readFile.get (), false );
445
447
}
446
448
447
449
// Set error for all kinds of operations.
448
450
fs_->setFileInjectionError (fileError_);
449
- auto readFile = fs_->openFileForRead (filePath_ , {});
451
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
450
452
VELOX_ASSERT_THROW (readData (readFile.get (), true ), " InjectedFaultFileError" );
451
453
VELOX_ASSERT_THROW (readData (readFile.get (), false ), " InjectedFaultFileError" );
452
- fs_->remove (filePath_);
453
- // Check there is no interference on write as we don't support it for now.
454
- auto writeFile = fs_->openFileForWrite (filePath_, {});
455
- writeData (writeFile.get ());
454
+ fs_->remove (readFilePath_);
456
455
}
457
456
458
457
TEST_F (FaultyFsTest, fileReadDelayInjection) {
459
- // Set 3 seconds delay.
458
+ // Set 2 seconds delay.
460
459
const uint64_t injectDelay{2'000'000 };
461
460
fs_->setFileInjectionDelay (injectDelay, {FaultFileOperation::Type::kRead });
462
461
{
463
- auto readFile = fs_->openFileForRead (filePath_ , {});
462
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
464
463
uint64_t readDurationUs{0 };
465
464
{
466
465
MicrosecondTimer readTimer (&readDurationUs);
@@ -469,7 +468,7 @@ TEST_F(FaultyFsTest, fileReadDelayInjection) {
469
468
ASSERT_GE (readDurationUs, injectDelay);
470
469
}
471
470
{
472
- auto readFile = fs_->openFileForRead (filePath_ , {});
471
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
473
472
// We only inject error for pread API so preadv should be fine.
474
473
uint64_t readDurationUs{0 };
475
474
{
@@ -482,7 +481,7 @@ TEST_F(FaultyFsTest, fileReadDelayInjection) {
482
481
// Set readv error
483
482
fs_->setFileInjectionDelay (injectDelay, {FaultFileOperation::Type::kReadv });
484
483
{
485
- auto readFile = fs_->openFileForRead (filePath_ , {});
484
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
486
485
uint64_t readDurationUs{0 };
487
486
{
488
487
MicrosecondTimer readTimer (&readDurationUs);
@@ -491,7 +490,7 @@ TEST_F(FaultyFsTest, fileReadDelayInjection) {
491
490
ASSERT_GE (readDurationUs, injectDelay);
492
491
}
493
492
{
494
- auto readFile = fs_->openFileForRead (filePath_ , {});
493
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
495
494
// We only inject error for pread API so preadv should be fine.
496
495
uint64_t readDurationUs{0 };
497
496
{
@@ -504,7 +503,7 @@ TEST_F(FaultyFsTest, fileReadDelayInjection) {
504
503
// Set error for all kinds of operations.
505
504
fs_->setFileInjectionDelay (injectDelay);
506
505
{
507
- auto readFile = fs_->openFileForRead (filePath_ , {});
506
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
508
507
// We only inject error for pread API so preadv should be fine.
509
508
uint64_t readDurationUs{0 };
510
509
{
@@ -514,7 +513,7 @@ TEST_F(FaultyFsTest, fileReadDelayInjection) {
514
513
ASSERT_GE (readDurationUs, injectDelay);
515
514
}
516
515
{
517
- auto readFile = fs_->openFileForRead (filePath_ , {});
516
+ auto readFile = fs_->openFileForRead (readFilePath_ , {});
518
517
// We only inject error for pread API so preadv should be fine.
519
518
uint64_t readDurationUs{0 };
520
519
{
@@ -523,16 +522,6 @@ TEST_F(FaultyFsTest, fileReadDelayInjection) {
523
522
}
524
523
ASSERT_GE (readDurationUs, injectDelay);
525
524
}
526
-
527
- fs_->remove (filePath_);
528
- // Check there is no interference on write as we don't support it for now.
529
- auto writeFile = fs_->openFileForWrite (filePath_, {});
530
- uint64_t writeDurationUs{0 };
531
- {
532
- MicrosecondTimer writeTimer (&writeDurationUs);
533
- writeData (writeFile.get ());
534
- }
535
- ASSERT_LT (writeDurationUs, injectDelay);
536
525
}
537
526
538
527
TEST_F (FaultyFsTest, fileReadFaultHookInjection) {
@@ -605,3 +594,106 @@ TEST_F(FaultyFsTest, fileReadFaultHookInjection) {
605
594
VELOX_ASSERT_THROW (readData (readFile.get (), false ), " Data Mismatch" );
606
595
}
607
596
}
597
+
598
+ TEST_F (FaultyFsTest, fileWriteErrorInjection) {
599
+ // Set write error.
600
+ fs_->setFileInjectionError (fileError_, {FaultFileOperation::Type::kWrite });
601
+ {
602
+ auto writeFile = fs_->openFileForWrite (writeFilePath_, {});
603
+ VELOX_ASSERT_THROW (writeFile->append (" hello" ), " InjectedFaultFileError" );
604
+ fs_->remove (writeFilePath_);
605
+ }
606
+ // Set error for all kinds of operations.
607
+ fs_->setFileInjectionError (fileError_);
608
+ {
609
+ auto writeFile = fs_->openFileForWrite (writeFilePath_, {});
610
+ VELOX_ASSERT_THROW (writeFile->append (" hello" ), " InjectedFaultFileError" );
611
+ fs_->remove (writeFilePath_);
612
+ }
613
+ }
614
+
615
+ TEST_F (FaultyFsTest, fileWriteDelayInjection) {
616
+ // Set 2 seconds delay.
617
+ const uint64_t injectDelay{2'000'000 };
618
+ fs_->setFileInjectionDelay (injectDelay, {FaultFileOperation::Type::kWrite });
619
+ {
620
+ auto writeFile = fs_->openFileForWrite (writeFilePath_, {});
621
+ uint64_t readDurationUs{0 };
622
+ {
623
+ MicrosecondTimer readTimer (&readDurationUs);
624
+ writeFile->append (" hello" );
625
+ }
626
+ ASSERT_GE (readDurationUs, injectDelay);
627
+ fs_->remove (writeFilePath_);
628
+ }
629
+ }
630
+
631
+ TEST_F (FaultyFsTest, fileWriteFaultHookInjection) {
632
+ const std::string path1 = fmt::format (" {}/hookFile1" , dir_->getPath ());
633
+ const std::string path2 = fmt::format (" {}/hookFile2" , dir_->getPath ());
634
+ // Set to write fake data.
635
+ fs_->setFileInjectionHook ([&](FaultFileOperation* op) {
636
+ // Only inject for write.
637
+ if (op->type != FaultFileOperation::Type::kWrite ) {
638
+ return ;
639
+ }
640
+ // Only inject for path2.
641
+ if (op->path != path2) {
642
+ return ;
643
+ }
644
+ auto * writeOp = static_cast <FaultFileWriteOperation*>(op);
645
+ writeOp->data = " Error data" ;
646
+ });
647
+ {
648
+ auto writeFile = fs_->openFileForWrite (path1, {});
649
+ writeFile->append (" hello" );
650
+ writeFile->close ();
651
+ auto readFile = fs_->openFileForRead (path1, {});
652
+ char buffer[5 ];
653
+ ASSERT_EQ (readFile->size (), 5 );
654
+ ASSERT_EQ (readFile->pread (0 , 5 , &buffer), " hello" );
655
+ fs_->remove (path1);
656
+ }
657
+ {
658
+ auto writeFile = fs_->openFileForWrite (path2, {});
659
+ writeFile->append (" hello" );
660
+ writeFile->close ();
661
+ auto readFile = fs_->openFileForRead (path2, {});
662
+ char buffer[10 ];
663
+ ASSERT_EQ (readFile->size (), 10 );
664
+ ASSERT_EQ (readFile->pread (0 , 10 , &buffer), " Error data" );
665
+ fs_->remove (path2);
666
+ }
667
+
668
+ // Set to not delegate.
669
+ fs_->setFileInjectionHook ([&](FaultFileOperation* op) {
670
+ // Only inject for write.
671
+ if (op->type != FaultFileOperation::Type::kWrite ) {
672
+ return ;
673
+ }
674
+ // Only inject for path2.
675
+ if (op->path != path2) {
676
+ return ;
677
+ }
678
+ auto * writeOp = static_cast <FaultFileWriteOperation*>(op);
679
+ writeOp->delegate = false ;
680
+ });
681
+ {
682
+ auto writeFile = fs_->openFileForWrite (path1, {});
683
+ writeFile->append (" hello" );
684
+ writeFile->close ();
685
+ auto readFile = fs_->openFileForRead (path1, {});
686
+ char buffer[5 ];
687
+ ASSERT_EQ (readFile->size (), 5 );
688
+ ASSERT_EQ (readFile->pread (0 , 5 , &buffer), " hello" );
689
+ fs_->remove (path1);
690
+ }
691
+ {
692
+ auto writeFile = fs_->openFileForWrite (path2, {});
693
+ writeFile->append (" hello" );
694
+ writeFile->close ();
695
+ auto readFile = fs_->openFileForRead (path2, {});
696
+ ASSERT_EQ (readFile->size (), 0 );
697
+ fs_->remove (path2);
698
+ }
699
+ }
0 commit comments