oceanbase/unittest/share/test_ob_guard.cpp
xuhuleon 9dae112952 [FEAT MERGE] merge transfer
Co-authored-by: wxhwang <wxhwang@126.com>
Co-authored-by: godyangfight <godyangfight@gmail.com>
Co-authored-by: Tyshawn <tuyunshan@gmail.com>
2023-06-21 11:42:28 +00:00

385 lines
13 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.
*/
#define UNITTEST_DEBUG
#include "lib/guard/ob_shared_guard.h"
#include "lib/guard/ob_unique_guard.h"
#include "lib/guard/ob_weak_guard.h"
#include "lib/container/ob_se_array.h"
#include <gtest/gtest.h>
#include <iostream>
#include <vector>
namespace oceanbase {
namespace unittest {
using namespace common;
using namespace std;
function::DefaultFunctionAllocator &default_allocator1 = function::DefaultFunctionAllocator::get_default_allocator();
guard::DefaultSharedGuardAllocator &default_allocator2 = guard::DefaultSharedGuardAllocator::get_default_allocator();
guard::DefaultUniqueGuardAllocator &default_allocator3 = guard::DefaultUniqueGuardAllocator::get_default_allocator();
struct TestObj {
TestObj() { ++total_alive_num; }
~TestObj() { --total_alive_num; }
int test() { return 123; }
static int total_alive_num;
};
struct TestObj2 {
TestObj2(int a, const double &b) : a_(a), b_(b) { ++total_alive_num; }
~TestObj2() { --total_alive_num; }
const double &get_b() { return b_; }
static int total_alive_num;
int a_;
const double &b_;
};
class TestObGuard: public ::testing::Test
{
public:
TestObGuard() {};
virtual ~TestObGuard() {};
virtual void SetUp() { };
virtual void TearDown() {
ASSERT_EQ(default_allocator1.total_alive_num, 0);
ASSERT_EQ(default_allocator2.total_alive_num, 0);
ASSERT_EQ(default_allocator3.total_alive_num, 0);
ASSERT_EQ(TestObj::total_alive_num, 0);
ASSERT_EQ(TestObj2::total_alive_num, 0);
};
template <typename T>
guard::BlockPtr<T> &get_block_ptr(ObSharedGuard<T> &ptr) { return ptr.block_ptr_; }
private:
// disallow copy
DISALLOW_COPY_AND_ASSIGN(TestObGuard);
};
int TestObj::total_alive_num = 0;
int TestObj2::total_alive_num = 0;
// ObUniqueGuard
// 测试默认构造函数的行为
TEST_F(TestObGuard, ob_unqiue_guard_default_construction) {
ObUniqueGuard<TestObj> ptr;
ASSERT_EQ(false, ptr.is_valid());
}
// 测试普通构造函数的行为
TEST_F(TestObGuard, ob_unqiue_guard_general_construction) {
TestObj *ptr = new TestObj();
ObUniqueGuard<TestObj> ptr1;
ASSERT_EQ(OB_SUCCESS, ptr1.assign(ptr, [](TestObj* ptr){ delete ptr; }));
ASSERT_EQ(true, ptr1.is_valid());
}
// 测试拷贝构造函数的行为
TEST_F(TestObGuard, ob_unqiue_guard_copy_construction) {
TestObj *ptr = new TestObj();
ObUniqueGuard<TestObj> ptr1;
ASSERT_EQ(OB_SUCCESS, ptr1.assign(ptr, [](TestObj* ptr){ delete ptr; }));
ASSERT_EQ(true, ptr1.is_valid());
ObUniqueGuard<TestObj> ptr2(ptr1);
ASSERT_EQ(false, ptr1.is_valid());
ASSERT_EQ(true, ptr2.is_valid());
ptr2.~ObUniqueGuard();
ASSERT_EQ(false, ptr2.is_valid());
}
// 测试赋值运算符的行为
TEST_F(TestObGuard, ob_unqiue_guard_equal) {
TestObj *ptr = new TestObj();
ObUniqueGuard<TestObj> ptr1;
ASSERT_EQ(OB_SUCCESS, ptr1.assign(ptr, [](TestObj* ptr){ delete ptr; }));
ASSERT_EQ(true, ptr1.is_valid());
ObUniqueGuard<TestObj> ptr2;
ASSERT_EQ(true, ptr1.is_valid());
ASSERT_EQ(false, ptr2.is_valid());
ptr2 = ptr1;
ASSERT_EQ(false, ptr1.is_valid());
ASSERT_EQ(true, ptr2.is_valid());
//ptr2 = ptr2;
ASSERT_EQ(false, ptr1.is_valid());
ASSERT_EQ(true, ptr2.is_valid());
//ptr1 = ptr1;
ASSERT_EQ(false, ptr1.is_valid());
ptr1 = ptr2;
ASSERT_EQ(true, ptr1.is_valid());
ASSERT_EQ(false, ptr2.is_valid());
ptr1.~ObUniqueGuard();
ASSERT_EQ(false, ptr1.is_valid());
}
// 测试assgin的行为
TEST_F(TestObGuard, ob_unqiue_guard_assign) {
ObUniqueGuard<TestObj> ptr1;
TestObj *ptr = new TestObj();
ASSERT_EQ(OB_SUCCESS, ptr1.assign(ptr, [](TestObj* ptr){ delete ptr; }));
ASSERT_EQ(true, ptr1.is_valid());
ASSERT_EQ(ptr, ptr1.get_ptr());
ObUniqueGuard<TestObj> ptr2;
ASSERT_EQ(OB_SUCCESS, ptr2.assign(ptr1));
ASSERT_EQ(false, ptr1.is_valid());
ASSERT_EQ(true, ptr2.is_valid());
ObUniqueGuard<TestObj> ptr3;
ASSERT_EQ(OB_SUCCESS, ptr3.assign(new TestObj(), [](TestObj* ptr){ delete ptr; }));
ASSERT_EQ(OB_SUCCESS, ptr3.assign(ptr2));
ASSERT_EQ(false, ptr1.is_valid());
ASSERT_EQ(false, ptr2.is_valid());
ASSERT_EQ(true, ptr3.is_valid());
}
// 测试reset的行为
TEST_F(TestObGuard, ob_unqiue_guard_reset) {
ObUniqueGuard<TestObj> ptr1;
ASSERT_EQ(OB_SUCCESS, ptr1.assign(new TestObj(), [](TestObj* ptr){ delete ptr; }));
ASSERT_EQ(true, ptr1.is_valid());
ASSERT_NE(nullptr, ptr1.get_ptr());
ptr1.reset();
ASSERT_EQ(false, ptr1.is_valid());
ASSERT_EQ(nullptr, ptr1.get_ptr());
}
// 测试指针的使用行为
TEST_F(TestObGuard, ob_unqiue_guard_use) {
ObUniqueGuard<TestObj> ptr1;
ASSERT_EQ(OB_SUCCESS, ptr1.assign(new TestObj(), [](TestObj* ptr){ delete ptr; }));
ASSERT_EQ(123, ptr1->test());
ASSERT_EQ(123, (*ptr1).test());
}
// 测试make函数
TEST_F(TestObGuard, ob_unqiue_guard_make) {
ObUniqueGuard<TestObj> ptr1;
ASSERT_EQ(OB_SUCCESS, ob_make_unique<TestObj>(ptr1));
auto temp_ptr = ptr1.get_ptr();
ObNullAllocator bad_allocator;
ASSERT_EQ(OB_ALLOCATE_MEMORY_FAILED, ob_alloc_unique<TestObj>(ptr1, bad_allocator));
ASSERT_EQ(temp_ptr, ptr1.get_ptr());
ASSERT_EQ(OB_SUCCESS, ob_make_unique<TestObj>(ptr1));// new ptr
ASSERT_NE(temp_ptr, ptr1.get_ptr());
ObUniqueGuard<TestObj2> ptr2;
double arg = 1.0;
ASSERT_EQ(OB_SUCCESS, ob_make_unique<TestObj2>(ptr2, 1, arg));
ASSERT_EQ(&arg, &(ptr2.get_ptr()->get_b()));
ASSERT_EQ(OB_ALLOCATE_MEMORY_FAILED, ob_alloc_unique<TestObj2>(ptr2, bad_allocator, 1, arg));
ASSERT_EQ(&arg, &(ptr2.get_ptr()->get_b()));
}
// ObSharedGuard
// 测试默认构造函数
TEST_F(TestObGuard, ob_shared_guard_default_construction) {
ObSharedGuard<TestObj> shared_ptr;
ASSERT_EQ(false, shared_ptr.is_valid());
}
// 测试assign
TEST_F(TestObGuard, ob_shared_guard_assign) {
ObNullAllocator bad_allocator;
auto ptr = new TestObj();
ObSharedGuard<TestObj> shared_ptr;
ASSERT_EQ(OB_SUCCESS, shared_ptr.assign(ptr, [](TestObj* ptr){ delete ptr; }));// assign ObSharedGuard
ASSERT_EQ(ptr, get_block_ptr(shared_ptr).data_ptr_);
ASSERT_EQ(true, shared_ptr.is_valid());
ObSharedGuard<TestObj> shared_ptr2;
auto ptr2 = new TestObj();
ASSERT_EQ(OB_ALLOCATE_MEMORY_FAILED, shared_ptr.assign(ptr2, [](TestObj* ptr){ delete ptr; }, bad_allocator));// assign failed cause bad alloc
delete ptr2;
ObSharedGuard<TestObj> shared_ptr3;
ASSERT_EQ(OB_SUCCESS, shared_ptr3.assign(shared_ptr));
ASSERT_EQ(ptr, get_block_ptr(shared_ptr3).data_ptr_);
ObSharedGuard<TestObj> shared_ptr4;
ASSERT_EQ(true, (shared_ptr4 = shared_ptr3).is_valid());
ASSERT_EQ(ptr, get_block_ptr(shared_ptr4).data_ptr_);
}
// 测试拷贝构造函数
TEST_F(TestObGuard, ob_shared_guard_copy_construction) {
ObSharedGuard<TestObj> shared_ptr1;
ASSERT_EQ(OB_SUCCESS, shared_ptr1.assign(new TestObj(), [](TestObj* ptr){ delete ptr; }));
{
ObSharedGuard<TestObj> shared_ptr2(shared_ptr1);
ASSERT_EQ(TestObj::total_alive_num, 1);
}
ASSERT_EQ(TestObj::total_alive_num, 1);
}
// 测试拷贝赋值运算符
TEST_F(TestObGuard, ob_shared_guard_equal) {
ObSharedGuard<TestObj> shared_ptr1;
ASSERT_EQ(OB_SUCCESS, shared_ptr1.assign(new TestObj(), [](TestObj* ptr){ delete ptr; }));
{
ObSharedGuard<TestObj> shared_ptr2;
shared_ptr2 = shared_ptr1;
ASSERT_EQ(TestObj::total_alive_num, 1);
}
ObSharedGuard<TestObj> shared_ptr3;
shared_ptr1 = shared_ptr3;
ASSERT_EQ(TestObj::total_alive_num, 0);
}
struct BigObj {
char data[4096];
};
// 测试unique_gaurd到shared_guard的转化
TEST_F(TestObGuard, ob_shared_guard_from_uique_guard) {
BigObj big;
ObNullAllocator bad_allocator;
ObUniqueGuard<TestObj> uniq_ptr;
ObSharedGuard<TestObj> shared_ptr;
// invalid unique -> shared
ASSERT_EQ(OB_INVALID_ARGUMENT, shared_ptr.assign(uniq_ptr));
auto ptr = new TestObj();
// make a valid shared
ASSERT_EQ(OB_SUCCESS, shared_ptr.assign(ptr, [](TestObj *ptr){ delete ptr; }));
ASSERT_EQ(ptr, shared_ptr.get_ptr());
auto ptr2 = new TestObj();
// assign shared with bad allocator
ASSERT_EQ(OB_ALLOCATE_MEMORY_FAILED, shared_ptr.assign(ptr2, [](TestObj *ptr){ delete ptr; }, bad_allocator));
delete ptr2;
ASSERT_EQ(ptr, shared_ptr.get_ptr());// 强异常安全保证
auto ptr3 = new TestObj();
// make a valid unique
ASSERT_EQ(OB_SUCCESS, uniq_ptr.assign(ptr3, [big](TestObj *ptr){ UNUSED(big); delete ptr; }));
// valid unique -> valid shared, with bad allocator
ASSERT_EQ(OB_ALLOCATE_MEMORY_FAILED, shared_ptr.assign(uniq_ptr, bad_allocator));
ASSERT_EQ(ptr, shared_ptr.get_ptr());// 强异常安全保证
ASSERT_EQ(true, uniq_ptr.is_valid());
// valid unique -> valid shared
ASSERT_EQ(OB_SUCCESS, shared_ptr.assign(uniq_ptr));
ASSERT_EQ(false, uniq_ptr.is_valid());
ASSERT_EQ(ptr3, shared_ptr.get_ptr());
// make a maked unique
ASSERT_EQ(OB_SUCCESS, ob_make_unique<TestObj>(uniq_ptr));
ASSERT_EQ(true, uniq_ptr.is_valid());
// maked unique -> valid shared
ASSERT_EQ(OB_SUCCESS, shared_ptr.assign(uniq_ptr));
ASSERT_NE(ptr3, shared_ptr.get_ptr());
ASSERT_EQ(false, uniq_ptr.is_valid());
shared_ptr.~ObSharedGuard();
}
// 测试make
TEST_F(TestObGuard, ob_shared_guard_make_and_alloc) {
ObNullAllocator bad_allocator;
double a = 1.0;
ObSharedGuard<TestObj2> shared_ptr;
ASSERT_EQ(OB_SUCCESS, ob_make_shared<TestObj2>(shared_ptr, 1, a));
ASSERT_EQ(&a, &shared_ptr->get_b());
ASSERT_EQ(OB_ALLOCATE_MEMORY_FAILED, ob_alloc_shared<TestObj2>(shared_ptr, bad_allocator));
auto ptr = shared_ptr.get_ptr();
ASSERT_EQ(&a, &shared_ptr->get_b());// 强异常安全保证
ASSERT_EQ(OB_SUCCESS, ob_alloc_shared<TestObj2>(shared_ptr, default_allocator1));
new(shared_ptr.get_ptr()) TestObj2(1, a);
ASSERT_NE(ptr, shared_ptr.get_ptr());
}
// ObWeakGuard
// 默认构造函数
TEST_F(TestObGuard, ob_weak_guard_default_construction) {
ObWeakGuard<TestObj> weak_gaurd;
ASSERT_EQ(false, weak_gaurd.is_valid());
}
// 升级构造函数
TEST_F(TestObGuard, ob_weak_guard_upgrade_construction) {
ObSharedGuard<TestObj> shared_ptr;
ASSERT_EQ(OB_SUCCESS, ob_make_shared<TestObj>(shared_ptr));
ObWeakGuard<TestObj> weak_gaurd(shared_ptr);
ASSERT_EQ(true, weak_gaurd.is_valid());
ASSERT_EQ(shared_ptr.get_ptr(), weak_gaurd.upgrade().get_ptr());
}
// 拷贝构造函数
TEST_F(TestObGuard, ob_weak_guard_copy_construction) {
ObSharedGuard<TestObj> shared_ptr;
ASSERT_EQ(OB_SUCCESS, ob_make_shared<TestObj>(shared_ptr));
ObWeakGuard<TestObj> weak_gaurd(shared_ptr);
ASSERT_EQ(true, weak_gaurd.is_valid());
ASSERT_EQ(shared_ptr.get_ptr(), weak_gaurd.upgrade().get_ptr());
ObWeakGuard<TestObj> weak_gaurd2(weak_gaurd);
ASSERT_EQ(shared_ptr.get_ptr(), weak_gaurd2.upgrade().get_ptr());
weak_gaurd2.reset();
ObWeakGuard<TestObj> weak_gaurd3(weak_gaurd2);
ASSERT_EQ(false, weak_gaurd2.is_valid());
ASSERT_EQ(false, weak_gaurd3.is_valid());
}
// 拷贝赋值运算符
TEST_F(TestObGuard, ob_weak_guard_copy_equal) {
ObSharedGuard<TestObj> shared_ptr;
ASSERT_EQ(OB_SUCCESS, ob_make_shared<TestObj>(shared_ptr));
ObWeakGuard<TestObj> weak_gaurd = shared_ptr;// 隐式构造
ObWeakGuard<TestObj> weak_gaurd2;
weak_gaurd2 = shared_ptr;// 隐式构造后赋值
weak_gaurd2 = weak_gaurd;// 同类型赋值,无隐式构造
ObWeakGuard<TestObj> weak_gaurd3;
ASSERT_EQ(OB_SUCCESS, weak_gaurd.assign(weak_gaurd3));
ASSERT_EQ(OB_SUCCESS, weak_gaurd.assign(shared_ptr));
}
// lock operation
TEST_F(TestObGuard, ob_weak_guard_lock) {
{
ObWeakGuard<TestObj> weak_gaurd;
ASSERT_EQ(false, weak_gaurd.upgrade().is_valid());
{
ObSharedGuard<TestObj> shared_ptr;
ASSERT_EQ(OB_SUCCESS, ob_make_shared<TestObj>(shared_ptr));
weak_gaurd = shared_ptr;
}// shared ptr release
ASSERT_EQ(1, default_allocator2.total_alive_num);
ObSharedGuard<TestObj> shared_ptr2 = weak_gaurd.upgrade();
ASSERT_EQ(false, shared_ptr2.is_valid());
ObWeakGuard<TestObj> weak_gaurd2 = weak_gaurd;
ASSERT_EQ(1, default_allocator2.total_alive_num);
weak_gaurd2.~ObWeakGuard();
weak_gaurd.~ObWeakGuard();
ASSERT_EQ(0, default_allocator2.total_alive_num);
}
{
ObWeakGuard<TestObj> weak_gaurd;
{
ObSharedGuard<TestObj> shared_ptr;
ASSERT_EQ(OB_SUCCESS, shared_ptr.assign(new TestObj(), [](TestObj*ptr) { delete ptr; }));
weak_gaurd = shared_ptr;
}// shared ptr release
ASSERT_EQ(1, default_allocator2.total_alive_num);
ObSharedGuard<TestObj> shared_ptr2 = weak_gaurd.upgrade();
ASSERT_EQ(false, shared_ptr2.is_valid());
ObWeakGuard<TestObj> weak_gaurd2 = weak_gaurd;
ASSERT_EQ(1, default_allocator2.total_alive_num);
weak_gaurd2.~ObWeakGuard();
weak_gaurd.~ObWeakGuard();
ASSERT_EQ(0, default_allocator2.total_alive_num);
}
}
}// namespace oceanbase
}// namespace unittest
int main(int argc, char **argv)
{
system("rm -rf test_ob_guard.log");
oceanbase::common::ObLogger &logger = oceanbase::common::ObLogger::get_logger();
logger.set_file_name("test_ob_guard.log", false);
logger.set_log_level(OB_LOG_LEVEL_DEBUG);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}