Files
oceanbase/unittest/share/schema/test_schema_cache.cpp
gm 4a92b6d7df reformat source code
according to code styles, 'AccessModifierOffset' should be -2.
2021-06-17 10:40:36 +08:00

590 lines
25 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 USING_LOG_PREFIX SHARE
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#define private public
#include "lib/oblog/ob_log.h"
#include "lib/time/ob_time_utility.h"
#include "lib/random/ob_random.h"
#include "lib/container/ob_array.h"
#include "lib/container/ob_array_iterator.h"
#include "lib/allocator/page_arena.h"
#define private public
#include "share/schema/ob_schema_cache.h"
#include "share/schema/ob_schema_service_sql_impl.h"
#include "schema_test_utils.h"
namespace oceanbase {
using namespace common;
namespace share {
namespace schema {
class GetBatchSchemasFuncs0 {
public:
// return non schema
int get_batch_tenants(const int64_t schema_version, ObArray<uint64_t>& tenant_ids, ObISQLClient& client,
ObIArray<ObTenantSchema>& tenant_infos)
{
UNUSED(schema_version);
UNUSED(tenant_ids);
UNUSED(client);
UNUSED(tenant_infos);
return OB_SUCCESS;
}
int get_batch_users(
const int64_t schema_version, ObArray<uint64_t>& user_ids, ObISQLClient& client, ObIArray<ObUserInfo>& user_infos)
{
UNUSED(schema_version);
UNUSED(user_ids);
UNUSED(client);
UNUSED(user_infos);
return OB_SUCCESS;
}
int get_batch_databases(const int64_t schema_version, ObArray<uint64_t>& db_ids, ObISQLClient& client,
ObIArray<ObDatabaseSchema>& db_schemas)
{
UNUSED(schema_version);
UNUSED(db_ids);
UNUSED(client);
UNUSED(db_schemas);
return OB_SUCCESS;
}
int get_batch_tablegroups(const int64_t schema_version, ObArray<uint64_t>& tg_ids, ObISQLClient& client,
ObIArray<ObTablegroupSchema>& tg_schemas)
{
UNUSED(schema_version);
UNUSED(tg_ids);
UNUSED(client);
UNUSED(tg_schemas);
return OB_SUCCESS;
}
int get_batch_outlines(const int64_t schema_version, ObArray<uint64_t>& outline_ids, ObISQLClient& client,
ObIArray<ObOutlineInfo>& outline_infos)
{
UNUSED(schema_version);
UNUSED(outline_ids);
UNUSED(client);
UNUSED(outline_infos);
return OB_SUCCESS;
}
int get_table_schema(const uint64_t table_id, const int64_t schema_version, ObISQLClient& client,
ObIAllocator& allocator, ObTableSchema*& table_schema)
{
UNUSED(table_id);
UNUSED(schema_version);
UNUSED(client);
UNUSED(allocator);
UNUSED(table_schema);
return OB_SUCCESS;
}
int get_tablegroup_schema(const uint64_t tablegroup_id, const int64_t schema_version,
common::ObISQLClient& sql_client, common::ObIAllocator& allocator, ObTablegroupSchema*& tablegroup_schema)
{
UNUSED(tablegroup_id);
UNUSED(schema_version);
UNUSED(sql_client);
UNUSED(allocator);
UNUSED(tablegroup_schema);
return OB_SUCCESS;
}
};
class GetBatchSchemasFuncs1 {
public:
// return one schema
int get_batch_tenants(const int64_t schema_version, ObArray<uint64_t>& tenant_ids, ObISQLClient& client,
ObIArray<ObTenantSchema>& tenant_infos)
{
UNUSED(schema_version);
UNUSED(tenant_ids);
UNUSED(client);
ObTenantSchema tenant_schema;
tenant_schema.set_tenant_id(1);
tenant_schema.set_tenant_name("tenant");
tenant_infos.push_back(tenant_schema);
return OB_SUCCESS;
}
int get_batch_users(
const int64_t schema_version, ObArray<uint64_t>& user_ids, ObISQLClient& client, ObIArray<ObUserInfo>& user_infos)
{
UNUSED(schema_version);
UNUSED(user_ids);
UNUSED(client);
ObUserInfo user_info;
user_info.set_tenant_id(1);
user_info.set_user_id(combine_id(1, 1));
user_info.set_user_name("user");
user_info.set_host(OB_DEFAULT_HOST_NAME);
user_infos.push_back(user_info);
return OB_SUCCESS;
}
int get_batch_databases(const int64_t schema_version, ObArray<uint64_t>& db_ids, ObISQLClient& client,
ObIArray<ObDatabaseSchema>& db_schemas)
{
UNUSED(schema_version);
UNUSED(db_ids);
UNUSED(client);
ObDatabaseSchema db_schema;
db_schema.set_tenant_id(1);
db_schema.set_database_id(combine_id(1, 1));
db_schema.set_database_name("db");
db_schemas.push_back(db_schema);
return OB_SUCCESS;
}
int get_batch_tablegroups(const int64_t schema_version, ObArray<uint64_t>& tg_ids, ObISQLClient& client,
ObIArray<ObTablegroupSchema>& tg_schemas)
{
UNUSED(schema_version);
UNUSED(tg_ids);
UNUSED(client);
ObTablegroupSchema tg_schema;
tg_schema.set_tenant_id(1);
tg_schema.set_tablegroup_id(combine_id(1, 1));
tg_schema.set_tablegroup_name("tg");
tg_schemas.push_back(tg_schema);
return OB_SUCCESS;
}
int get_table_schema(const uint64_t table_id, const int64_t schema_version, ObISQLClient& client,
ObIAllocator& allocator, ObTableSchema*& table_schema)
{
UNUSED(table_id);
UNUSED(schema_version);
UNUSED(client);
UNUSED(allocator);
ObTableSchema table;
// table_info.set_tenant_id(1);
// table_info.set_table_id(combine_id(1,1));
// table_info.set_table_name("table");
table_schema = &table;
return OB_SUCCESS;
}
int get_batch_outlines(const int64_t schema_version, ObArray<uint64_t>& outline_ids, ObISQLClient& client,
ObIArray<ObOutlineInfo>& outline_infos)
{
UNUSED(schema_version);
UNUSED(outline_ids);
UNUSED(client);
ObOutlineInfo outline_info;
outline_info.set_tenant_id(1);
outline_info.set_outline_id(combine_id(1, 1));
outline_info.set_name("outline");
outline_infos.push_back(outline_info);
return OB_SUCCESS;
}
int get_tablegroup_schema(const uint64_t tablegroup_id, const int64_t schema_version,
common::ObISQLClient& sql_client, common::ObIAllocator& allocator, ObTablegroupSchema*& tablegroup_schema)
{
UNUSED(tablegroup_id);
UNUSED(schema_version);
UNUSED(sql_client);
UNUSED(allocator);
ObTablegroupSchema tg_schema;
tablegroup_schema = &tg_schema;
return OB_SUCCESS;
}
};
class TestSchemaCache : public ::testing::Test {
public:
virtual void SetUp();
virtual void TearDown();
private:
GetBatchSchemasFuncs0 get_batch_schemas_funcs0;
GetBatchSchemasFuncs1 get_batch_schemas_funcs1;
};
void TestSchemaCache::TearDown()
{
ObKVGlobalCache::get_instance().destroy();
}
void TestSchemaCache::SetUp()
{
const int64_t bucket_num = 1024;
const int64_t max_cache_size = 1024 * 1024 * 512;
const int64_t block_size = OB_MALLOC_BIG_BLOCK_SIZE;
ObKVGlobalCache::get_instance().init(bucket_num, max_cache_size, block_size);
}
TEST_F(TestSchemaCache, schema_key)
{
int ret = OB_SUCCESS;
// hash && operator ==
ObSchemaCacheKey cache_key_a(TENANT_SCHEMA, 1, 1);
ObSchemaCacheKey cache_key_b(TENANT_SCHEMA, 1, 1);
ObSchemaCacheKey cache_key_c(TENANT_SCHEMA, 2, 1);
ASSERT_TRUE(cache_key_a.hash() == cache_key_b.hash());
ASSERT_TRUE(cache_key_a == cache_key_b);
ASSERT_FALSE(cache_key_a.hash() == cache_key_c.hash());
ASSERT_FALSE(cache_key_a == cache_key_c);
// get_tenant_id
ASSERT_EQ(OB_SYS_TENANT_ID, cache_key_a.get_tenant_id());
// size
ASSERT_EQ(sizeof(ObSchemaCacheKey), cache_key_a.size());
// deep_copy
char* buf = new char[cache_key_a.size()];
ObIKVCacheKey* tmp_cache_key = NULL;
ret = cache_key_a.deep_copy(buf, cache_key_a.size(), tmp_cache_key);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != tmp_cache_key);
ASSERT_EQ(cache_key_a, *static_cast<ObSchemaCacheKey*>(tmp_cache_key));
// to_string
LOG_INFO("test schema key to_string", K(cache_key_a));
}
TEST_F(TestSchemaCache, schema_value)
{
int ret = OB_SUCCESS;
#define DEEP_COPY(xx_schema, SCHEMA, SCHEMA_TYPE_ENUM, SCHEMA_TYPE) \
{ \
ObSchemaCacheValue cache_value(SCHEMA_TYPE_ENUM, &xx_schema); \
LOG_INFO("test schema value to_string", K(cache_value)); \
ASSERT_EQ(sizeof(ObSchemaCacheValue) + xx_schema.get_convert_size() + sizeof(ObDataBuffer), cache_value.size()); \
char* buf = new char[cache_value.size()]; \
ObIKVCacheValue* tmp_cache_value = NULL; \
ret = cache_value.deep_copy(buf, cache_value.size(), tmp_cache_value); \
ASSERT_EQ(OB_SUCCESS, ret); \
ASSERT_TRUE(NULL != tmp_cache_value); \
const ObSchemaCacheValue* tmp_schema_cache_value = static_cast<ObSchemaCacheValue*>(tmp_cache_value); \
ASSERT_TRUE(SchemaTestUtils::equal_##SCHEMA##_schema( \
xx_schema, *static_cast<SCHEMA_TYPE*>(tmp_schema_cache_value->schema_))); \
}
// tenant
ObTenantSchema tenant_schema;
tenant_schema.set_tenant_id(1);
tenant_schema.set_tenant_name("tenant");
DEEP_COPY(tenant_schema, tenant, TENANT_SCHEMA, ObTenantSchema);
// user
ObUserInfo user_schema;
user_schema.set_tenant_id(1);
user_schema.set_user_id(combine_id(1, 1));
user_schema.set_user_name("user");
user_schema.set_host(OB_DEFAULT_HOST_NAME);
DEEP_COPY(user_schema, user, USER_SCHEMA, ObUserInfo);
// database
ObDatabaseSchema database_schema;
database_schema.set_tenant_id(1);
database_schema.set_database_id(combine_id(1, 1));
database_schema.set_database_name("database");
DEEP_COPY(database_schema, database, DATABASE_SCHEMA, ObDatabaseSchema);
// tablegroup
ObTablegroupSchema tablegroup_schema;
tablegroup_schema.set_tenant_id(1);
tablegroup_schema.set_tablegroup_id(combine_id(1, 1));
tablegroup_schema.set_tablegroup_name("tablegroup");
DEEP_COPY(tablegroup_schema, tablegroup, TABLEGROUP_SCHEMA, ObTablegroupSchema);
// table
ObTableSchema table_schema;
table_schema.set_tenant_id(1);
table_schema.set_database_id(combine_id(1, 1));
table_schema.set_table_id(combine_id(1, 1));
table_schema.set_table_name("table");
DEEP_COPY(table_schema, table, TABLE_SCHEMA, ObTableSchema);
// outline
ObOutlineInfo outline_schema;
outline_schema.set_tenant_id(1);
outline_schema.set_database_id(combine_id(1, 1));
outline_schema.set_outline_id(combine_id(1, 1));
outline_schema.set_name("outline");
outline_schema.set_signature("sig");
DEEP_COPY(outline_schema, outline, OUTLINE_SCHEMA, ObOutlineInfo);
}
TEST_F(TestSchemaCache, is_valid_key)
{
ObSchemaCache schema_cache;
ASSERT_EQ(OB_SUCCESS, schema_cache.init());
ASSERT_FALSE(schema_cache.is_valid_key(OB_MAX_SCHEMA, OB_INVALID_VERSION, -1));
ASSERT_FALSE(schema_cache.is_valid_key(TABLE_SCHEMA, OB_INVALID_VERSION, -1));
ASSERT_FALSE(schema_cache.is_valid_key(TABLE_SCHEMA, 1, -1));
ASSERT_TRUE(schema_cache.is_valid_key(TABLE_SCHEMA, 1, 1));
}
TEST_F(TestSchemaCache, need_use_sys_cache)
{
ObSchemaCache schema_cache;
ASSERT_EQ(OB_SUCCESS, schema_cache.init());
ObSchemaCacheKey cache_key;
ASSERT_TRUE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TENANT_SCHEMA, 1, 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TENANT_SCHEMA, 2, 1)));
ASSERT_TRUE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(USER_SCHEMA, combine_id(1, 1), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(USER_SCHEMA, combine_id(2, 1), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(DATABASE_SCHEMA, combine_id(1, 1), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(DATABASE_SCHEMA, combine_id(2, 1), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TABLEGROUP_SCHEMA, combine_id(1, 1), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TABLEGROUP_SCHEMA, combine_id(2, 1), 1)));
ASSERT_TRUE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TABLE_SCHEMA, combine_id(1, 1), 1)));
ASSERT_TRUE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TABLE_SCHEMA, combine_id(1, 50000), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TABLE_SCHEMA, combine_id(1, 50001), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(TABLE_SCHEMA, combine_id(2, 1), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(OUTLINE_SCHEMA, combine_id(1, 1), 1)));
ASSERT_FALSE(schema_cache.need_use_sys_cache(cache_key = ObSchemaCacheKey(OUTLINE_SCHEMA, combine_id(1, 2), 1)));
}
TEST_F(TestSchemaCache, schema_cache)
{
int ret = OB_SUCCESS;
ObSchemaCache schema_cache;
ObKVCacheHandle handle;
const ObSchema* dst_schema = NULL;
// not init when get
ret = schema_cache.get_schema(TENANT_SCHEMA, 1, 1, handle, dst_schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
ASSERT_EQ(OB_SUCCESS, schema_cache.init());
// invalid arg when get
ret = schema_cache.get_schema(OB_MAX_SCHEMA, 1, 1, handle, dst_schema);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ret = schema_cache.get_schema(TENANT_SCHEMA, OB_INVALID_ID, 1, handle, dst_schema);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ret = schema_cache.get_schema(TENANT_SCHEMA, 1, -1, handle, dst_schema);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
// not exist
ret = schema_cache.get_schema(TENANT_SCHEMA, 1, 1, handle, dst_schema);
ASSERT_EQ(OB_ENTRY_NOT_EXIST, ret);
ASSERT_TRUE(NULL == dst_schema);
// sys cache
ObTenantSchema tenant_schema;
tenant_schema.set_tenant_id(1);
tenant_schema.set_tenant_name("fds");
tenant_schema.set_schema_version(1);
// not init when put
schema_cache.is_inited_ = false;
ret = schema_cache.put_schema(TENANT_SCHEMA, 1, 1, tenant_schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
schema_cache.is_inited_ = true;
// invalid arg when put
ret = schema_cache.put_schema(OB_MAX_SCHEMA, 1, 1, tenant_schema);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ret = schema_cache.put_schema(TENANT_SCHEMA, OB_INVALID_ID, 1, tenant_schema);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ret = schema_cache.put_schema(TENANT_SCHEMA, 1, -1, tenant_schema);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ret = schema_cache.put_schema(TENANT_SCHEMA, 1, 1, tenant_schema);
ASSERT_EQ(OB_SUCCESS, ret);
ret = schema_cache.get_schema(TENANT_SCHEMA, 1, 1, handle, dst_schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != dst_schema);
ASSERT_TRUE(SchemaTestUtils::equal_tenant_schema(tenant_schema, *static_cast<const ObTenantSchema*>(dst_schema)));
// no sys cache
ret = schema_cache.get_schema(DATABASE_SCHEMA, combine_id(1, 1), 1, handle, dst_schema);
ASSERT_EQ(OB_ENTRY_NOT_EXIST, ret);
ASSERT_TRUE(NULL == dst_schema);
ObDatabaseSchema db_schema;
db_schema.set_tenant_id(1);
db_schema.set_database_id(combine_id(1, 1));
db_schema.set_database_name("fds");
db_schema.set_schema_version(1);
ret = schema_cache.put_schema(DATABASE_SCHEMA, combine_id(1, 1), 1, db_schema);
ASSERT_EQ(OB_SUCCESS, ret);
ret = schema_cache.get_schema(DATABASE_SCHEMA, combine_id(1, 1), 1, handle, dst_schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != dst_schema);
ASSERT_TRUE(SchemaTestUtils::equal_database_schema(db_schema, *static_cast<const ObDatabaseSchema*>(dst_schema)));
}
using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;
class MockSchemaServiceSQLImpl : public ObSchemaServiceSQLImpl {
public:
MOCK_METHOD4(get_batch_tenants, int(const int64_t, ObArray<uint64_t>&, ObISQLClient&, ObIArray<ObTenantSchema>&));
MOCK_METHOD4(get_batch_users, int(const int64_t, ObArray<uint64_t>&, ObISQLClient&, ObIArray<ObUserInfo>&));
MOCK_METHOD4(get_batch_databases, int(const int64_t, ObArray<uint64_t>&, ObISQLClient&, ObIArray<ObDatabaseSchema>&));
MOCK_METHOD4(
get_batch_tablegroups, int(const int64_t, ObArray<uint64_t>&, ObISQLClient&, ObIArray<ObTablegroupSchema>&));
MOCK_METHOD4(get_batch_outlines, int(const int64_t, ObArray<uint64_t>&, ObISQLClient&, ObIArray<ObOutlineInfo>&));
MOCK_METHOD5(get_table_schema, int(const uint64_t, const int64_t, ObISQLClient&, ObIAllocator&, ObTableSchema*&));
MOCK_METHOD5(
get_tablegroup_schema, int(const uint64_t, const int64_t, ObISQLClient&, ObIAllocator&, ObTablegroupSchema*&));
virtual int can_read_schema_version(int64_t expected_version)
{
UNUSED(expected_version);
return common::OB_SUCCESS;
}
};
TEST_F(TestSchemaCache, schema_fetcher)
{
int ret = OB_SUCCESS;
ObArenaAllocator allocator;
ObSchemaFetcher schema_fetcher;
MockSchemaServiceSQLImpl schema_service;
ObSchema* schema = NULL;
// mock sql_clent for init
ObISQLClient* sql_client = reinterpret_cast<ObISQLClient*>(this);
// schema_fetcher is not inited
ret = schema_fetcher.fetch_schema(TENANT_SCHEMA, OB_INVALID_ID, -1, allocator, schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
ret = schema_fetcher.fetch_schema(USER_SCHEMA, OB_INVALID_ID, -1, allocator, schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
ret = schema_fetcher.fetch_schema(DATABASE_SCHEMA, OB_INVALID_ID, -1, allocator, schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
ret = schema_fetcher.fetch_schema(TABLEGROUP_SCHEMA, OB_INVALID_ID, -1, allocator, schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
ret = schema_fetcher.fetch_schema(TABLE_SCHEMA, OB_INVALID_ID, -1, allocator, schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
ret = schema_fetcher.fetch_schema(OUTLINE_SCHEMA, OB_INVALID_ID, -1, allocator, schema);
ASSERT_EQ(OB_INNER_STAT_ERROR, ret);
ret = schema_fetcher.init(NULL, sql_client);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ret = schema_fetcher.init(&schema_service, NULL);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ret = schema_fetcher.init(&schema_service, sql_client);
ASSERT_EQ(OB_SUCCESS, ret);
// invalid arg
ret = schema_fetcher.fetch_schema(TENANT_SCHEMA, OB_INVALID_ID, 1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(TENANT_SCHEMA, 1, -1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(USER_SCHEMA, OB_INVALID_ID, 1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(USER_SCHEMA, 1, -1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(DATABASE_SCHEMA, OB_INVALID_ID, 1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(DATABASE_SCHEMA, 1, -1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(TABLEGROUP_SCHEMA, OB_INVALID_ID, 1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(TABLEGROUP_SCHEMA, 1, -1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(TABLE_SCHEMA, OB_INVALID_ID, 1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(TABLE_SCHEMA, 1, -1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(OUTLINE_SCHEMA, OB_INVALID_ID, 1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
ret = schema_fetcher.fetch_schema(OUTLINE_SCHEMA, 1, -1, allocator, schema);
ASSERT_EQ(ret, OB_INVALID_ARGUMENT);
// schema_serice's get batch funcs failed
ON_CALL(schema_service, get_batch_tenants(_, _, _, _)).WillByDefault(Return(OB_ERROR));
ret = schema_fetcher.fetch_schema(TENANT_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(ret, OB_ERROR);
ON_CALL(schema_service, get_batch_users(_, _, _, _)).WillByDefault(Return(OB_ERROR));
ret = schema_fetcher.fetch_schema(USER_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(ret, OB_ERROR);
ON_CALL(schema_service, get_batch_databases(_, _, _, _)).WillByDefault(Return(OB_ERROR));
ret = schema_fetcher.fetch_schema(DATABASE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(ret, OB_ERROR);
ON_CALL(schema_service, get_tablegroup_schema(_, _, _, _, _)).WillByDefault(Return(OB_ERROR));
ret = schema_fetcher.fetch_schema(TABLEGROUP_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(ret, OB_ERROR);
ON_CALL(schema_service, get_table_schema(_, _, _, _, _)).WillByDefault(Return(OB_ERROR));
ret = schema_fetcher.fetch_schema(TABLE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(ret, OB_ERROR);
ON_CALL(schema_service, get_batch_outlines(_, _, _, _)).WillByDefault(Return(OB_ERROR));
ret = schema_fetcher.fetch_schema(OUTLINE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(ret, OB_ERROR);
// schema_service's get batch func succeed, but no schema return
ON_CALL(schema_service, get_batch_databases(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs0, &GetBatchSchemasFuncs0::get_batch_databases));
ret = schema_fetcher.fetch_schema(DATABASE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
ON_CALL(schema_service, get_tablegroup_schema(_, _, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs0, &GetBatchSchemasFuncs0::get_tablegroup_schema));
ret = schema_fetcher.fetch_schema(TABLEGROUP_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
ON_CALL(schema_service, get_batch_users(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs0, &GetBatchSchemasFuncs0::get_batch_users));
ret = schema_fetcher.fetch_schema(USER_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
ON_CALL(schema_service, get_batch_tenants(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs0, &GetBatchSchemasFuncs0::get_batch_tenants));
ret = schema_fetcher.fetch_schema(TENANT_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
ON_CALL(schema_service, get_batch_outlines(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs0, &GetBatchSchemasFuncs0::get_batch_outlines));
ret = schema_fetcher.fetch_schema(OUTLINE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
ON_CALL(schema_service, get_table_schema(_, _, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs0, &GetBatchSchemasFuncs0::get_table_schema));
ret = schema_fetcher.fetch_schema(TABLE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_ERR_UNEXPECTED, ret);
// schema_service's get batch func succeed
ON_CALL(schema_service, get_batch_tenants(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs1, &GetBatchSchemasFuncs1::get_batch_tenants));
ret = schema_fetcher.fetch_schema(TENANT_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != schema);
ON_CALL(schema_service, get_batch_users(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs1, &GetBatchSchemasFuncs1::get_batch_users));
ret = schema_fetcher.fetch_schema(USER_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != schema);
ON_CALL(schema_service, get_batch_databases(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs1, &GetBatchSchemasFuncs1::get_batch_databases));
ret = schema_fetcher.fetch_schema(DATABASE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != schema);
ON_CALL(schema_service, get_tablegroup_schema(_, _, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs1, &GetBatchSchemasFuncs1::get_tablegroup_schema));
ret = schema_fetcher.fetch_schema(TABLEGROUP_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != schema);
ON_CALL(schema_service, get_table_schema(_, _, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs1, &GetBatchSchemasFuncs1::get_table_schema));
ret = schema_fetcher.fetch_schema(TABLE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != schema);
ON_CALL(schema_service, get_batch_outlines(_, _, _, _))
.WillByDefault(Invoke(&get_batch_schemas_funcs1, &GetBatchSchemasFuncs1::get_batch_outlines));
ret = schema_fetcher.fetch_schema(OUTLINE_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_TRUE(NULL != schema);
}
TEST_F(TestSchemaCache, schema_fetcher_connect_error)
{
int ret = OB_SUCCESS;
ObArenaAllocator allocator;
ObSchemaFetcher schema_fetcher;
MockSchemaServiceSQLImpl schema_service;
ObSchema* schema = NULL;
// mock sql_client for init
ObISQLClient* sql_client = reinterpret_cast<ObISQLClient*>(this);
ret = schema_fetcher.init(&schema_service, sql_client);
ASSERT_EQ(OB_SUCCESS, ret);
// schema_service return OB_CONNECT_ERROR
// EXPECT_CALL(schema_service,
// get_batch_tenants(_,_,_,_)).Times(2).WillOnce(Return(OB_CONNECT_ERROR)).WillOnce(Return(OB_SUCCESS));
EXPECT_CALL(schema_service, get_batch_tenants(_, _, _, _))
.Times(2)
.WillOnce(Return(OB_CONNECT_ERROR))
.WillOnce(Invoke(&get_batch_schemas_funcs1, &GetBatchSchemasFuncs1::get_batch_tenants));
ret = schema_fetcher.fetch_schema(TENANT_SCHEMA, 1, 1, allocator, schema);
ASSERT_EQ(OB_SUCCESS, ret);
}
} // namespace schema
} // namespace share
} // namespace oceanbase
int main(int argc, char** argv)
{
oceanbase::common::ObLogger::get_logger().set_log_level("INFO");
OB_LOGGER.set_file_name("test_schema_cache.log", true);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}