zircon/system/ulib/fs/journal/test/journal_test.cc
// Tests that many data operations, which overfill the writeback buffer, will cause subsequent
// requests to block.
Tests that many data operations, which overfill the writeback buffer, will cause subsequent
requests to block.
Tests that many data operations which overfill the writeback buffer will cause subsequent requests to block .
TEST_F(JournalTest, WritingDataToFullBufferBlocksCaller) {
  storage::VmoBuffer buffer = registry()->InitializeBuffer(kWritebackLength);
  const std::vector<storage::UnbufferedOperation> operations = {
      {
          zx::unowned_vmo(buffer.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 20,
              .length = 9,
          },
      },
      {
          zx::unowned_vmo(buffer.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 20,
              .length = 2,
          },
      },
  };
  ASSERT_EQ(kWritebackLength + 1, operations[0].op.length + operations[1].op.length,
            "Operations should slightly overflow the data buffer");
  std::atomic<bool> op0_completed = false;
  std::atomic<bool> op1_written = false;
  constexpr uint64_t kJournalStartBlock = 55;
  JournalRequestVerifier verifier(registry()->info(), registry()->journal(),
                                  registry()->writeback(), kJournalStartBlock);
  MockTransactionHandler::TransactionCallback callbacks[] = {
      [&](const std::vector<storage::BufferedOperation>& requests) {
        EXPECT_FALSE(op0_completed);
        EXPECT_FALSE(op1_written);
        verifier.VerifyDataWrite(operations[0], requests);
        verifier.ExtendDataOffset(operations[0].op.length);
        op0_completed = true;
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        EXPECT_TRUE(op0_completed);
        EXPECT_TRUE(op1_written);
        verifier.VerifyDataWrite(operations[1], requests);
        verifier.ExtendDataOffset(operations[1].op.length);
        return ZX_OK;
      },
  };
  MockTransactionHandler handler(registry(), callbacks, std::size(callbacks));
  {
    Journal journal(&handler, take_info(), take_journal_buffer(), take_data_buffer(), 0,
                    Journal::Options());
    auto promise0 = journal.WriteData({operations[0]});
    journal.schedule_task(std::move(promise0));
    std::thread worker([&]() {
      auto promise1 = journal.WriteData({operations[1]});
      if (!op0_completed) {
        fprintf(stderr, "Expected operation 0 to complete before operation 1\n");
        return;
      }
      op1_written = true;
      journal.schedule_task(std::move(promise1));
    });
    worker.join();
  }
  EXPECT_TRUE(op0_completed);
  EXPECT_TRUE(op1_written);
}
TEST_F ( JournalTest , WritingDataToFullBufferBlocksCaller ) { storage :: VmoBuffer buffer = registry ( ) -> InitializeBuffer ( kWritebackLength ) ; const std :: vector < storage :: UnbufferedOperation > operations = { { zx :: unowned_vmo ( buffer . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 20 , . length = 9 , } , } , { zx :: unowned_vmo ( buffer . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 20 , . length = 2 , } , } , } ; ASSERT_EQ ( kWritebackLength + 1 , operations [ 0 ] . op . length + operations [ 1 ] . op . length , " " ) ; std :: atomic < bool > op0_completed = false ; std :: atomic < bool > op1_written = false ; constexpr uint64_t kJournalStartBlock = 55 ; JournalRequestVerifier verifier ( registry ( ) -> info ( ) , registry ( ) -> journal ( ) , registry ( ) -> writeback ( ) , kJournalStartBlock ) ; MockTransactionHandler :: TransactionCallback callbacks [ ] = { [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { EXPECT_FALSE ( op0_completed ) ; EXPECT_FALSE ( op1_written ) ; verifier . VerifyDataWrite ( operations [ 0 ] , requests ) ; verifier . ExtendDataOffset ( operations [ 0 ] . op . length ) ; op0_completed = true ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { EXPECT_TRUE ( op0_completed ) ; EXPECT_TRUE ( op1_written ) ; verifier . VerifyDataWrite ( operations [ 1 ] , requests ) ; verifier . ExtendDataOffset ( operations [ 1 ] . op . length ) ; return ZX_OK ; } , } ; MockTransactionHandler handler ( registry ( ) , callbacks , std :: size ( callbacks ) ) ; { Journal journal ( & handler , take_info ( ) , take_journal_buffer ( ) , take_data_buffer ( ) , 0 , Journal :: Options ( ) ) ; auto promise0 = journal . WriteData ( { operations [ 0 ] } ) ; journal . schedule_task ( std :: move ( promise0 ) ) ; std :: thread worker ( [ & ] ( ) { auto promise1 = journal . WriteData ( { operations [ 1 ] } ) ; if ( ! op0_completed ) { fprintf ( stderr , " \n " ) ; return ; } op1_written = true ; journal . schedule_task ( std :: move ( promise1 ) ) ; } ) ; worker . join ( ) ; } EXPECT_TRUE ( op0_completed ) ; EXPECT_TRUE ( op1_written ) ; }
Tests that many data operations, which overfill the writeback buffer, will cause subsequent
requests to block.
Tests that many data operations which overfill the writeback buffer will cause subsequent requests to block .
// Was operations[0] completed (received by transaction handler)? // Was operations[1] successfully written to the buffer (WriteData promise created)? // Start a background thread attempting to write operation[1]. // It should block until operations[0] has completed.