Exemplo n.º 1
0
VOID
TestWrap(
    PVMDIR_TEST_STATE pState
    )
{
    PVMDIR_CIRCULAR_BUFFER pCircularBuffer;
    PCIRCULAR_BUFFER_TEST_ELEMENT Element;
    DWORD dwError = 0;

    dwError = VmDirCircularBufferCreate(3, sizeof(CIRCULAR_BUFFER_TEST_ELEMENT), &pCircularBuffer);
    TestAssertEquals(dwError, 0);

    Element = VmDirCircularBufferGetNextEntry(pCircularBuffer);
    Element->name = arrCircularBufferTestData[0].name;
    Element->age = arrCircularBufferTestData[0].age;

    Element = VmDirCircularBufferGetNextEntry(pCircularBuffer);
    Element->name = arrCircularBufferTestData[1].name;
    Element->age = arrCircularBufferTestData[1].age;

    Element = VmDirCircularBufferGetNextEntry(pCircularBuffer);
    Element->name = arrCircularBufferTestData[2].name;
    Element->age = arrCircularBufferTestData[2].age;

    Element = VmDirCircularBufferGetNextEntry(pCircularBuffer);
    Element->name = arrCircularBufferTestData[3].name;
    Element->age = arrCircularBufferTestData[3].age;

    dwError = VmDirCircularBufferSelectElements(pCircularBuffer, 1, Callback, &arrCircularBufferTestData[1]);
    TestAssertEquals(dwError, 0);

    VmDirCircularBufferFree(pCircularBuffer);
}
  // Utility for running timings of reads of the filebundle segment with
  // different caching.
  uint32 TestReadAll(FileBundleReaderSegment& segment,
                   uint32 request_count,
                   uint32 max_blocks,
                   uint32 block_size,
                   std::string prefix) {
    std::string buffer;
    buffer.reserve(block_size);
    buffer.resize(request_count);
    char* out_buffer = const_cast<char*>(buffer.data());

    // Test Read uncached of entire filebundle
    CachedReadAccessor accessor(max_blocks < 2 ? 2 : max_blocks, block_size);
    khTimer_t begin = khTimer::tick();
    uint32 read_count = 0;
    uint32 packet_count = 0;
    uint64 stats_bytes_read = 0;
    uint64 stats_disk_accesses = 0;
    for(uint32 offset = 0; offset < file_bundle_size_; offset += request_count) {
      uint32 size = std::min(request_count, file_bundle_size_ - offset);
      if (max_blocks == 0) { // No cache...read via the segment directly.
        segment.Pread(out_buffer, size, offset);
        stats_bytes_read += size;
        stats_disk_accesses++;
      }
      else { // Read via the accessor.
        accessor.Pread(segment, out_buffer, size, offset);
      }
      read_count += size;
      packet_count++;
    }
    khTimer_t end = khTimer::tick();
    uint32 megabytes_per_second = static_cast<uint32>(read_count /
      (khTimer::delta_s(begin, end) * 1000000));
    std::cerr << prefix << ": " << request_count << " bytes per packet " <<
      packet_count << " packets " <<
      megabytes_per_second << " MB/sec" << std::endl;
    // Print some basic stats to make sure the cache is doing it's job right.
    if (max_blocks >= 2) {
      stats_bytes_read = accessor.StatsBytesRead();
      stats_disk_accesses = accessor.StatsDiskAccesses();
    }
    uint64 chunk_sizes = block_size;
    if (max_blocks < 2) {
      chunk_sizes = request_count;
    }
    uint64 desired_disk_accesses = (file_bundle_size_ + chunk_sizes - 1) / chunk_sizes;
    TestAssertEquals(stats_bytes_read, static_cast<uint64>(file_bundle_size_));
    TestAssertEquals(stats_disk_accesses,
                     static_cast<uint64>(desired_disk_accesses));

    std::cerr << "Read " << stats_bytes_read << " bytes from disk in " <<
      stats_disk_accesses << " reads" << std::endl;

    return megabytes_per_second;
  }
Exemplo n.º 3
0
VOID
TestMakeCapacityBiggerShouldSucceed(
    PVMDIR_TEST_STATE pState
    )
{
    PVMDIR_CIRCULAR_BUFFER pCircularBuffer = NULL;
    DWORD dwError = 0;

    dwError = VmDirCircularBufferCreate(2, sizeof(CIRCULAR_BUFFER_TEST_ELEMENT), &pCircularBuffer);
    TestAssertEquals(dwError, 0);

    dwError = VmDirCircularBufferSetCapacity(pCircularBuffer, 4);
    TestAssertEquals(dwError, 0);
}
Exemplo n.º 4
0
VOID
_Test_VmDirStringNCpyA_SourceStringTooLong(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[4] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "Hello, world!",
                7);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
    TestAssertEquals(szDestination[0], 'a');
}
Exemplo n.º 5
0
VOID
_Test_VmDirStringNCpyA_CallShouldFailCountMatchesSize(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szBuffer[4] = { 'a' };

    dwError = VmDirStringNCpyA(
                szBuffer,
                VMDIR_ARRAY_SIZE(szBuffer),
                "abcd",
                4);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
    TestAssertEquals(szBuffer[0], 'a');
}
  // Test CacheBlockAddress Utility class, mostly that constructor and
  // comparison operators are properly defined.
  bool TestCacheBlockAddress() {
    uint32 offset = 100;
    uint32 segment_id = 1010;
    CachedReadAccessor::CacheBlockAddress address1(segment_id, offset);
    TestAssertEquals(offset, address1.Offset());

    { // Equality and copy constructor tests.
      CachedReadAccessor::CacheBlockAddress address2(segment_id, offset);
      TestAssert(address1 == address2);
      TestAssert((address1 < address2) == false);
      CachedReadAccessor::CacheBlockAddress address3 = address1;
      TestAssert(address2 == address3);
    }
    { // less than by segment id
      CachedReadAccessor::CacheBlockAddress address2(segment_id+1, offset);
      TestAssert(address1 < address2);
      TestAssert(address1 != address2);
      TestAssert((address2 < address1) == false);
    }
    { // less than by offset
      CachedReadAccessor::CacheBlockAddress address2(segment_id, offset+1);
      TestAssert(address1 < address2);
      TestAssert(address1 != address2);
      TestAssert((address2 < address1) == false);
    }
    return true;
  }
Exemplo n.º 7
0
VOID
_Test_VmDirStringNCpyA_NullSourceString(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[16] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                NULL,
                10);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
    TestAssertEquals(szDestination[0], 'a');
}
Exemplo n.º 8
0
VOID
_Test_VmDirStringNCpyA_EmptySourceStringWrongCount(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[16] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "",
                10);
    TestAssertEquals(dwError, 0);
    TestAssertEquals(szDestination[0], '\0');
}
Exemplo n.º 9
0
VOID
TestSelectTooManyElementsQuietlySucceeds(
    PVMDIR_TEST_STATE pState
    )
{
    PVMDIR_CIRCULAR_BUFFER pCircularBuffer = NULL;
    DWORD dwError = 0;
    DWORD dwCount = 0;

    dwError = VmDirCircularBufferCreate(4, sizeof(CIRCULAR_BUFFER_TEST_ELEMENT), &pCircularBuffer);
    TestAssertEquals(dwError, 0);

    FillBuffer(pCircularBuffer, 4);

    dwError = VmDirCircularBufferSelectElements(pCircularBuffer, 20, CountingCallback, &dwCount);
    TestAssertEquals(dwError, 0);
}
Exemplo n.º 10
0
VOID
testEmpty(
    PVMDIR_TEST_STATE pState,
    PDEQUE pDeque
    )
{
    DWORD dwError = 0;
    PDEQUEUE_TEST_ELEMENT pElement = NULL;
    BOOLEAN fEmpty = FALSE;

    //Test case: pop from empty queue
    fEmpty = dequeIsEmpty(pDeque);
    TestAssertEquals(fEmpty, TRUE);

    dwError = dequePopLeft(pDeque, (PVOID*)&pElement);
    TestAssertEquals(dwError, ERROR_NO_MORE_ITEMS);
}
Exemplo n.º 11
0
VOID
TestSelectReturnsCorrectElementsInCorrectOrder(
    PVMDIR_TEST_STATE pState
    )
{
    PVMDIR_CIRCULAR_BUFFER pCircularBuffer = NULL;
    DWORD dwError = 0;
    DWORD dwCount = 0;

    dwError = VmDirCircularBufferCreate(4, sizeof(CIRCULAR_BUFFER_TEST_ELEMENT), &pCircularBuffer);
    TestAssertEquals(dwError, 0);

    FillBuffer(pCircularBuffer, 7);

    dwError = VmDirCircularBufferSelectElements(pCircularBuffer, 4, Callback2, &dwCount);
    TestAssertEquals(dwError, 0);
}
Exemplo n.º 12
0
VOID
TestMakeCapacitySmallerShouldSucceed(
    PVMDIR_TEST_STATE pState
    )
{
    PVMDIR_CIRCULAR_BUFFER pCircularBuffer = NULL;
    DWORD dwError = 0;

    dwError = VmDirCircularBufferCreate(4, sizeof(CIRCULAR_BUFFER_TEST_ELEMENT), &pCircularBuffer);
    TestAssertEquals(dwError, 0);

    FillBuffer(pCircularBuffer, 4);

    dwError = VmDirCircularBufferSetCapacity(pCircularBuffer, 2);
    TestAssertEquals(pCircularBuffer->dwCapacity, 2);
    TestAssertEquals(dwError, 0);
    TestAssert(pCircularBuffer->dwHead < pCircularBuffer->dwCapacity);
}
Exemplo n.º 13
0
VOID
TestSelectReturnsWhenCallbackReturnsFalse(
    PVMDIR_TEST_STATE pState
    )
{
    PVMDIR_CIRCULAR_BUFFER pCircularBuffer = NULL;
    DWORD dwError = 0;
    DWORD dwCount = 0;

    dwError = VmDirCircularBufferCreate(4, sizeof(CIRCULAR_BUFFER_TEST_ELEMENT), &pCircularBuffer);
    TestAssertEquals(dwError, 0);

    FillBuffer(pCircularBuffer, 4);

    dwError = VmDirCircularBufferSelectElements(pCircularBuffer, 4, CountingCallback, &dwCount);
    TestAssertEquals(dwError, 0);
    TestAssertEquals(dwCount, 2);
}
Exemplo n.º 14
0
VOID
_Test_VmDirStringNCpyA_NullDestinationString(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;

    dwError = VmDirStringNCpyA(NULL, 4, "test", 4);
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);
}
Exemplo n.º 15
0
VOID
_Test_VmDirStringNCpyA_EmptySourceStringRightCount(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[16] = { '\0' };

    //
    // This call will yield different results on windows and linux. On
    // the former we call the _s version of strncpy so the string's first byte
    // will be NULL, regardless of what it is coming into the call. However,
    // on linux the string will be untouched after the call.
    //
    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "",
                0);
    TestAssertEquals(dwError, 0);
    TestAssertEquals(szDestination[0], '\0');
}
Exemplo n.º 16
0
VOID
TestCleanupOfValidCircularBuffer(
    PVMDIR_TEST_STATE pState
    )
{
    PVMDIR_CIRCULAR_BUFFER pCircularBuffer;
    DWORD dwError = 0;

    dwError = VmDirCircularBufferCreate(4, sizeof(CIRCULAR_BUFFER_TEST_ELEMENT), &pCircularBuffer);
    TestAssertEquals(dwError, 0);

    VmDirCircularBufferFree(pCircularBuffer);
}
Exemplo n.º 17
0
VOID
testStack(
    PVMDIR_TEST_STATE pState,
    PDEQUE pDeque
    )
{
    DWORD dwError = 0;
    PDEQUEUE_TEST_ELEMENT pElement = NULL;
    int i = 0;

    for (i = 0; i < VMDIR_ARRAY_SIZE(arrDequeTestData); i++)
    {
        dwError = dequePush(pDeque, &arrDequeTestData[i]);
        TestAssertEquals(dwError, ERROR_SUCCESS);
    }

    for (i = 0; i < VMDIR_ARRAY_SIZE(arrDequeTestData); i++)
    {
        dwError = dequePop(pDeque, (PVOID*)&pElement);
        TestAssertEquals(dwError, ERROR_SUCCESS);
        TestAssertPtrEquals(pElement, &arrDequeTestData[VMDIR_ARRAY_SIZE(arrDequeTestData)-i-1]);
    }
}
Exemplo n.º 18
0
VOID
TestMaxDwordValueRoundTrip(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwTestValue = 0;
    DWORD dwComparisonValue = 0;
    DWORD dwError = 0;

    dwTestValue = 0xFFFFFFFF; // Biggest possible DWORD
    dwError = VmDirSetRegKeyValueDword(
                VMDIR_CONFIG_PARAMETER_KEY_PATH,
                "TestMaxValue",
                dwTestValue);
    TestAssertEquals(dwError, 0);

    dwError = VmDirGetRegKeyValueDword(
                VMDIR_CONFIG_PARAMETER_KEY_PATH,
                "TestMaxValue",
                &dwComparisonValue,
                0);
    TestAssertEquals(dwError, 0);
    TestAssertEquals(dwTestValue, dwComparisonValue);
}
Exemplo n.º 19
0
DWORD
_TestVmDirAllocateStringPrintfWithBadParameters(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    PSTR pszString = NULL;

    dwError = VmDirAllocateStringPrintf(
                NULL,
                "dword ==> %d, string ==> '%s'",
                42,
                "Hello, world!");
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);

    dwError = VmDirAllocateStringPrintf(
                &pszString,
                NULL,
                42,
                "Hello, world!");
    TestAssertEquals(dwError, ERROR_INVALID_PARAMETER);

    return 0;
}
Exemplo n.º 20
0
BOOLEAN
Callback(
    PVOID Element,
    PVOID Context
    )
{
    PCIRCULAR_BUFFER_TEST_ELEMENT TestElement = (PCIRCULAR_BUFFER_TEST_ELEMENT)Element;
    PCIRCULAR_BUFFER_TEST_ELEMENT ReferenceElement = (PCIRCULAR_BUFFER_TEST_ELEMENT)Context;
    PVMDIR_TEST_STATE pState = NULL;

    pState = TestElement->pState;
    TestAssertEquals(TestElement->age, ReferenceElement->age);
    TestAssertStrEquals(TestElement->name, ReferenceElement->name);

    return TRUE;
}
Exemplo n.º 21
0
VOID
_Test_VmDirStringNCpyA_CallShouldSucceedWithTruncation(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    CHAR szDestination[6] = { 'a' };

    dwError = VmDirStringNCpyA(
                szDestination,
                VMDIR_ARRAY_SIZE(szDestination),
                "Hello, world!",
                VMDIR_ARRAY_SIZE(szDestination) - 1);
    TestAssertEquals(dwError, 0);
    TestAssertStrEquals(szDestination, "Hello");
}
Exemplo n.º 22
0
DWORD
_TestVmDirAllocateStringPrintfWithGoodParameters(
    PVMDIR_TEST_STATE pState
    )
{
    PSTR pszString = NULL;
    DWORD dwError = 0;

    dwError = VmDirAllocateStringPrintf(
                &pszString,
                "dword ==> %d, string ==> '%s'",
                (DWORD)42,
                "Hello, world!");
    TestAssertEquals(dwError, ERROR_SUCCESS);
    TestAssertStrEquals(pszString, "dword ==> 42, string ==> 'Hello, world!'");

    return 0;
}
Exemplo n.º 23
0
VOID
TestDequeCode(
    PVMDIR_TEST_STATE pState
    )
{
    DWORD dwError = 0;
    PDEQUE pDeque = NULL;

    printf("Testing deque code ...");

    dwError = dequeCreate(&pDeque);
    TestAssertEquals(dwError, ERROR_SUCCESS);

    testEmpty(pState, pDeque);
    testQueue(pState, pDeque);
    testStack(pState, pDeque);
    testEmpty(pState, pDeque);

    dequeFree(pDeque);

    printf(" PASSED\n");
}
Exemplo n.º 24
0
DWORD
TestStandardRightsForUser(
    PVMDIR_TEST_STATE pState,
    LDAP *pLd,
    PCSTR pszContainerName
    )
{
    DWORD dwError = 0;

    dwError = TryToListChildObjects(pState, pszContainerName);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = TryToDeleteObject(pState, pszContainerName);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = TryToReadProperties(pState, pszContainerName);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = TryToReadSD(pState, pszContainerName);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = TryToWriteProperties(pState, pszContainerName);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = TryToWriteSD(pState, pszContainerName);
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = TryToListObject(pState, pszContainerName);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:
    return dwError;
error:
    TestAssertEquals(dwError, 0);
    goto cleanup;
}
  // Test the CacheBlock utility object Read() and LastAccessTick().
  bool TestCacheBlock() {
    uint32 offset = 13;
    uint32 segment_id = 0;
    uint32 block_size = file_bundle_size_ / 4;
    CachedReadAccessor::CacheBlockAddress address1(segment_id, 0);
    uint64 access_tick = 1033;
    CachedReadAccessor::CacheBlock block1(address1, block_size);

    // Check the initial access tick
    TestAssert(block1.LastAccessTick() == 0);
    block1.SetLastAccessTick(access_tick - 1);
    TestAssert(block1.LastAccessTick() == (access_tick - 1));

    // Test Read
    // Read request that is contained in 1 block.
    uint32 request_count = block_size - offset - 10;
    FileBundleReaderSegment segment(file_pool_,
                                    path_base_,
                                    segment_names_[segment_id],
                                    segment_names_[segment_id],
                                    segment_id);
    std::string buffer;
    buffer.reserve(block_size);
    buffer.resize(request_count);
    char* out_buffer = const_cast<char*>(buffer.data());

    // Test read within non-cached (uninitialized) block
    uint64 stats_bytes_read = 0;
    uint64 stats_disk_accesses = 0;
    uint32 read_count =
      block1.Read(segment, out_buffer, request_count, offset, access_tick++,
                  stats_bytes_read, stats_disk_accesses);
    TestAssert(block1.LastAccessTick() + 1 == access_tick);
    TestAssertEquals(stats_bytes_read, static_cast<uint64>(block_size));
    TestAssertEquals(stats_disk_accesses, static_cast<uint64>(1));
    TestAssertEquals(request_count, read_count);
    char* expected = test_buffer_ + offset;
    if (!TestBuffer(out_buffer, expected, read_count,
               std::string("TestCacheBlock: all data in one non-cached block")))
      return false;

    // Test read from the NOW cached block within the segment.
    offset = 23;
    request_count /= 3;
    buffer.resize(request_count);
    read_count =
      block1.Read(segment, out_buffer, request_count, offset, access_tick++,
                  stats_bytes_read, stats_disk_accesses);
    TestAssertEquals(stats_bytes_read, static_cast<uint64>(block_size));
    TestAssertEquals(stats_disk_accesses, static_cast<uint64>(1));
    TestAssertEquals(request_count, read_count);
    expected = test_buffer_ + offset;
    if (!TestBuffer(out_buffer, expected, read_count,
               std::string("TestCacheBlock: all data in one cached block")))
      return false;

    // Test a PARTIAL reads from a block (i.e., a request past the block
    // boundary.
    // create a new CacheBlock to start with an empty cache.
    block1 = CachedReadAccessor::CacheBlock(address1, block_size);
    request_count = 200;
    buffer.resize(request_count);

    uint32 expected_read_count = 133;
    offset = block_size - expected_read_count;
    // Read from a non-cached block
    read_count =
      block1.Read(segment, out_buffer, request_count, offset, access_tick++,
                  stats_bytes_read, stats_disk_accesses);
    TestAssertEquals(stats_bytes_read, static_cast<uint64>(2*block_size));
    TestAssertEquals(stats_disk_accesses, static_cast<uint64>(2));
    TestAssertEquals(expected_read_count, read_count);
    expected = test_buffer_ + offset;
    if (!TestBuffer(out_buffer, expected, read_count,
               std::string("TestCacheBlock: partial data in cached block")))
      return false;

    // Read from a cached block
    read_count =
      block1.Read(segment, out_buffer, request_count, offset, access_tick++,
                  stats_bytes_read, stats_disk_accesses);
    TestAssertEquals(expected_read_count, read_count);
    expected = test_buffer_ + offset;
    if (!TestBuffer(out_buffer, expected, read_count,
               std::string("TestCacheBlock: partial data in cached block")))
      return false;

    return true;
  }
  // Test the CachedReadAccessor utility methods BlockAddress(),
  // AddCacheBlock(), GetCacheBlock() and FindBlocks().
  bool TestCachedReadAccessorBasics() {
    uint32 offset = 13;
    uint32 segment_id = 0;
    uint32 block_size = file_bundle_size_ / 4;
    uint64 access_tick = 1033;

    CachedReadAccessor accessor(2, block_size);

    // Test BlockAddress
    CachedReadAccessor::CacheBlockAddress address1 =
      accessor.BlockAddress(segment_id, offset);
    TestAssertEquals(address1.Offset(), static_cast<uint32>(0));
    uint32 n = 7;
    CachedReadAccessor::CacheBlockAddress address2 =
      accessor.BlockAddress(segment_id, offset + n * block_size);
    TestAssertEquals(address2.Offset(), n * block_size);
    CachedReadAccessor::CacheBlockAddress address3 =
      accessor.BlockAddress(segment_id, (n+2) * block_size - 10);
    TestAssertEquals(address3.Offset(), (n+1) * block_size);

    // Test that AddCacheBlock and GetCacheBlock are compatible.
    CachedReadAccessor::CacheBlock* block1 = accessor.AddCacheBlock(address1);
    CachedReadAccessor::CacheBlock* block1_b = accessor.GetCacheBlock(address1);
    TestAssertEquals(block1, block1_b);
    block1->SetLastAccessTick(access_tick);

    // Test getting a new block twice.
    CachedReadAccessor::CacheBlock* block2 = accessor.GetCacheBlock(address2);
    CachedReadAccessor::CacheBlock* block2_b = accessor.GetCacheBlock(address2);
    TestAssertEquals(block2, block2_b);
    TestAssert(block1 != block2);
    block2->SetLastAccessTick(access_tick+1);
    uint64 block1_access_tick = block1->LastAccessTick();

    // Ok, we have block1 and block2
    // Now we try to get block3, should force one of the cached blocks out of
    // the cache (namely block1).
    CachedReadAccessor::CacheBlock* block3 = accessor.GetCacheBlock(address3);
    TestAssert(block3 != block1);
    TestAssert(block3 != block2);
    block3->SetLastAccessTick(0); // mark this as older for fun.

    // We should have block2 and block3
    // Getting block2 again should be the same object as before.
    block2_b = accessor.GetCacheBlock(address2);
    TestAssertEquals(block2, block2_b);

    // Getting block1 again should be a newly created object and block3 should
    // be flushed.
    block1_b = accessor.GetCacheBlock(address1);
    TestAssert(block1_b->LastAccessTick() != block1_access_tick);
    block1 = block1_b; // block1 was deleted...better be safe here.

    // Getting block2 yet again should be the same object as before.
    block2_b = accessor.GetCacheBlock(address2);
    TestAssertEquals(block2, block2_b);


    // Test FindBlocks
    // case 1: request spans a single block
    // case 2: request spans two blocks
    uint32 in_block_offset = 33;
    offset = block_size + in_block_offset;
    address1 = accessor.BlockAddress(segment_id, offset);
    address2 = accessor.BlockAddress(segment_id, offset + block_size);

    // test these cases when not cached and then again when cached.
    uint32 request_size = block_size - 2 * in_block_offset;
    // set request size to guarantee to be within 1 block.
    uint32 blocks_returned = accessor.FindBlocks(segment_id, request_size, offset,
                                        &block1, &block2);
    TestAssertEquals(blocks_returned, static_cast<uint32>(1));
    TestAssert(block2 == NULL);
    TestAssert(block1 != NULL);
    block1->SetLastAccessTick(access_tick++); // Make sure it stays in the cache.
    // Try again, slightly different request in the same block, block1
    // should be cached.
    blocks_returned = accessor.FindBlocks(segment_id,
                                        request_size - 3 * in_block_offset,
                                        offset + in_block_offset,
                                        &block1_b, &block2);
    TestAssertEquals(blocks_returned, static_cast<uint32>(1));
    TestAssert(block2 == NULL);
    TestAssert(block1 == block1_b);

    // Now try the same FindBlocks test on requests that span 2 CacheBlocks.
    request_size = block_size - in_block_offset / 2;
    blocks_returned = accessor.FindBlocks(segment_id, request_size, offset,
                                        &block1_b, &block2);
    TestAssertEquals(blocks_returned, static_cast<uint32>(2));
    TestAssert(block2 != NULL); // Make sure it stays in the cache.
    block2->SetLastAccessTick(access_tick++);
    TestAssert(block1 == block1_b);
    // Try again, slightly different request in the same block, block1
    // should be cached.
    blocks_returned = accessor.FindBlocks(segment_id,
                                        request_size,
                                        offset + in_block_offset,
                                        &block1_b, &block2_b);
    TestAssertEquals(blocks_returned, static_cast<uint32>(2));
    TestAssert(block2 == block2_b);
    TestAssert(block1 == block1_b);
    return true;
  }