Files
oceanbase/deps/oblib/unittest/lib/container/ob_heap_test.cpp
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

212 lines
5.2 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "lib/container/ob_heap.h"
#include <gtest/gtest.h>
using namespace oceanbase::common;
class TestComp
{
public:
int get_error_code() { return OB_SUCCESS; }
bool operator()(int64_t a, int64_t b)
{
return a < b ? true : false;
}
};
class ObHeapTest: public ::testing::Test
{
public:
ObHeapTest();
virtual ~ObHeapTest();
virtual void SetUp();
virtual void TearDown();
private:
// disallow copy
ObHeapTest(const ObHeapTest &other);
ObHeapTest& operator=(const ObHeapTest &other);
private:
// data members
};
ObHeapTest::ObHeapTest()
{
}
ObHeapTest::~ObHeapTest()
{
}
void ObHeapTest::SetUp()
{
}
void ObHeapTest::TearDown()
{
}
TEST_F(ObHeapTest, basic_test)
{
TestComp tc;
ObBinaryHeap<int64_t, TestComp, 30> heap(tc, NULL);
heap.push(1);
heap.push(9);
heap.push(8);
heap.push(7);
heap.push(11);
heap.push(6);
heap.push(4);
ASSERT_EQ(11, heap.top());
int ret = heap.pop();
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(9, heap.top());
ret = heap.pop();
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(8, heap.top());
ret = heap.replace_top(50);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(50, heap.top());
ret = heap.replace_top(23);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(23, heap.top());
ASSERT_EQ(5, heap.count());
}
TEST_F(ObHeapTest, bound_test)
{
TestComp tc;
int ret = 0;
ObArenaAllocator buf;
ObBinaryHeap<int64_t, TestComp, 5> heap(tc, &buf);
ret = heap.push(1);
ASSERT_EQ(ret, OB_SUCCESS);
ret = heap.push(9);
ASSERT_EQ(ret, OB_SUCCESS);
ret = heap.push(8);
ASSERT_EQ(ret, OB_SUCCESS);
ret = heap.push(7);
ASSERT_EQ(ret, OB_SUCCESS);
ret = heap.push(11);
ASSERT_EQ(ret, OB_SUCCESS);
ret = heap.push(6);
ASSERT_EQ(ret, OB_SUCCESS);
ret = heap.push(4);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(11, heap.top());
ret = heap.pop();
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(9, heap.top());
ret = heap.pop();
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(8, heap.top());
ret = heap.replace_top(50);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(50, heap.top());
ret = heap.replace_top(23);
ASSERT_EQ(ret, OB_SUCCESS);
ASSERT_EQ(23, heap.top());
ASSERT_EQ(5, heap.count());
}
class Element
{
public:
explicit Element(int64_t val) : val_(val), pos_(-1) {}
TO_STRING_KV(K(val_), K(pos_));
public:
int64_t val_;
int64_t pos_;
};
class CompElement
{
public:
int get_error_code() { return OB_SUCCESS; }
bool operator()(Element *a, Element *b)
{
return a->val_ < b->val_ ? true : false;
}
};
TEST_F(ObHeapTest, remove_element)
{
int ret = 0;
CompElement tc;
ObArenaAllocator buf;
ObRemovableHeap<Element *, CompElement, &Element::pos_, 5> heap(tc, &buf);
Element e1(1);
Element e9(9);
Element e8(8);
Element e7(7);
Element e11(11);
Element e6(6);
Element e4(4);
ASSERT_EQ(OB_SUCCESS, heap.push(&e1));
ASSERT_EQ(OB_SUCCESS, heap.push(&e9));
ASSERT_EQ(1, e1.pos_);
ASSERT_EQ(OB_SUCCESS, heap.push(&e8));
ASSERT_EQ(OB_SUCCESS, heap.push(&e7));
ASSERT_EQ(OB_SUCCESS, heap.push(&e11));
ASSERT_EQ(OB_SUCCESS, heap.push(&e6));
ASSERT_EQ(OB_SUCCESS, heap.push(&e4));
LIB_LOG(INFO, "check heap", K(heap));
ASSERT_EQ(11, heap.top()->val_);
ASSERT_EQ(0, heap.top()->pos_);
ASSERT_EQ(OB_SUCCESS, heap.pop());
ASSERT_EQ(9, heap.top()->val_);
ASSERT_EQ(0, heap.top()->pos_);
ASSERT_EQ(OB_SUCCESS, heap.remove_by_index(0));
ASSERT_EQ(8, heap.top()->val_);
ASSERT_EQ(OB_SUCCESS, heap.remove(&e6));
LIB_LOG(INFO, "check heap", K(heap));
}
TEST_F(ObHeapTest, remove_random)
{
int ret = 0;
CompElement compare_functor;
ObArenaAllocator arena;
ObRemovableHeap<Element *, CompElement, &Element::pos_, 5> heap(compare_functor, &arena);
const int64_t test_count = 10000L * 10L;
char *buf = (char *)arena.alloc(sizeof(Element) * test_count);
ASSERT_TRUE(nullptr != buf);
for (int64_t i = 0; OB_SUCC(ret) && i < test_count; ++i) {
Element *item = new (buf + sizeof(Element) * i) Element(ObRandom::rand(0, test_count));
ASSERT_EQ(OB_SUCCESS, heap.push(item));
}
int64_t last_val = INT64_MAX;
for (int64_t i = 0; OB_SUCC(ret) && i < test_count; ++i) {
ASSERT_GE(last_val, heap.top()->val_);
last_val = heap.top()->val_;
if (ObRandom::rand(0, test_count) % 3 == 0) {
const int64_t index = ObRandom::rand(0, heap.count() - 1);
ASSERT_EQ(heap.at(index)->pos_, index);
ASSERT_GE(last_val, heap.at(index)->val_);
ASSERT_EQ(OB_SUCCESS, heap.remove_by_index(index));
} else {
ASSERT_EQ(OB_SUCCESS, heap.pop());
}
}
ASSERT_EQ(0, heap.count());
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc,argv);
OB_LOGGER.set_log_level("INFO");
OB_LOGGER.set_file_name("heap_test.log", true);
return RUN_ALL_TESTS();
}