| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 | //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.//  This source code is licensed under both the GPLv2 (found in the//  COPYING file in the root directory) and Apache 2.0 License//  (found in the LICENSE.Apache file in the root directory).#include <gtest/gtest.h>#include <climits>#include <queue>#include <random>#include <utility>#include "util/heap.h"#ifndef GFLAGSconst int64_t FLAGS_iters = 100000;#else#include "util/gflags_compat.h"DEFINE_int64(iters, 100000, "number of pseudo-random operations in each test");#endif  // GFLAGS/* * Compares the custom heap implementation in util/heap.h against * std::priority_queue on a pseudo-random sequence of operations. */namespace ROCKSDB_NAMESPACE {using HeapTestValue = uint64_t;using Params = std::tuple<size_t, HeapTestValue, int64_t>;class HeapTest : public ::testing::TestWithParam<Params> {};TEST_P(HeapTest, Test) {  // This test performs the same pseudorandom sequence of operations on a  // BinaryHeap and an std::priority_queue, comparing output.  The three  // possible operations are insert, replace top and pop.  //  // Insert is chosen slightly more often than the others so that the size of  // the heap slowly grows.  Once the size heats the MAX_HEAP_SIZE limit, we  // disallow inserting until the heap becomes empty, testing the "draining"  // scenario.  const auto MAX_HEAP_SIZE = std::get<0>(GetParam());  const auto MAX_VALUE = std::get<1>(GetParam());  const auto RNG_SEED = std::get<2>(GetParam());  BinaryHeap<HeapTestValue> heap;  std::priority_queue<HeapTestValue> ref;  std::mt19937 rng(static_cast<unsigned int>(RNG_SEED));  std::uniform_int_distribution<HeapTestValue> value_dist(0, MAX_VALUE);  int ndrains = 0;  bool draining = false;     // hit max size, draining until we empty the heap  size_t size = 0;  for (int64_t i = 0; i < FLAGS_iters; ++i) {    if (size == 0) {      draining = false;    }    if (!draining &&        (size == 0 || std::bernoulli_distribution(0.4)(rng))) {      // insert      HeapTestValue val = value_dist(rng);      heap.push(val);      ref.push(val);      ++size;      if (size == MAX_HEAP_SIZE) {        draining = true;        ++ndrains;      }    } else if (std::bernoulli_distribution(0.5)(rng)) {      // replace top      HeapTestValue val = value_dist(rng);      heap.replace_top(val);      ref.pop();      ref.push(val);    } else {      // pop      assert(size > 0);      heap.pop();      ref.pop();      --size;    }    // After every operation, check that the public methods give the same    // results    assert((size == 0) == ref.empty());    ASSERT_EQ(size == 0, heap.empty());    if (size > 0) {      ASSERT_EQ(ref.top(), heap.top());    }  }  // Probabilities should be set up to occasionally hit the max heap size and  // drain it  assert(ndrains > 0);  heap.clear();  ASSERT_TRUE(heap.empty());}// Basic test, MAX_VALUE = 3*MAX_HEAP_SIZE (occasional duplicates)INSTANTIATE_TEST_CASE_P(  Basic, HeapTest,  ::testing::Values(Params(1000, 3000, 0x1b575cf05b708945)));// Mid-size heap with small values (many duplicates)INSTANTIATE_TEST_CASE_P(  SmallValues, HeapTest,  ::testing::Values(Params(100, 10, 0x5ae213f7bd5dccd0)));// Small heap, large value range (no duplicates)INSTANTIATE_TEST_CASE_P(  SmallHeap, HeapTest,  ::testing::Values(Params(10, ULLONG_MAX, 0x3e1fa8f4d01707cf)));// Two-element heapINSTANTIATE_TEST_CASE_P(  TwoElementHeap, HeapTest,  ::testing::Values(Params(2, 5, 0x4b5e13ea988c6abc)));// One-element heapINSTANTIATE_TEST_CASE_P(  OneElementHeap, HeapTest,  ::testing::Values(Params(1, 3, 0x176a1019ab0b612e)));}  // namespace ROCKSDB_NAMESPACEint main(int argc, char** argv) {  ::testing::InitGoogleTest(&argc, argv);#ifdef GFLAGS  GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);#endif  // GFLAGS  return RUN_ALL_TESTS();}
 |