zircon/system/ulib/fs/journal/test/journal_test.cc
// Tests that when data operations fail, subsequent operations also fail to avoid
// leaving the device in an inconsistent state.
Tests that when data operations fail, subsequent operations also fail to avoid
leaving the device in an inconsistent state.
Tests that when data operations fail subsequent operations also fail to avoid leaving the device in an inconsistent state .
TEST_F(JournalTest, DataWriteFailureFailsSubsequentRequests) {
  storage::VmoBuffer buffer = registry()->InitializeBuffer(5);
  const std::vector<storage::UnbufferedOperation> operations = {
      {
          zx::unowned_vmo(buffer.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 20,
              .length = 1,
          },
      },
      {
          zx::unowned_vmo(buffer.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 200,
              .length = 1,
          },
      },
  };
  JournalRequestVerifier verifier(registry()->info(), registry()->journal(),
                                  registry()->writeback(), 0);
  MockTransactionHandler::TransactionCallback callbacks[] = {
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyDataWrite(operations[0], requests);
        verifier.ExtendDataOffset(operations[0].op.length);
        return ZX_ERR_IO;
      },
  };
  std::atomic<bool> first_operation_failed = false;
  std::atomic<bool> second_operation_failed = false;
  MockTransactionHandler handler(registry(), callbacks, std::size(callbacks));
  {
    Journal journal(&handler, take_info(), take_journal_buffer(), take_data_buffer(), 0,
                    Journal::Options());
    auto promise =
        journal.WriteData({operations[0]})
            .then([&](fit::result<void, zx_status_t>& result) {
              EXPECT_STATUS(ZX_ERR_IO, result.error(), "operations[0] should fail with ZX_ERR_IO");
              first_operation_failed = true;
              return journal.WriteData({operations[1]});
            })
            .or_else([&](zx_status_t& status) {
              EXPECT_STATUS(ZX_ERR_IO_REFUSED, status);
              second_operation_failed = true;
              return fit::error(status);
            });
    journal.schedule_task(std::move(promise));
  }
  EXPECT_TRUE(first_operation_failed);
  EXPECT_TRUE(second_operation_failed);
}
TEST_F ( JournalTest , DataWriteFailureFailsSubsequentRequests ) { storage :: VmoBuffer buffer = registry ( ) -> InitializeBuffer ( 5 ) ; const std :: vector < storage :: UnbufferedOperation > operations = { { zx :: unowned_vmo ( buffer . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 20 , . length = 1 , } , } , { zx :: unowned_vmo ( buffer . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 200 , . length = 1 , } , } , } ; JournalRequestVerifier verifier ( registry ( ) -> info ( ) , registry ( ) -> journal ( ) , registry ( ) -> writeback ( ) , 0 ) ; MockTransactionHandler :: TransactionCallback callbacks [ ] = { [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyDataWrite ( operations [ 0 ] , requests ) ; verifier . ExtendDataOffset ( operations [ 0 ] . op . length ) ; return ZX_ERR_IO ; } , } ; std :: atomic < bool > first_operation_failed = false ; std :: atomic < bool > second_operation_failed = false ; MockTransactionHandler handler ( registry ( ) , callbacks , std :: size ( callbacks ) ) ; { Journal journal ( & handler , take_info ( ) , take_journal_buffer ( ) , take_data_buffer ( ) , 0 , Journal :: Options ( ) ) ; auto promise = journal . WriteData ( { operations [ 0 ] } ) . then ( [ & ] ( fit :: result < void , zx_status_t > & result ) { EXPECT_STATUS ( ZX_ERR_IO , result . error ( ) , " " ) ; first_operation_failed = true ; return journal . WriteData ( { operations [ 1 ] } ) ; } ) . or_else ( [ & ] ( zx_status_t & status ) { EXPECT_STATUS ( ZX_ERR_IO_REFUSED , status ) ; second_operation_failed = true ; return fit :: error ( status ) ; } ) ; journal . schedule_task ( std :: move ( promise ) ) ; } EXPECT_TRUE ( first_operation_failed ) ; EXPECT_TRUE ( second_operation_failed ) ; }
Tests that when data operations fail, subsequent operations also fail to avoid
leaving the device in an inconsistent state.
Tests that when data operations fail subsequent operations also fail to avoid leaving the device in an inconsistent state .
// Validate the request, but cause it to fail.