zircon/system/ulib/fs/journal/test/journal_test.cc
// Tests that the info block is updated after the journal is completely full.
//
// This acts as a regression test against a bug where "the journal was exactly full"
// appeared the same as "the journal is exactly empty" when making the decision
// to write back the info block.
//
// Operation 0: [ H, 1, 2, 3, 4, 5, 6, 7, 8, C ]
// Operation 1: [ H, 1, C, _, _, _, _, _, _, _ ]
//            : Info block update promted by operation 1.
Tests that the info block is updated after the journal is completely full.
This acts as a regression test against a bug where "the journal was exactly full"
appeared the same as "the journal is exactly empty" when making the decision
to write back the info block.


Tests that the info block is updated after the journal is completely full . This acts as a regression test against a bug where " the journal was exactly full " appeared the same as " the journal is exactly empty " when making the decision to write back the info block .
TEST_F(JournalTest, WriteExactlyFullJournalDoesNotUpdateInfoBlockUntilNewOperationArrives) {
  storage::VmoBuffer metadata = registry()->InitializeBuffer(kJournalLength);
  const std::vector<storage::UnbufferedOperation> operations = {
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 20,
              .length = 8,
          },
      },
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 1234,
              .length = 1,
          },
      },
  };
  ASSERT_EQ(kJournalLength, kEntryMetadataBlocks + operations[0].op.length,
            "Operations should just fill the journal (no early info writeback)");
  constexpr uint64_t kJournalStartBlock = 55;
  JournalRequestVerifier verifier(registry()->info(), registry()->journal(),
                                  registry()->writeback(), kJournalStartBlock);
  uint64_t sequence_number = 0;
  MockTransactionHandler::TransactionCallback callbacks[] = {
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyJournalWrite(operations[0], requests);
        sequence_number++;
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyMetadataWrite(operations[0], requests);
        verifier.ExtendJournalOffset(operations[0].op.length + kEntryMetadataBlocks);
        registry()->VerifyReplay({operations[0]}, sequence_number);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyInfoBlockWrite(sequence_number, requests);
        registry()->VerifyReplay({}, sequence_number);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyJournalWrite(operations[1], requests);
        sequence_number++;
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyMetadataWrite(operations[1], requests);
        verifier.ExtendJournalOffset(operations[1].op.length + kEntryMetadataBlocks);
        registry()->VerifyReplay({operations[1]}, sequence_number);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyInfoBlockWrite(sequence_number, requests);
        registry()->VerifyReplay({}, sequence_number);
        return ZX_OK;
      },
  };
  MockTransactionHandler handler(registry(), callbacks, std::size(callbacks));
  {
    Journal journal(&handler, take_info(), take_journal_buffer(), take_data_buffer(),
                    kJournalStartBlock, Journal::Options());
    journal.schedule_task(journal.WriteMetadata({operations[0]}));
    journal.schedule_task(journal.WriteMetadata({operations[1]}));
  }
}
TEST_F ( JournalTest , WriteExactlyFullJournalDoesNotUpdateInfoBlockUntilNewOperationArrives ) { storage :: VmoBuffer metadata = registry ( ) -> InitializeBuffer ( kJournalLength ) ; const std :: vector < storage :: UnbufferedOperation > operations = { { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 20 , . length = 8 , } , } , { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 1234 , . length = 1 , } , } , } ; ASSERT_EQ ( kJournalLength , kEntryMetadataBlocks + operations [ 0 ] . op . length , " " ) ; constexpr uint64_t kJournalStartBlock = 55 ; JournalRequestVerifier verifier ( registry ( ) -> info ( ) , registry ( ) -> journal ( ) , registry ( ) -> writeback ( ) , kJournalStartBlock ) ; uint64_t sequence_number = 0 ; MockTransactionHandler :: TransactionCallback callbacks [ ] = { [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyJournalWrite ( operations [ 0 ] , requests ) ; sequence_number ++ ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyMetadataWrite ( operations [ 0 ] , requests ) ; verifier . ExtendJournalOffset ( operations [ 0 ] . op . length + kEntryMetadataBlocks ) ; registry ( ) -> VerifyReplay ( { operations [ 0 ] } , sequence_number ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyInfoBlockWrite ( sequence_number , requests ) ; registry ( ) -> VerifyReplay ( { } , sequence_number ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyJournalWrite ( operations [ 1 ] , requests ) ; sequence_number ++ ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyMetadataWrite ( operations [ 1 ] , requests ) ; verifier . ExtendJournalOffset ( operations [ 1 ] . op . length + kEntryMetadataBlocks ) ; registry ( ) -> VerifyReplay ( { operations [ 1 ] } , sequence_number ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyInfoBlockWrite ( sequence_number , requests ) ; registry ( ) -> VerifyReplay ( { } , sequence_number ) ; return ZX_OK ; } , } ; MockTransactionHandler handler ( registry ( ) , callbacks , std :: size ( callbacks ) ) ; { Journal journal ( & handler , take_info ( ) , take_journal_buffer ( ) , take_data_buffer ( ) , kJournalStartBlock , Journal :: Options ( ) ) ; journal . schedule_task ( journal . WriteMetadata ( { operations [ 0 ] } ) ) ; journal . schedule_task ( journal . WriteMetadata ( { operations [ 1 ] } ) ) ; } }
Tests that the info block is updated after the journal is completely full.
Tests that the info block is updated after the journal is completely full .
// Operation 0 written. // Operation 1 written. This prompts the info block to be updated. // Info block written on journal termination.