[FEAT MERGE]OBKV refactoring
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
#ob_unittest(test_manage_tenant omt/test_manage_tenant.cpp)
|
||||
storage_unittest(test_worker_pool omt/test_worker_pool.cpp)
|
||||
storage_unittest(test_hfilter_parser)
|
||||
storage_unittest(test_hfilter_parser table/test_hfilter_parser.cpp)
|
||||
storage_unittest(test_query_response_time mysql/test_query_response_time.cpp)
|
||||
storage_unittest(test_create_executor table/test_create_executor.cpp)
|
||||
storage_unittest(test_table_sess_pool table/test_table_sess_pool.cpp)
|
||||
|
||||
add_subdirectory(rpc EXCLUDE_FROM_ALL)
|
||||
|
||||
546
unittest/observer/table/test_create_executor.cpp
Normal file
546
unittest/observer/table/test_create_executor.cpp
Normal file
@ -0,0 +1,546 @@
|
||||
#include <gtest/gtest.h>
|
||||
#define private public // 获取private成员
|
||||
#define protected public // 获取protect成员
|
||||
#include "observer/table/ob_table_cg_service.h"
|
||||
#include "observer/table/ob_table_cache.h"
|
||||
#include "../share/schema/mock_schema_service.h"
|
||||
#include "sql/code_generator/ob_static_engine_cg.h"
|
||||
#include "sql/plan_cache/ob_plan_cache_manager.h"
|
||||
#include "lib/net/ob_addr.h"
|
||||
#include "sql/plan_cache/ob_lib_cache_register.h"
|
||||
#include "observer/ob_req_time_service.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::table;
|
||||
using namespace oceanbase::sql;
|
||||
using namespace oceanbase::share::schema;
|
||||
using namespace oceanbase::observer;
|
||||
|
||||
// copy from test_table_schema.cpp
|
||||
void fill_table_schema(ObTableSchema &table)
|
||||
{
|
||||
table.set_tenant_id(1);
|
||||
table.set_database_id(1);
|
||||
table.set_tablegroup_id(1);
|
||||
table.set_table_id(3001);
|
||||
table.set_max_used_column_id(16);
|
||||
table.set_rowkey_column_num(0);
|
||||
table.set_index_column_num(0);
|
||||
table.set_rowkey_split_pos(11);
|
||||
table.set_progressive_merge_num(11);
|
||||
table.set_compress_func_name(ObString::make_string("snappy_1.0"));
|
||||
table.set_autoinc_column_id(0);
|
||||
table.set_auto_increment(1);
|
||||
table.set_load_type(TABLE_LOAD_TYPE_IN_DISK);
|
||||
table.set_def_type(TABLE_DEF_TYPE_USER);
|
||||
table.set_part_level(PARTITION_LEVEL_TWO);
|
||||
table.set_charset_type(CHARSET_UTF8MB4);
|
||||
table.set_collation_type(CS_TYPE_UTF8MB4_BIN);
|
||||
table.set_table_type(USER_TABLE);
|
||||
table.set_index_type(INDEX_TYPE_IS_NOT);
|
||||
table.set_index_status(INDEX_STATUS_AVAILABLE);
|
||||
table.set_data_table_id(0);
|
||||
table.set_is_use_bloomfilter(false);
|
||||
table.set_block_size(2097152);
|
||||
table.set_tablegroup_name("table group name 1");
|
||||
table.set_comment("This is a table");
|
||||
table.set_table_name("table_xxx");
|
||||
table.set_expire_info("expire: modify_time > 3000s");
|
||||
table.set_schema_version(1);
|
||||
table.get_part_option().set_part_func_type(PARTITION_FUNC_TYPE_HASH);
|
||||
table.get_part_option().set_part_expr (ObString::make_string("rand() mod 111"));
|
||||
table.get_part_option().set_part_num(100);
|
||||
table.get_sub_part_option().set_part_func_type(PARTITION_FUNC_TYPE_HASH);
|
||||
table.get_sub_part_option().set_part_expr (ObString::make_string("rand() mod 111"));
|
||||
table.get_sub_part_option().set_part_num(666);
|
||||
}
|
||||
// 填充一个column_schema,类型:ObIntType
|
||||
// rowkey_pos: >0时为rowkey列,表示rowkey的顺序
|
||||
// index_key_pos:>0时为索引列,表示索引列顺序
|
||||
// part_key_pos:>0时为分区键,表示分区间顺序
|
||||
void fill_column_schema(ObColumnSchemaV2 &column, uint64_t id, const char *name,
|
||||
uint64_t rowkey_pos = 1, uint64_t index_key_pos = 1,
|
||||
uint64_t part_key_pos = 1, ObOrderType rowkey_order = ObOrderType::ASC)
|
||||
{
|
||||
ObObj value;
|
||||
column.set_column_id(id);
|
||||
column.set_column_name(ObString::make_string(name));
|
||||
column.set_rowkey_position(rowkey_pos);
|
||||
column.set_order_in_rowkey(rowkey_order);
|
||||
column.set_tbl_part_key_pos(part_key_pos);
|
||||
column.set_index_position(index_key_pos);
|
||||
column.set_data_length(100);
|
||||
column.set_data_precision(1100);
|
||||
column.set_data_scale(88);
|
||||
column.set_nullable(false);
|
||||
column.set_charset_type(CHARSET_UTF8MB4);
|
||||
column.set_collation_type(CS_TYPE_UTF8MB4_BIN);
|
||||
column.set_data_type(ObIntType);
|
||||
value.set_int(100);
|
||||
column.set_orig_default_value(value);
|
||||
value.set_int(101);
|
||||
column.set_cur_default_value(value);
|
||||
column.set_comment("black gives me black eyes");
|
||||
}
|
||||
|
||||
// create table test (C1, C2, C3)
|
||||
void create_table_schema(ObTableSchema *table_schema, ObColumnSchemaV2 *columns)
|
||||
{
|
||||
ASSERT_NE(nullptr, table_schema);
|
||||
fill_table_schema(*table_schema);
|
||||
fill_column_schema(columns[0], 1, "C1", 1, 1, 1);
|
||||
fill_column_schema(columns[1], 2, "C2", 0, 0, 0);
|
||||
fill_column_schema(columns[2], 3, "C3", 0, 0, 0);
|
||||
ASSERT_EQ(OB_SUCCESS, table_schema->add_column(columns[0]));
|
||||
ASSERT_EQ(OB_SUCCESS, table_schema->add_column(columns[1]));
|
||||
ASSERT_EQ(OB_SUCCESS, table_schema->add_column(columns[2]));
|
||||
ASSERT_EQ(1, table_schema->get_tenant_id());
|
||||
ASSERT_EQ(1, table_schema->get_database_id());
|
||||
ASSERT_EQ(1, table_schema->get_tablegroup_id());
|
||||
ASSERT_EQ(3001, table_schema->get_table_id());
|
||||
ASSERT_EQ(3, table_schema->get_column_count());
|
||||
ASSERT_EQ(1, table_schema->get_index_column_num());
|
||||
ASSERT_EQ(1, table_schema->get_rowkey_column_num());
|
||||
ASSERT_EQ(1, table_schema->get_partition_key_column_num());
|
||||
}
|
||||
|
||||
ObTableApiSessNodeVal g_sess_node_val(1, NULL);
|
||||
void fake_ctx_init_common(ObTableCtx &fake_ctx, ObTableSchema *table_schema)
|
||||
{
|
||||
fake_ctx.table_schema_ = table_schema;
|
||||
fake_ctx.tenant_id_ = table_schema->get_tenant_id();
|
||||
fake_ctx.database_id_ = table_schema->get_database_id();
|
||||
fake_ctx.table_name_ = table_schema->get_table_name();
|
||||
fake_ctx.ref_table_id_ = table_schema->get_table_id();
|
||||
fake_ctx.index_tablet_id_ = table_schema->get_table_id();
|
||||
fake_ctx.sess_guard_.sess_node_val_ = &g_sess_node_val;
|
||||
g_sess_node_val.is_inited_ = true;
|
||||
g_sess_node_val.sess_info_.test_init(0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
class TestCreateExecutor: public ::testing::Test
|
||||
{
|
||||
public:
|
||||
TestCreateExecutor();
|
||||
virtual ~TestCreateExecutor() {}
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
public:
|
||||
ObArenaAllocator allocator_;
|
||||
MockSchemaService schema_service_;
|
||||
ObSchemaGetterGuard schema_guard_;
|
||||
ObTableSchema table_schema_;
|
||||
ObColumnSchemaV2 columns_[3];
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(TestCreateExecutor);
|
||||
};
|
||||
|
||||
TestCreateExecutor::TestCreateExecutor()
|
||||
: allocator_()
|
||||
{
|
||||
}
|
||||
|
||||
void TestCreateExecutor::SetUp()
|
||||
{
|
||||
schema_service_.init();
|
||||
create_table_schema(&table_schema_, columns_);
|
||||
schema_service_.add_table_schema(table_schema_, 1);
|
||||
}
|
||||
|
||||
void TestCreateExecutor::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, scan)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
ObExprFrameInfo fake_expr_info(allocator_);
|
||||
// init ctx
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.init_get());
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ASSERT_EQ(columns_[i].get_column_id(), fake_ctx.select_col_ids_.at(i));
|
||||
ASSERT_EQ(columns_[i].get_meta_type(), fake_ctx.select_metas_.at(i));
|
||||
}
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info));
|
||||
fake_ctx.set_expr_info(&fake_expr_info);
|
||||
ASSERT_EQ(3, fake_ctx.get_all_exprs().get_expr_array().count());
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.classify_scan_exprs());
|
||||
ASSERT_EQ(3, fake_ctx.select_exprs_.count());
|
||||
ASSERT_EQ(1, fake_ctx.rowkey_exprs_.count());
|
||||
|
||||
ObTableApiSpec *root_spec = nullptr;
|
||||
ObTableApiExecutor *executor = nullptr;
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableSpecCgService::generate<TABLE_API_EXEC_SCAN>(allocator_, fake_ctx, root_spec));
|
||||
ASSERT_TRUE(nullptr != root_spec);
|
||||
ASSERT_EQ(TABLE_API_EXEC_SCAN, root_spec->get_type());
|
||||
ASSERT_EQ(nullptr, root_spec->get_parent());
|
||||
ASSERT_EQ(nullptr, root_spec->get_child());
|
||||
|
||||
ASSERT_EQ(OB_SUCCESS, root_spec->create_executor(fake_ctx, executor));
|
||||
ASSERT_TRUE(nullptr != executor);
|
||||
ObTableApiScanExecutor *scan_executor = dynamic_cast<ObTableApiScanExecutor *>(executor);
|
||||
ASSERT_TRUE(nullptr != scan_executor);
|
||||
ASSERT_EQ(nullptr, executor->get_parent());
|
||||
ASSERT_EQ(nullptr, executor->get_child());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, insert)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
ObExprFrameInfo fake_expr_info(allocator_);
|
||||
// init ctx
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.init_insert());
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info));
|
||||
fake_ctx.set_expr_info(&fake_expr_info);
|
||||
ASSERT_EQ(3, fake_ctx.get_all_exprs().get_expr_array().count());
|
||||
|
||||
ObTableApiSpec *root_spec = nullptr;
|
||||
ObTableApiExecutor *executor = nullptr;
|
||||
|
||||
// generate insert spec tree
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableSpecCgService::generate<TABLE_API_EXEC_INSERT>(allocator_, fake_ctx, root_spec));
|
||||
ASSERT_TRUE(nullptr != root_spec);
|
||||
ASSERT_EQ(TABLE_API_EXEC_INSERT, root_spec->get_type());
|
||||
ASSERT_EQ(nullptr, root_spec->get_parent());
|
||||
ASSERT_EQ(nullptr, root_spec->get_child());
|
||||
|
||||
// create insert excutor tree;
|
||||
ASSERT_EQ(OB_SUCCESS, root_spec->create_executor(fake_ctx, executor));
|
||||
ASSERT_TRUE(nullptr != executor);
|
||||
ObTableApiInsertExecutor *ins_executor = dynamic_cast<ObTableApiInsertExecutor *>(executor);
|
||||
ASSERT_TRUE(nullptr != ins_executor);
|
||||
ASSERT_EQ(nullptr, executor->get_parent());
|
||||
ASSERT_EQ(nullptr, executor->get_child());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, delete)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
ObExprFrameInfo fake_expr_info(allocator_);
|
||||
// init ctx
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.init_delete());
|
||||
ASSERT_EQ(3, fake_ctx.select_col_ids_.count());
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info));
|
||||
fake_ctx.set_expr_info(&fake_expr_info);
|
||||
ASSERT_EQ(3, fake_ctx.get_all_exprs().get_expr_array().count());
|
||||
ObTableApiSpec *root_spec = nullptr;
|
||||
ObTableApiExecutor *executor = nullptr;
|
||||
|
||||
// generate delete spec tree
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableSpecCgService::generate<TABLE_API_EXEC_DELETE>(allocator_, fake_ctx, root_spec));
|
||||
ASSERT_TRUE(nullptr != root_spec);
|
||||
ASSERT_EQ(TABLE_API_EXEC_DELETE, root_spec->get_type());
|
||||
ASSERT_EQ(nullptr, root_spec->get_parent());
|
||||
ASSERT_TRUE(nullptr != root_spec->get_child());
|
||||
|
||||
// check child spec (scan)
|
||||
const ObTableApiScanSpec *child_spec = dynamic_cast<const ObTableApiScanSpec *>(root_spec->get_child());
|
||||
ASSERT_TRUE(nullptr != child_spec);
|
||||
ASSERT_EQ(nullptr, child_spec->get_child());
|
||||
ASSERT_EQ(root_spec, child_spec->get_parent());
|
||||
|
||||
// create executor tree
|
||||
ASSERT_EQ(OB_SUCCESS, root_spec->create_executor(fake_ctx, executor));
|
||||
ASSERT_TRUE(nullptr != executor);
|
||||
ObTableApiDeleteExecutor *del_executor = dynamic_cast<ObTableApiDeleteExecutor *>(executor);
|
||||
ASSERT_TRUE(nullptr != del_executor);
|
||||
ASSERT_EQ(nullptr, del_executor->get_parent());
|
||||
ASSERT_TRUE(nullptr != del_executor->get_child());
|
||||
|
||||
// check child executor (scan)
|
||||
const ObTableApiScanExecutor *scan_executor = dynamic_cast<const ObTableApiScanExecutor *>(del_executor->get_child());
|
||||
ASSERT_TRUE(nullptr != scan_executor);
|
||||
ASSERT_EQ(del_executor, scan_executor->get_parent());
|
||||
ASSERT_EQ(nullptr, scan_executor->get_child());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, update)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
ObExprFrameInfo fake_expr_info(allocator_);
|
||||
// prepare
|
||||
ObTableEntity entity;
|
||||
ObObj obj;
|
||||
obj.set_int(1234);
|
||||
entity.add_rowkey_value(obj);
|
||||
entity.set_property(ObString::make_string("C2"), obj);
|
||||
// init ctx
|
||||
fake_ctx.set_entity(&entity);
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.init_update());
|
||||
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info));
|
||||
fake_ctx.set_expr_info(&fake_expr_info);
|
||||
ASSERT_EQ(6, fake_ctx.get_all_exprs().get_expr_array().count());
|
||||
ObTableApiSpec *root_spec = nullptr;
|
||||
ObTableApiExecutor *executor = nullptr;
|
||||
// generate update spec tree
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableSpecCgService::generate<TABLE_API_EXEC_UPDATE>(allocator_, fake_ctx, root_spec));
|
||||
ASSERT_TRUE(nullptr != root_spec);
|
||||
ASSERT_EQ(TABLE_API_EXEC_UPDATE, root_spec->get_type());
|
||||
ASSERT_EQ(nullptr, root_spec->get_parent());
|
||||
ASSERT_TRUE(nullptr != root_spec->get_child());
|
||||
|
||||
// check child spec (scan)
|
||||
const ObTableApiScanSpec *child_spec = dynamic_cast<const ObTableApiScanSpec *>(root_spec->get_child());
|
||||
ASSERT_TRUE(nullptr != child_spec);
|
||||
ASSERT_EQ(nullptr, child_spec->get_child());
|
||||
ASSERT_EQ(root_spec, child_spec->get_parent());
|
||||
|
||||
// create executor tree
|
||||
ASSERT_EQ(OB_SUCCESS, root_spec->create_executor(fake_ctx, executor));
|
||||
ASSERT_TRUE(nullptr != executor);
|
||||
ObTableApiUpdateExecutor *upd_executor = dynamic_cast<ObTableApiUpdateExecutor *>(executor);
|
||||
ASSERT_TRUE(nullptr != upd_executor);
|
||||
ASSERT_EQ(nullptr, upd_executor->get_parent());
|
||||
ASSERT_TRUE(nullptr != upd_executor->get_child());
|
||||
|
||||
// check child executor (scan)
|
||||
const ObTableApiScanExecutor *scan_executor = dynamic_cast<const ObTableApiScanExecutor *>(upd_executor->get_child());
|
||||
ASSERT_TRUE(nullptr != scan_executor);
|
||||
ASSERT_EQ(upd_executor, scan_executor->get_parent());
|
||||
ASSERT_EQ(nullptr, scan_executor->get_child());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, insertup)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
ObExprFrameInfo fake_expr_info(allocator_);
|
||||
ObTableEntity entity;
|
||||
ObObj obj;
|
||||
obj.set_int(1234);
|
||||
entity.add_rowkey_value(obj);
|
||||
entity.set_property(ObString::make_string("C2"), obj);
|
||||
// init ctx
|
||||
fake_ctx.set_entity(&entity);
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.init_insert_up());
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info));
|
||||
fake_ctx.set_expr_info(&fake_expr_info);
|
||||
ASSERT_EQ(6, fake_ctx.get_all_exprs().get_expr_array().count());
|
||||
ObTableApiSpec *root_spec = nullptr;
|
||||
ObTableApiExecutor *executor = nullptr;
|
||||
|
||||
// generate insertup spec tree
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableSpecCgService::generate<TABLE_API_EXEC_INSERT_UP>(allocator_, fake_ctx, root_spec));
|
||||
ASSERT_TRUE(nullptr != root_spec);
|
||||
ASSERT_EQ(TABLE_API_EXEC_INSERT_UP, root_spec->get_type());
|
||||
ASSERT_EQ(nullptr, root_spec->get_parent());
|
||||
ASSERT_EQ(nullptr, root_spec->get_child());
|
||||
|
||||
// create insertup excutor tree;
|
||||
ASSERT_EQ(OB_SUCCESS, root_spec->create_executor(fake_ctx, executor));
|
||||
ASSERT_TRUE(nullptr != executor);
|
||||
ObTableApiInsertUpExecutor *insup_executor = dynamic_cast<ObTableApiInsertUpExecutor *>(executor);
|
||||
ASSERT_TRUE(nullptr != insup_executor);
|
||||
ASSERT_EQ(nullptr, executor->get_parent());
|
||||
ASSERT_EQ(nullptr, executor->get_child());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, replace)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
ObExprFrameInfo fake_expr_info(allocator_);
|
||||
// init ctx
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.init_replace());
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info));
|
||||
fake_ctx.set_expr_info(&fake_expr_info);
|
||||
ASSERT_EQ(3, fake_ctx.get_all_exprs().get_expr_array().count());
|
||||
ObTableApiSpec *root_spec = nullptr;
|
||||
ObTableApiExecutor *executor = nullptr;
|
||||
|
||||
// generate replace spec tree
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableSpecCgService::generate<TABLE_API_EXEC_REPLACE>(allocator_, fake_ctx, root_spec));
|
||||
ASSERT_TRUE(nullptr != root_spec);
|
||||
ASSERT_EQ(TABLE_API_EXEC_REPLACE, root_spec->get_type());
|
||||
ASSERT_EQ(nullptr, root_spec->get_parent());
|
||||
ASSERT_EQ(nullptr, root_spec->get_child());
|
||||
|
||||
// create replace excutor tree;
|
||||
ASSERT_EQ(OB_SUCCESS, root_spec->create_executor(fake_ctx, executor));
|
||||
ASSERT_TRUE(nullptr != executor);
|
||||
ObTableApiReplaceExecutor *replace_executor = dynamic_cast<ObTableApiReplaceExecutor *>(executor);
|
||||
ASSERT_TRUE(nullptr != replace_executor);
|
||||
ASSERT_EQ(nullptr, executor->get_parent());
|
||||
ASSERT_EQ(nullptr, executor->get_child());
|
||||
}
|
||||
|
||||
// refresh frame: init_datum_param_store + check_entity + refresh_rowkey_exprs_frame + refresh_properties_exprs_frame
|
||||
TEST_F(TestCreateExecutor, refresh_exprs_frame)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
ObExprFrameInfo fake_expr_info(allocator_);
|
||||
ObTableEntity entity;
|
||||
ObStaticEngineCG cg;
|
||||
// prepare data
|
||||
ObObj obj;
|
||||
obj.set_int(1234);
|
||||
entity.add_rowkey_value(obj);
|
||||
obj.set_int(1235);
|
||||
entity.set_property(ObString::make_string("C2"), obj);
|
||||
// init ctx
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.init_insert());
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::generate_exprs(fake_ctx, allocator_, fake_expr_info));
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::alloc_exprs_memory(fake_ctx, fake_expr_info));
|
||||
fake_ctx.set_expr_info(&fake_expr_info);
|
||||
ASSERT_EQ(3, fake_ctx.get_all_exprs().get_expr_array().count());
|
||||
ObArray<ObExpr *> rt_exprs;
|
||||
ASSERT_EQ(OB_SUCCESS, cg.generate_rt_exprs(fake_ctx.get_all_exprs().get_expr_array(), rt_exprs));
|
||||
|
||||
ASSERT_EQ(OB_SUCCESS, ObTableExprCgService::refresh_exprs_frame(fake_ctx, rt_exprs, entity));
|
||||
// verify the refresh value
|
||||
ObEvalCtx eval_ctx(fake_ctx.get_exec_ctx());
|
||||
ObDatum *datum = nullptr;
|
||||
ObExpr *rt_expr = nullptr;
|
||||
ObObj objs[3];
|
||||
const ObIArray<ObRawExpr *> &all_exprs = fake_ctx.get_all_exprs().get_expr_array();
|
||||
for (int i = 0; i < all_exprs.count(); i++) {
|
||||
ASSERT_EQ(OB_SUCCESS, cg.generate_rt_expr(*all_exprs.at(i), rt_expr));
|
||||
ASSERT_EQ(OB_SUCCESS, rt_expr->eval(eval_ctx, datum));
|
||||
ASSERT_EQ(OB_SUCCESS, datum->to_obj(objs[i], columns_[i].get_meta_type()));
|
||||
}
|
||||
ASSERT_EQ(1234, objs[0].get_int());
|
||||
ASSERT_EQ(1235, objs[1].get_int());
|
||||
// column default value
|
||||
ASSERT_EQ(101, objs[2].get_int());
|
||||
}
|
||||
|
||||
// table context
|
||||
TEST_F(TestCreateExecutor, cons_column_type)
|
||||
{
|
||||
ObColumnSchemaV2 col_schema;
|
||||
// prepare data
|
||||
col_schema.set_data_type(ObVarcharType);
|
||||
col_schema.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
|
||||
ObAccuracy acc(1);
|
||||
col_schema.set_accuracy(acc);
|
||||
uint32_t res_flag = ObRawExprUtils::calc_column_result_flag(col_schema);
|
||||
|
||||
ObExprResType column_type;
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.cons_column_type(col_schema, column_type));
|
||||
ASSERT_EQ(ObVarcharType, column_type.get_type());
|
||||
ASSERT_EQ(res_flag, column_type.get_result_flag());
|
||||
ASSERT_EQ(CS_TYPE_UTF8MB4_GENERAL_CI, column_type.get_collation_type());
|
||||
ASSERT_EQ(CS_LEVEL_IMPLICIT, column_type.get_collation_level());
|
||||
ASSERT_EQ(1, column_type.get_accuracy().get_length());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, check_column_type)
|
||||
{
|
||||
ObExprResType column_type;
|
||||
ObObj obj;
|
||||
uint32_t res_flag = 0;
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
schema_service_.get_schema_guard(fake_ctx.schema_guard_, 1);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
|
||||
// check nullable
|
||||
obj.set_null();
|
||||
res_flag |= NOT_NULL_FLAG;
|
||||
column_type.set_result_flag(res_flag);
|
||||
ASSERT_EQ(OB_BAD_NULL_ERROR, fake_ctx.check_column_type(column_type, obj));
|
||||
// check data type mismatch
|
||||
res_flag = 0;
|
||||
obj.set_int(1);
|
||||
column_type.set_result_flag(res_flag);
|
||||
column_type.set_type(ObVarcharType);
|
||||
ASSERT_EQ(OB_OBJ_TYPE_ERROR, fake_ctx.check_column_type(column_type, obj));
|
||||
// check collation
|
||||
obj.set_binary("ttt");
|
||||
column_type.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
|
||||
ASSERT_EQ(OB_ERR_COLLATION_MISMATCH, fake_ctx.check_column_type(column_type, obj));
|
||||
// collation convert
|
||||
obj.set_varchar("test");
|
||||
obj.set_collation_type(CS_TYPE_UTF8MB4_BIN);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.check_column_type(column_type, obj));
|
||||
ASSERT_EQ(CS_TYPE_UTF8MB4_GENERAL_CI, obj.get_collation_type());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, generate_key_range)
|
||||
{
|
||||
ObTableCtx fake_ctx(allocator_);
|
||||
fake_ctx_init_common(fake_ctx, &table_schema_);
|
||||
// prepare data
|
||||
ObArray<ObNewRange> scan_ranges;
|
||||
ObObj pk_objs_start[1];
|
||||
pk_objs_start[0].set_int(0);
|
||||
ObObj pk_objs_end[1];
|
||||
pk_objs_end[0].set_max_value();
|
||||
ObNewRange range;
|
||||
range.start_key_.assign(pk_objs_start, 1);
|
||||
range.end_key_.assign(pk_objs_end, 1);
|
||||
range.border_flag_.set_inclusive_start();
|
||||
range.border_flag_.set_inclusive_end();
|
||||
scan_ranges.push_back(range);
|
||||
ASSERT_EQ(OB_SUCCESS, fake_ctx.generate_key_range(scan_ranges));
|
||||
// primary key range
|
||||
ASSERT_EQ(1, fake_ctx.get_key_ranges().count());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateExecutor, test_cache)
|
||||
{
|
||||
ObAddr addr;
|
||||
ObPCMemPctConf conf;
|
||||
ObPlanCacheManager lib_cache_mgr;
|
||||
ObLibCacheNameSpace ns = ObLibCacheNameSpace::NS_TABLEAPI;
|
||||
uint64_t tenant_id = 1;
|
||||
ObReqTimeGuard req_timeinfo_guard;
|
||||
// register cache obj
|
||||
ObLibCacheRegister::register_cache_objs();
|
||||
//init lib cache manager
|
||||
ASSERT_EQ(OB_SUCCESS, lib_cache_mgr.init(addr));
|
||||
// get lib cache
|
||||
ObPlanCache *lib_cache = lib_cache_mgr.get_or_create_plan_cache(tenant_id, conf);
|
||||
ASSERT_TRUE(nullptr != lib_cache);
|
||||
// construct cache key
|
||||
ObTableApiCacheKey cache_key(1001, 1001, 1, ObTableOperationType::Type::INSERT);
|
||||
// construct ctx
|
||||
ObILibCacheCtx ctx;
|
||||
// construct cache obj
|
||||
{
|
||||
ObCacheObjGuard guard(CacheRefHandleID::TABLEAPI_NODE_HANDLE);
|
||||
ASSERT_EQ(OB_SUCCESS, lib_cache->alloc_cache_obj(guard, ns, tenant_id));
|
||||
ObILibCacheObject *cache_obj = guard.get_cache_obj();
|
||||
ASSERT_TRUE(nullptr != cache_obj);
|
||||
ObTableApiCacheObj *table_cache_obj = static_cast<ObTableApiCacheObj *>(cache_obj);
|
||||
ObIAllocator &cache_allocator = table_cache_obj->get_allocator();
|
||||
// construct spec
|
||||
ObTableApiInsertSpec spec(cache_allocator, TABLE_API_EXEC_INSERT);
|
||||
table_cache_obj->set_spec(&spec);
|
||||
// add an cache obj
|
||||
ASSERT_EQ(OB_SUCCESS, lib_cache->add_cache_obj(ctx, &cache_key , table_cache_obj));
|
||||
}
|
||||
// get cache obj
|
||||
{
|
||||
ObCacheObjGuard guard(CacheRefHandleID::TABLEAPI_NODE_HANDLE);
|
||||
ASSERT_EQ(OB_SUCCESS, lib_cache->get_cache_obj(ctx, &cache_key, guard));
|
||||
ObTableApiCacheObj *cache_obj = static_cast<ObTableApiCacheObj *>(guard.get_cache_obj());
|
||||
ASSERT_TRUE(nullptr != cache_obj);
|
||||
ObTableApiSpec *spec = cache_obj->get_spec();
|
||||
ASSERT_TRUE(nullptr != spec);
|
||||
ASSERT_EQ(TABLE_API_EXEC_INSERT, spec->type_);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
OB_LOGGER.set_log_level("INFO");
|
||||
OB_LOGGER.set_file_name("test_create_executor.log", true);
|
||||
::testing::InitGoogleTest(&argc,argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@ -101,9 +101,9 @@ void TestHFilterParser::do_parse(const char *filter_cstr, std::ofstream &of_resu
|
||||
|
||||
TEST_F(TestHFilterParser, basic_test)
|
||||
{
|
||||
const char* test_file = "./hfilter_parser.test";
|
||||
const char* result_file = "./hfilter_parser.result";
|
||||
const char* tmp_file = "./hfilter_parser.tmp";
|
||||
const char* test_file = "./table/hfilter_parser.test";
|
||||
const char* result_file = "./table/hfilter_parser.result";
|
||||
const char* tmp_file = "./table/hfilter_parser.tmp";
|
||||
// run tests
|
||||
std::ifstream if_tests(test_file);
|
||||
ASSERT_TRUE(if_tests.is_open());
|
||||
222
unittest/observer/table/test_table_sess_pool.cpp
Normal file
222
unittest/observer/table/test_table_sess_pool.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
#include <gtest/gtest.h>
|
||||
#define private public // 获取私有成员
|
||||
#include "observer/table/ob_table_session_pool.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::table;
|
||||
using namespace oceanbase::sql;
|
||||
|
||||
class TestTableSessPool: public ::testing::Test
|
||||
{
|
||||
public:
|
||||
const int64_t TENANT_CNT = 10;
|
||||
const int64_t USER_CNT = 100;
|
||||
const int64_t NODE_CNT = 100;
|
||||
const int64_t SESS_CNT = 10;
|
||||
public:
|
||||
TestTableSessPool() {}
|
||||
virtual ~TestTableSessPool() {}
|
||||
void prepare_sess_pool(ObTableApiSessPoolMgr &mgr);
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(TestTableSessPool);
|
||||
};
|
||||
|
||||
// 10租户,100用户,每个用户下面挂10个session
|
||||
void TestTableSessPool::prepare_sess_pool(ObTableApiSessPoolMgr &mgr)
|
||||
{
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.init());
|
||||
uint64_t tenant_ids[TENANT_CNT];
|
||||
uint64_t user_ids[USER_CNT];
|
||||
ObTableApiSessPoolGuard pool_guards[TENANT_CNT];
|
||||
for (uint64_t i = 0; i < TENANT_CNT; i++) {
|
||||
tenant_ids[i] = i + 1001;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.extend_sess_pool(tenant_ids[i], pool_guards[i]));
|
||||
ObTableApiSessPool *tmp_pool = pool_guards[i].get_sess_pool();
|
||||
ASSERT_NE(nullptr, tmp_pool);
|
||||
for (uint64_t j = 0; j < USER_CNT; j++) {
|
||||
user_ids[j] = j;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.get_session_pool(tenant_ids[i], pool_guards[i]));
|
||||
ObTableApiSessPool *pool = pool_guards[i].get_sess_pool();
|
||||
ASSERT_NE(nullptr, pool);
|
||||
ObTableApiCredential credential;
|
||||
credential.tenant_id_ = tenant_ids[i];
|
||||
credential.user_id_ = user_ids[j];
|
||||
ASSERT_EQ(OB_SUCCESS, pool->update_sess(credential));
|
||||
ObTableApiSessNode *node = nullptr;
|
||||
ASSERT_EQ(OB_SUCCESS, tmp_pool->get_sess_node(user_ids[j], node));
|
||||
ASSERT_NE(nullptr, node);
|
||||
for (int64_t k = 0; k < SESS_CNT; k++) {
|
||||
void *buf = node->allocator_.alloc(sizeof(ObTableApiSessNodeVal));
|
||||
ASSERT_NE(nullptr, buf);
|
||||
ObTableApiSessNodeVal *val = new (buf) ObTableApiSessNodeVal(tenant_ids[i], node);
|
||||
val->is_inited_ = true;
|
||||
ASSERT_EQ(true, node->sess_lists_.free_list_.add_last(val));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestTableSessPool, get_session)
|
||||
{
|
||||
uint64_t tenant_id = 1;
|
||||
uint64_t user_id = 0;
|
||||
uint64_t key = user_id;
|
||||
ObTableApiSessPoolMgr mgr;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.init());
|
||||
ObTableApiSessPoolGuard pool_guard;
|
||||
ASSERT_EQ(OB_HASH_NOT_EXIST, mgr.get_session_pool(tenant_id, pool_guard));
|
||||
ASSERT_EQ(nullptr, pool_guard.get_sess_pool());
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.extend_sess_pool(tenant_id, pool_guard));
|
||||
ObTableApiSessPool *pool = pool_guard.get_sess_pool();
|
||||
ASSERT_TRUE(nullptr != pool);
|
||||
ASSERT_TRUE(pool->is_inited_);
|
||||
ASSERT_EQ(1, pool->ref_count_);
|
||||
ASSERT_EQ(false, pool->is_deleted_);
|
||||
ASSERT_EQ(tenant_id, pool->tenant_id_);
|
||||
ObTableApiSessGuard sess_guard;
|
||||
ASSERT_EQ(OB_HASH_NOT_EXIST, pool->get_sess_info(key, sess_guard));
|
||||
ASSERT_EQ(OB_HASH_NOT_EXIST, pool->get_sess_info(key, sess_guard));
|
||||
ObTableApiCredential credential;
|
||||
credential.tenant_id_ = tenant_id;
|
||||
credential.user_id_ = user_id;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->update_sess(credential));
|
||||
ObTableApiSessNode *node = nullptr;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->get_sess_node(key, node));
|
||||
ASSERT_TRUE(nullptr != node);
|
||||
ASSERT_TRUE(node->is_empty());
|
||||
void *buf = node->allocator_.alloc(sizeof(ObTableApiSessNodeVal));
|
||||
ASSERT_NE(nullptr, buf);
|
||||
ObTableApiSessNodeVal *new_val = new (buf) ObTableApiSessNodeVal(tenant_id, node);
|
||||
new_val->is_inited_ = true;
|
||||
ASSERT_EQ(true, node->sess_lists_.free_list_.add_last(new_val));
|
||||
}
|
||||
|
||||
TEST_F(TestTableSessPool, remove_session)
|
||||
{
|
||||
int64_t tenant_id = 1001;
|
||||
uint64_t user_id = 0;
|
||||
ObTableApiCredential credential;
|
||||
credential.tenant_id_ = tenant_id;
|
||||
credential.user_id_ = user_id;
|
||||
ObTableApiSessNode node(credential);
|
||||
for (int64_t i = 0; i < SESS_CNT; i++) {
|
||||
void *buf = node.allocator_.alloc(sizeof(ObTableApiSessNodeVal));
|
||||
ASSERT_NE(nullptr, buf);
|
||||
ObTableApiSessNodeVal *val = new (buf) ObTableApiSessNodeVal(tenant_id, &node);
|
||||
val->is_inited_ = true;
|
||||
ASSERT_EQ(true, node.sess_lists_.free_list_.add_last(val));
|
||||
}
|
||||
ASSERT_EQ(false, node.is_empty());
|
||||
ASSERT_EQ(SESS_CNT, node.sess_lists_.free_list_.get_size());
|
||||
node.remove_unused_sess();
|
||||
ASSERT_EQ(0, node.sess_lists_.free_list_.get_size());
|
||||
}
|
||||
|
||||
TEST_F(TestTableSessPool, retire_session)
|
||||
{
|
||||
int ret = 0;
|
||||
ObTableApiSessPoolMgr mgr;
|
||||
prepare_sess_pool(mgr);
|
||||
ObTableApiSessPoolForeachOp op;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.sess_pool_map_.foreach_refactored(op));
|
||||
const ObTableApiSessPoolForeachOp::TelantIdArray &tenant_ids = op.get_telant_id_array();
|
||||
ASSERT_EQ(TENANT_CNT, tenant_ids.count());
|
||||
const int64_t N = tenant_ids.count();
|
||||
// 1. 标记淘汰
|
||||
for (int64_t i = 0; i < N; i++) {
|
||||
uint64_t tenant_id = tenant_ids.at(i);
|
||||
ObTableApiSessPoolGuard pool_guard;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.get_session_pool(tenant_id, pool_guard));
|
||||
ObTableApiSessPool *pool = pool_guard.get_sess_pool();
|
||||
ASSERT_NE(nullptr, pool);
|
||||
ObTableApiSessForeachOp op;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->key_node_map_.foreach_refactored(op));
|
||||
const ObTableApiSessForeachOp::SessKvArray &kvs = op.get_key_value_array();
|
||||
ASSERT_EQ(NODE_CNT, kvs.count());
|
||||
for (int64_t j = 0; j < kvs.count(); j++) {
|
||||
if (j % 2 == 0) {
|
||||
const ObTableApiSessForeachOp::ObTableApiSessKV &kv = kvs.at(j);
|
||||
ASSERT_EQ(OB_SUCCESS, pool->move_retired_sess(kv.key_));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2. 触发淘汰
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.elimination_task_.run_recycle_retired_sess_task());
|
||||
// 3. 检查
|
||||
for (int64_t i = 0; i < N; i++) {
|
||||
uint64_t tenant_id = tenant_ids.at(i);
|
||||
ObTableApiSessPoolGuard pool_guard;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.get_session_pool(tenant_id, pool_guard));
|
||||
ObTableApiSessPool *pool = pool_guard.get_sess_pool();
|
||||
ASSERT_NE(nullptr, pool);
|
||||
ObTableApiSessForeachOp op;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->key_node_map_.foreach_refactored(op));
|
||||
const ObTableApiSessForeachOp::SessKvArray &kvs = op.get_key_value_array();
|
||||
ASSERT_EQ(NODE_CNT/2, kvs.count());
|
||||
for (int64_t j = 0; j < kvs.count(); j++) {
|
||||
const ObTableApiSessForeachOp::ObTableApiSessKV &kv = kvs.at(j);
|
||||
ASSERT_EQ(SESS_CNT, kv.node_->sess_lists_.free_list_.get_size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestTableSessPool, reference_session)
|
||||
{
|
||||
// prepare
|
||||
ObTableApiSessPoolMgr mgr;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.init());
|
||||
uint64_t tenant_id = 1001;
|
||||
uint64_t user_id = 0;
|
||||
ObTableApiSessPoolGuard pool_guard;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.extend_sess_pool(tenant_id, pool_guard));
|
||||
ObTableApiSessPool *pool = pool_guard.get_sess_pool();
|
||||
ASSERT_NE(nullptr, pool);
|
||||
ObTableApiCredential credential;
|
||||
credential.tenant_id_ = tenant_id;
|
||||
credential.user_id_ = user_id;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->update_sess(credential));
|
||||
ObTableApiSessNode *node = nullptr;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->get_sess_node(user_id, node));
|
||||
ASSERT_NE(nullptr, node);
|
||||
void *buf = node->allocator_.alloc(sizeof(ObTableApiSessNodeVal));
|
||||
ASSERT_NE(nullptr, buf);
|
||||
ObTableApiSessNodeVal *val = new (buf) ObTableApiSessNodeVal(tenant_id, node);
|
||||
val->is_inited_ = true;
|
||||
ASSERT_EQ(true, node->sess_lists_.free_list_.add_last(val));
|
||||
// get and retire
|
||||
{
|
||||
// get
|
||||
ObTableApiSessGuard guard;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->get_sess_info(user_id, guard));
|
||||
ASSERT_NE(nullptr, guard.get_sess_node_val());
|
||||
// mark retire
|
||||
ObTableApiSessForeachOp op;
|
||||
ASSERT_EQ(OB_SUCCESS, pool->key_node_map_.foreach_refactored(op));
|
||||
const ObTableApiSessForeachOp::SessKvArray &kvs = op.get_key_value_array();
|
||||
ASSERT_EQ(1, kvs.count());
|
||||
const ObTableApiSessForeachOp::ObTableApiSessKV &kv = kvs.at(0);
|
||||
// run retire task
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.elimination_task_.run_recycle_retired_sess_task());
|
||||
// check
|
||||
op.reset();
|
||||
ASSERT_EQ(OB_SUCCESS, pool->key_node_map_.foreach_refactored(op));
|
||||
const ObTableApiSessForeachOp::SessKvArray &new_kvs = op.get_key_value_array();
|
||||
ASSERT_EQ(1, new_kvs.count());
|
||||
}
|
||||
// retire after def ref
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.elimination_task_.run_recycle_retired_sess_task());
|
||||
// check
|
||||
ObTableApiSessPoolForeachOp op;
|
||||
ASSERT_EQ(OB_SUCCESS, mgr.sess_pool_map_.foreach_refactored(op));
|
||||
const ObTableApiSessPoolForeachOp::TelantIdArray &arr = op.get_telant_id_array();
|
||||
ASSERT_EQ(1, arr.count());
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
OB_LOGGER.set_log_level("INFO");
|
||||
OB_LOGGER.set_file_name("TestTableSessPool.log", true);
|
||||
::testing::InitGoogleTest(&argc,argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user