oceanbase/unittest/storage/blocksstable/test_row_writer.cpp
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

475 lines
14 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.
*/
#include <gtest/gtest.h>
#include "storage/blocksstable/ob_row_writer.h"
#include "storage/blocksstable/ob_row_reader.h"
#include "storage/ob_i_store.h"
#include "storage/blocksstable/ob_block_sstable_struct.h"
#include "lib/number/ob_number_v2.h"
#include "ob_row_generate.h"
#define protected public
#define private public
namespace oceanbase
{
using namespace common;
using namespace blocksstable;
using namespace storage;
using namespace number;
using namespace share::schema;
namespace unittest
{
class TestRowWriter : public ::testing::Test
{
public:
static const int64_t rowkey_column_count = 1;
// Every ObObjType from ObTinyIntType to ObHexStringType inclusive.
// Skip ObNullType and ObExtendType because for external usage, a column type
// can't be NULL or NOP.
static const int64_t column_num = ObHexStringType;
public:
TestRowWriter();
virtual void SetUp();
virtual void TearDown();
void alloc(char *&ptr, const int64_t size);
protected:
ObRowGenerate row_generate_;
ObColumnMap column_map_;
private:
ObArenaAllocator allocator_;
};
TestRowWriter::TestRowWriter()
:allocator_(ObModIds::TEST)
{
}
void TestRowWriter::SetUp()
{
const int64_t table_id = 3001;
ObTableSchema table_schema;
ObColumnSchemaV2 column;
oceanbase::common::ObClusterVersion::get_instance().refresh_cluster_version("1.4.70");
//init table schema
table_schema.reset();
ASSERT_EQ(OB_SUCCESS, table_schema.set_table_name("test_row_writer"));
table_schema.set_tenant_id(1);
table_schema.set_tablegroup_id(1);
table_schema.set_database_id(1);
table_schema.set_table_id(table_id);
table_schema.set_rowkey_column_num(rowkey_column_count);
table_schema.set_max_used_column_id(column_num);
//init column
char name[OB_MAX_FILE_NAME_LENGTH];
memset(name, 0, sizeof(name));
for(int64_t i = 0; i < column_num; ++i){
ObObjType obj_type = static_cast<ObObjType>(i + 1);
column.reset();
column.set_collation_type(CS_TYPE_BINARY);
column.set_table_id(table_id);
column.set_column_id(i + OB_APP_MIN_COLUMN_ID);
sprintf(name, "test%020ld", i);
ASSERT_EQ(OB_SUCCESS, column.set_column_name(name));
column.set_data_type(obj_type);
column.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
if(obj_type == common::ObIntType){
column.set_rowkey_position(1);
} else {
column.set_rowkey_position(0);
}
ASSERT_EQ(OB_SUCCESS, table_schema.add_column(column));
}
//init ObRowGenerate
ASSERT_EQ(OB_SUCCESS, row_generate_.init(table_schema));
}
void TestRowWriter::TearDown()
{
}
void TestRowWriter::alloc(char *&ptr, const int64_t size)
{
ptr = reinterpret_cast<char*>(allocator_.alloc(size));
ASSERT_TRUE(NULL != ptr);
}
TEST_F(TestRowWriter, test_init)
{
int ret = OB_SUCCESS;
ObRowWriter row_writer;
oceanbase::common::ObObj objs[column_num];
ObStoreRow valid_store_row;
ObStoreRow invalid_store_row;
valid_store_row.row_val_.cells_ = objs;
valid_store_row.row_val_.count_ = column_num;
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(valid_store_row));
ObNewRow invalid_new_row;
ObNewRow valid_new_row;
valid_new_row.cells_ = objs;
valid_new_row.count_ = column_num;
char *buf = NULL;
alloc(buf, 2 * 1024 * 1024);
int64_t pos = 0;
int64_t rowkey_start_pos = 0;
int64_t rowkey_length = 0;
//init success
pos = 0;
rowkey_start_pos = 0;
rowkey_length = 0;
ret = row_writer.write(rowkey_column_count, valid_store_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_SUCCESS, ret);
pos = 0;
ret = row_writer.write(valid_new_row, buf, 2 * 1024 * 1024, FLAT_ROW_STORE, pos);
ASSERT_EQ(OB_SUCCESS, ret);
//invalid buf
pos = 0;
rowkey_start_pos = 0;
rowkey_length = 0;
ret = row_writer.write(rowkey_column_count, valid_store_row, NULL, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
pos = 0;
ret = row_writer.write(valid_new_row, NULL, 2 * 1024 * 1024, FLAT_ROW_STORE, pos);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ASSERT_EQ(0, pos);
//invalid buf_size
pos = 0;
rowkey_start_pos = 0;
rowkey_length = 0;
ret = row_writer.write(rowkey_column_count, valid_store_row, buf, 0,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//invalid pos
pos = 2 * 1024 * 1024;
rowkey_start_pos = 0;
rowkey_length = 0;
ret = row_writer.write(rowkey_column_count, valid_store_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_BUF_NOT_ENOUGH, ret);
ASSERT_EQ(2 * 1024 * 1024, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//invalid store_row
pos = 0;
rowkey_start_pos = 0;
rowkey_length = 0;
ret = row_writer.write(rowkey_column_count, invalid_store_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//invalid rowkey_column_count
pos = 0;
rowkey_start_pos = 0;
rowkey_length = 0;
ret = row_writer.write(-1, valid_store_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//invalid new_row
pos = 0;
ret = row_writer.write(invalid_new_row, buf, 2 * 1024 * 1024, FLAT_ROW_STORE, pos);
ASSERT_EQ(OB_INVALID_ARGUMENT, ret);
ASSERT_EQ(0, pos);
}
TEST_F(TestRowWriter, buf_not_enough)
{
int ret = OB_SUCCESS;
ObRowWriter row_writer;
oceanbase::common::ObObj objs[column_num];
ObStoreRow valid_store_row;
ObStoreRow invalid_store_row;
valid_store_row.row_val_.cells_ = objs;
valid_store_row.row_val_.count_ = column_num;
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(valid_store_row));
ObNewRow invalid_new_row;
ObNewRow valid_new_row;
valid_new_row.cells_ = objs;
valid_new_row.count_ = column_num;
char *buf = NULL;
alloc(buf, 2 * 1024 * 1024);
int64_t pos = 0;
int64_t rowkey_start_pos = 0;
int64_t rowkey_length = 0;
//row header buf not enough
ret = row_writer.write(rowkey_column_count, valid_store_row,
buf, 4, pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_BUF_NOT_ENOUGH, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//rowkey data not enough
ret = row_writer.write(rowkey_column_count, valid_store_row, buf, 8,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_BUF_NOT_ENOUGH, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//normal data not enough
ret = row_writer.write(rowkey_column_count, valid_store_row, buf, 200,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_BUF_NOT_ENOUGH, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//column index not enough
ret = row_writer.write(1, valid_store_row, buf, 430 - 16,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_BUF_NOT_ENOUGH, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
//new row not enough
ret = row_writer.write(valid_new_row, buf, 1, FLAT_ROW_STORE, pos);
ASSERT_EQ(OB_BUF_NOT_ENOUGH, ret);
ASSERT_EQ(0, pos);
//buf not enough
pos = 10;
ret = row_writer.write(valid_new_row, buf, pos, FLAT_ROW_STORE, pos);
ASSERT_EQ(OB_BUF_NOT_ENOUGH, ret);
}
TEST_F(TestRowWriter, data_type)
{
int ret = OB_SUCCESS;
ObRowWriter row_writer;
oceanbase::common::ObObj objs[column_num];
ObStoreRow writer_row;
writer_row.row_val_.cells_ = objs;
writer_row.row_val_.count_ = column_num;
ObFlatRowReader row_reader;
ObStoreRow reader_row;
oceanbase::common::ObObj reader_objs[column_num];
reader_row.row_val_.cells_ = reader_objs;
reader_row.row_val_.count_ = column_num;
char *buf = NULL;
alloc(buf, 2 * 1024 * 1024);
int64_t pos = 0;
int64_t rowkey_start_pos = 0;
int64_t rowkey_length = 0;
int64_t read_pos = 0;
const int64_t test_row_num = 10;
for(int64_t j = 0; j < test_row_num; ++j){
pos = 0;
rowkey_start_pos = 0;
rowkey_length = 0;
read_pos = 0;
//test every ObObjType from ObNullType to ObExtendType
bool exist = false;
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(writer_row));
//column index size is four, one, two will tested normally
if(0 == j){
char *ptr = NULL;
ObString str;
//TODO: OB_MAX_VARCHAR_LENGTH now is 4 * 1024 * 1024, too large to support
alloc(ptr, 256L * 1024);
memset(ptr, 0, 256L * 1024);
str.assign_ptr(ptr, 256L * 1024);
for (int64_t i = 0; i < column_num; ++i){
if(ObVarcharType == objs[i].get_type()){
objs[i].set_varchar(str);
objs[i].set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
break;
}
}
}
ret = row_writer.write(rowkey_column_count, writer_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_SUCCESS, ret);
//init ObColumnMap
column_map_.reuse();
ObArray<ObColDesc> columns;
ASSERT_EQ(OB_SUCCESS, row_generate_.get_schema().get_column_ids(columns));
for (int64_t i = 0; i < column_num; ++i){
ObObjType obj_type = writer_row.row_val_.cells_[i].get_type();
ObObjMeta obj_meta;
obj_meta.set_type(obj_type);
if (ObVarcharType == obj_type || ObCharType == obj_type) {
obj_meta.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
obj_meta.set_collation_level(CS_LEVEL_IMPLICIT);
}
columns[i].col_type_ = obj_meta;
}
ASSERT_EQ(OB_SUCCESS, column_map_.init(allocator_,
row_generate_.get_schema().get_schema_version(),
row_generate_.get_schema().get_rowkey_column_num(),
column_num,
columns));
ret = row_reader.read_row(buf, pos, read_pos, column_map_, allocator_, reader_row);
ASSERT_TRUE(OB_SUCCESS == ret)
<< "\n j: " << j;
if(0 != j){//we has change the rule
ASSERT_EQ(OB_SUCCESS, row_generate_.check_one_row(reader_row, exist));
ASSERT_TRUE(exist);
ASSERT_TRUE(column_num == reader_row.row_val_.count_);
}
//every obj should equal
for (int64_t i = 0; i < column_num ; ++i){
ASSERT_TRUE(writer_row.row_val_.cells_[i] == reader_row.row_val_.cells_[i])
<< "\n i: " << i
<< "\n writer: "<< to_cstring(writer_row.row_val_.cells_[i])
<< "\n reader: " << to_cstring(reader_row.row_val_.cells_[i]);
}
}
//unsupported data type
objs[0].set_type(static_cast<ObObjType>(ObMaxType));
pos = 0;
rowkey_start_pos = 0;
rowkey_length = 0;
ret = row_writer.write(rowkey_column_count, writer_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_NOT_SUPPORTED, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
}
TEST_F(TestRowWriter, char_binary_overflow)
{
int ret = OB_SUCCESS;
ObRowWriter row_writer;
oceanbase::common::ObObj objs[column_num];
ObStoreRow valid_store_row;
ObStoreRow invalid_store_row;
valid_store_row.row_val_.cells_ = objs;
valid_store_row.row_val_.count_ = column_num;
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(valid_store_row));
ObObj obj;
ObString str;
char *buf = NULL;
char *ptr = NULL;
alloc(buf, 2 * 1024 * 1024);
int64_t pos = 0;
int64_t rowkey_start_pos = 0;
int64_t rowkey_length = 0;
alloc(ptr, OB_MAX_VARCHAR_LENGTH + 1);
memset(ptr, 0, OB_MAX_VARCHAR_LENGTH + 1);
str.assign_ptr(ptr, OB_MAX_VARCHAR_LENGTH + 1);
obj.set_varchar(str);
obj.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
valid_store_row.row_val_.cells_[0] = obj;
ret = row_writer.write(1, valid_store_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_SIZE_OVERFLOW, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
obj.set_binary(str);
valid_store_row.row_val_.cells_[0] = obj;
ret = row_writer.write(1, valid_store_row, buf, 2 * 1024 * 1024,
pos, rowkey_start_pos, rowkey_length);
ASSERT_EQ(OB_SIZE_OVERFLOW, ret);
ASSERT_EQ(0, pos);
ASSERT_EQ(0, rowkey_start_pos);
ASSERT_EQ(0, rowkey_length);
}
TEST_F(TestRowWriter, write_only_key_column)
{
int ret = OB_SUCCESS;
ObRowWriter row_writer;
oceanbase::common::ObObj objs[column_num];
ObStoreRow valid_store_row;
ObStoreRow invalid_store_row;
valid_store_row.row_val_.cells_ = objs;
valid_store_row.row_val_.count_ = column_num;
ASSERT_EQ(OB_SUCCESS, row_generate_.get_next_row(valid_store_row));
int32_t buf_size = 1024;
char *buf = NULL;
alloc(buf, buf_size);
char *key_ptr = nullptr;
alloc(key_ptr, 512);
ObObj key_obj;
key_obj.set_varchar(key_ptr, 512);
key_obj.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
valid_store_row.row_val_.cells_[0] = key_obj;
char *col_ptr = nullptr;
alloc(col_ptr, 1024);
ObObj col_obj;
col_obj.set_varchar(col_ptr, 1024);
col_obj.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
valid_store_row.row_val_.cells_[1] = col_obj;
int64_t pos = 0;
int64_t rowkey_start_pos = 0;
int64_t rowkey_length = 0;
ret = row_writer.write(1, valid_store_row, buf, buf_size,
pos, rowkey_start_pos, rowkey_length, true/*only_row_key*/);
ASSERT_EQ(OB_SUCCESS, ret);
ASSERT_LE(0, pos);
ASSERT_LE(0, rowkey_start_pos);
// 1 byte collation type + 4 byte length + 512 byte data length
ASSERT_EQ(517, rowkey_length);
}
}//end namespace tests
}//end namespace oceanbase
int main(int argc, char **argv)
{
oceanbase::common::ObLogger::get_logger().set_log_level("WARN");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}