oceanbase/unittest/share/test_ob_occam_timer.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

271 lines
9.8 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 "share/ob_occam_timer.h"
#include <gtest/gtest.h>
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>
#include "common/ob_clock_generator.h"
#include "share/ob_occam_time_guard.h"
namespace oceanbase {
namespace unittest {
using namespace common;
using namespace std;
class TestObOccamTimer: public ::testing::Test
{
public:
TestObOccamTimer() {};
virtual ~TestObOccamTimer() {};
virtual void SetUp() {
thread_pool = new ObOccamThreadPool;
thread_pool->init_and_start(8);
occam_timer = new ObOccamTimer();
occam_timer->init_and_start(*thread_pool, 1000, "Timer");
};
virtual void TearDown() {
delete thread_pool;
delete occam_timer;
ASSERT_EQ(occam::DefaultAllocator::get_default_allocator().total_alive_num, 0);
ASSERT_EQ(function::DefaultFunctionAllocator::get_default_allocator().total_alive_num, 0);
ASSERT_EQ(future::DefaultFutureAllocator::get_default_allocator().total_alive_num, 0);
ASSERT_EQ(guard::DefaultSharedGuardAllocator::get_default_allocator().total_alive_num, 0);
};
ObOccamThreadPool *thread_pool;
ObOccamTimer *occam_timer;
private:
// disallow copy
DISALLOW_COPY_AND_ASSIGN(TestObOccamTimer);
};
void test(int &a) {
ATOMIC_STORE(&a, 2);
}
TEST_F(TestObOccamTimer, normal) {
int ret = OB_SUCCESS;
int a = 1;
ObOccamTimerTaskRAIIHandle task_desc;
ret = occam_timer->schedule_task_after(task_desc, 1_s, [&a](){ test(a); return false; });
this_thread::sleep_for(chrono::milliseconds(1200));
ASSERT_EQ(ret, OB_SUCCESS);
task_desc.stop_and_wait();
task_desc.stop_and_wait();
ASSERT_EQ(ATOMIC_LOAD(&a), 2);
}
TEST_F(TestObOccamTimer, run_2_task_parallel) {
int ret = OB_SUCCESS;
int64_t a = 1;
vector<ObOccamTimerTaskRAIIHandle> v_task_desc(8);
for (int i = 0 ; i < 8; ++i) {
ret = occam_timer->schedule_task_after(v_task_desc[i],
1_ms,
[&a](){
this_thread::sleep_for(chrono::milliseconds(100));
ATOMIC_INC(&a);
OB_LOG(INFO, "inc done", K(ObClockGenerator::getRealClock()));
return false;
});
ASSERT_EQ(ret, OB_SUCCESS);
}
OB_LOG(INFO, "commit done", K(ObClockGenerator::getRealClock()));
this_thread::sleep_for(chrono::milliseconds(200));
OB_LOG(INFO, "read a", K(ObClockGenerator::getRealClock()));
ASSERT_EQ(ATOMIC_LOAD(&a), 9);
for (auto &x : v_task_desc)
x.stop_and_wait();
}
TEST_F(TestObOccamTimer, cancel_task) {
int ret = OB_SUCCESS;
int64_t a = 1;
{
ObUniqueGuard<ObOccamTimerTaskRAIIHandle> handle;
ob_make_unique<ObOccamTimerTaskRAIIHandle>(handle);
occam_timer->schedule_task_repeat(*handle,
10_ms,
[&a](){ this_thread::sleep_for(chrono::milliseconds(100)); ++a; return false; });
}
this_thread::sleep_for(chrono::milliseconds(150));
ASSERT_EQ(ATOMIC_LOAD(&a), 1);
}
TEST_F(TestObOccamTimer, run_repeat_task) {
int ret = OB_SUCCESS;
int64_t a = 1;
ObUniqueGuard<ObOccamTimerTaskRAIIHandle> handle;
ob_make_unique<ObOccamTimerTaskRAIIHandle>(handle);
occam_timer->schedule_task_repeat(*handle,
100_ms,
[&a](){ ++a; return false; });
this_thread::sleep_for(chrono::milliseconds(1050));
ASSERT_EQ(ATOMIC_LOAD(&a), 11);
}
TEST_F(TestObOccamTimer, run_repeat_task_conflict) {
int ret = OB_SUCCESS;
int64_t a = 1;
ObUniqueGuard<ObOccamTimerTaskRAIIHandle> handle;
ob_make_unique<ObOccamTimerTaskRAIIHandle>(handle);
occam_timer->schedule_task_repeat(*handle,
10_ms,
[&a](){ this_thread::sleep_for(chrono::milliseconds(150)); ++a; return false; });
this_thread::sleep_for(chrono::milliseconds(205));
ASSERT_EQ(ATOMIC_LOAD(&a), 2);
}
TEST_F(TestObOccamTimer, stop_task_wait) {
int ret = OB_SUCCESS;
int64_t a = 1;
ObUniqueGuard<ObOccamTimerTaskRAIIHandle> handle;
ob_make_unique<ObOccamTimerTaskRAIIHandle>(handle);
OB_LOG(INFO, "before commit task", K(ObClockGenerator::getRealClock()));
ret = occam_timer->schedule_task_repeat(*handle,
100_ms,
[&a](){
OB_LOG(INFO, "execute task", K(ObClockGenerator::getRealClock()));
this_thread::sleep_for(chrono::milliseconds(500)); ++a;
return false;
});
ASSERT_EQ(ret, OB_SUCCESS);
this_thread::sleep_for(chrono::milliseconds(200));
int64_t time1 = ObClockGenerator::getRealClock();
OB_LOG(INFO, "before wait", K(ObClockGenerator::getRealClock()));
handle->stop_and_wait();
OB_LOG(INFO, "after wait", K(ObClockGenerator::getRealClock()));
int64_t time2 = ObClockGenerator::getRealClock();
cout << time1 << "," << time2 << ",diff:" << time2 - time1 << " a:" << a << endl;
ASSERT_EQ(time2 - time1 > 300_ms, true);
ASSERT_EQ(time2 - time1 < 500_ms, true);
ASSERT_EQ(a, 2);
}
TEST_F(TestObOccamTimer, schedule_task_ignore_handle) {
int ret = OB_SUCCESS;
int64_t a = 1;
ret = occam_timer->schedule_task_ignore_handle_after(100_ms,
[&a]() { ++a; return false; });
ASSERT_EQ(ret, OB_SUCCESS);
this_thread::sleep_for(chrono::milliseconds(350));
ASSERT_EQ(a, 2);
}
TEST_F(TestObOccamTimer, schedule_repeat_ignore_handle_destroyed_in_timer) {
int ret = OB_SUCCESS;
ObSharedGuard<int> p;
ob_make_shared<int>(p, 1);
ObWeakGuard<int> p_w(p);
ret = occam_timer->schedule_task_ignore_handle_repeat_and_immediately(100_ms,
[p]() {
static int b = 0;
if (++b == 2) {
return true;
} else {
return false;
}
});// 将在20ms后析构该任务
ASSERT_EQ(ret, OB_SUCCESS);
this_thread::sleep_for(chrono::milliseconds(250));
p.reset();
ASSERT_EQ(p_w.upgradeable(), false);
}
TEST_F(TestObOccamTimer, hung) {
int ret = OB_SUCCESS;
ObSharedGuard<int> p;
ob_make_shared<int>(p, 1);
ObWeakGuard<int> p_w(p);
ObOccamTimerTaskRAIIHandle *handle = new ObOccamTimerTaskRAIIHandle();
ret = occam_timer->schedule_task_repeat_and_immediately(*handle,
100_ms,
[p]() { return false; });
ASSERT_EQ(ret, OB_SUCCESS);
this_thread::sleep_for(chrono::milliseconds(300));
p.reset();
ASSERT_EQ(p_w.upgradeable(), true);
delete handle;// or will hung
}
TEST_F(TestObOccamTimer, stop_and_wait) {
int ret = OB_SUCCESS;
ret = occam_timer->schedule_task_ignore_handle_repeat(20_s, [](){ return false; });
ASSERT_EQ(ret, OB_SUCCESS);
occam_timer->destroy();
}
TEST_F(TestObOccamTimer, stop_repeat_task_inside_destroy_outside) {
int ret = OB_SUCCESS;
ObOccamTimerTaskRAIIHandle handle;
ret = occam_timer->schedule_task_repeat_and_immediately(handle, 20_ms, [](){ return true; });
ASSERT_EQ(ret, OB_SUCCESS);
std::this_thread::sleep_for(chrono::milliseconds(50));
handle.stop_and_wait();
occam_timer->destroy();
}
TEST_F(TestObOccamTimer, stop_and_destroy_repeat_task_outside) {
int ret = OB_SUCCESS;
ObOccamTimerTaskRAIIHandle handle;
ret = occam_timer->schedule_task_repeat_and_immediately(handle, 20_ms, [](){ return false; });
ASSERT_EQ(ret, OB_SUCCESS);
std::this_thread::sleep_for(chrono::milliseconds(50));
handle.stop_and_wait();
occam_timer->destroy();
}
TEST_F(TestObOccamTimer, test_specify_first_delay) {
int ret = OB_SUCCESS;
ObOccamTimerTaskRAIIHandle handle;
ret = occam_timer->schedule_task_repeat_spcifiy_first_delay(handle, 20_ms, 100_ms, [](){ OB_LOG(INFO, "run task", K(ObClockGenerator::getRealClock())); return false; });
ASSERT_EQ(ret, OB_SUCCESS);
std::this_thread::sleep_for(chrono::milliseconds(505));
handle.stop_and_wait();
occam_timer->destroy();
}
void test_func(const char *function_name = __builtin_FUNCTION(), const char *file = __builtin_FILE(), const int64_t line = __builtin_LINE())
{
OB_LOG(INFO, "print function name", K(function_name), K(file), K(line));
}
void test_func_1()
{
test_func();
}
TEST_F(TestObOccamTimer, test_function_name) {
test_func_1();
}
}
}
int main(int argc, char **argv)
{
system("rm -rf test_ob_occam_timer.log");
oceanbase::common::ObLogger &logger = oceanbase::common::ObLogger::get_logger();
logger.set_file_name("test_ob_occam_timer.log", false);
logger.set_log_level(OB_LOG_LEVEL_DEBUG);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}