namespace instrument {
namespace transforms {

namespace {

using block_graph::BlockGraph;

// A derived class to expose protected members for unit-testing.
class TestAsanInterceptorFilter : public AsanInterceptorFilter {
 public:
  using AsanInterceptorFilter::AddBlockToHashMap;
  using AsanInterceptorFilter::function_hash_map_;
};

}  // namespace

TEST(InterceptorFilterTest, IsFiltered) {
  BlockGraph block_graph;
  const size_t kBlockSize = 0x20;

  BlockGraph::Block* block = block_graph.AddBlock(BlockGraph::CODE_BLOCK,
                                                  kBlockSize,
                                                  "test block");
  EXPECT_NE(reinterpret_cast<uint8_t*>(NULL), block->ResizeData(kBlockSize));
  ::memset(block->GetMutableData(), 0xAB, kBlockSize);

  TestAsanInterceptorFilter filter;
  EXPECT_TRUE(filter.function_hash_map_.empty());
  filter.InitializeContentHashes(kAsanIntercepts, true);
  // Only check that the CRT functions hashes have been loaded into the map, the
  // integration tests takes care of ensuring that those functions are really
  // intercepted.
  EXPECT_FALSE(filter.function_hash_map_.empty());

  EXPECT_EQ(AsanInterceptorFilter::NOT_INTERCEPTED,
            filter.ShouldIntercept(block));
  filter.AddBlockToHashMap(block);
  EXPECT_EQ(AsanInterceptorFilter::INTERCEPTED, filter.ShouldIntercept(block));
  block->GetMutableData()[0] = ~block->data()[0];
  EXPECT_EQ(AsanInterceptorFilter::INVALID_HASH, filter.ShouldIntercept(block));
}

}  // namespace transforms
}  // namespace instrument
