590 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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();
 | 
						|
}
 |