// 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;
  }
	//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	// SetPropertyData()
	//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	void SMPTETimeCallback::SetPropertyData(const CMIOObjectPropertyAddress& address, UInt32 /*qualifierDataSize*/, const void* /*qualifierData*/, UInt32 dataSize, const void* data)
	{
		switch (address.mSelector)
		{
			case kCMIODevicePropertySMPTETimeCallback:
				ThrowIf(dataSize != sizeof(CMIODeviceSMPTETimeCallback), CAException(kCMIOHardwareBadPropertySizeError), "SMPTETimeCallback::SetData: wrong data size for kCMIODevicePropertySMPTETimeCallback");
				mSMPTECallback = *(static_cast<const CMIODeviceSMPTETimeCallback*>(data));
				PropertyAddress address1(kCMIODevicePropertySMPTETimeCallback);
				mOwningDevice.PropertiesChanged(1, &address1);
				break;
		};
	}
  // 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;
  }