From 3449f775a675c8c024cc4c311179d040594abb44 Mon Sep 17 00:00:00 2001 From: obdev Date: Thu, 4 Jul 2024 05:16:18 +0000 Subject: [PATCH] fix ObSEArray::pop_back bug --- deps/oblib/src/lib/container/ob_se_array.h | 11 ++- unittest/CMakeLists.txt | 1 + unittest/lib/CMakeLists.txt | 1 + unittest/lib/test_ob_searray.cpp | 95 ++++++++++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 unittest/lib/CMakeLists.txt create mode 100644 unittest/lib/test_ob_searray.cpp diff --git a/deps/oblib/src/lib/container/ob_se_array.h b/deps/oblib/src/lib/container/ob_se_array.h index 6dad1b1e9..2f95e6b87 100644 --- a/deps/oblib/src/lib/container/ob_se_array.h +++ b/deps/oblib/src/lib/container/ob_se_array.h @@ -87,6 +87,7 @@ struct ObClassOp static int construct_and_assign(const T &src, T &addr); static int array_remove(T* arr, int64_t &arr_size, int64_t idx); static T* default_construct(T &addr); + static void default_destruct(T &addr); static void array_default_construct(T *addr, int64_t arr_size); static int array_assign(const T *src_arr, T *dst_arr, int64_t arr_size); static int array_expand(const T *orig_arr, T *new_arr, int64_t orig_size); @@ -121,6 +122,10 @@ struct ObClassOp { return &addr; } + OB_INLINE static void default_destruct(T &addr) + { + UNUSED(addr); + } OB_INLINE static void array_default_construct(T *addr, int64_t arr_size) { MEMSET(addr, 0, sizeof(T) * arr_size); @@ -187,6 +192,10 @@ struct ObClassOp { return new(&addr) T(); } + OB_INLINE static void default_destruct(T &addr) + { + addr.~T(); + } OB_INLINE static void array_default_construct(T *addr, int64_t arr_size) { for (int64_t i = 0; i < arr_size; ++i) { @@ -578,7 +587,7 @@ void ObSEArrayImpl::pop_back() { if (OB_UNLIKELY(count_ <= 0)) { } else { - --count_; + MyOp::default_destruct(data_[--count_]); } } diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 1444b4504..d4d2504c5 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -29,6 +29,7 @@ add_subdirectory(logservice) add_subdirectory(storage) add_subdirectory(observer) add_subdirectory(share) +add_subdirectory(lib) add_subdirectory(rootserver) add_subdirectory(tools) add_subdirectory(data_dictionary) diff --git a/unittest/lib/CMakeLists.txt b/unittest/lib/CMakeLists.txt new file mode 100644 index 000000000..49bcdb7ff --- /dev/null +++ b/unittest/lib/CMakeLists.txt @@ -0,0 +1 @@ +ob_unittest(test_ob_searray) diff --git a/unittest/lib/test_ob_searray.cpp b/unittest/lib/test_ob_searray.cpp new file mode 100644 index 000000000..9c6a1d472 --- /dev/null +++ b/unittest/lib/test_ob_searray.cpp @@ -0,0 +1,95 @@ +/** + * 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 +#include +#include "lib/container/ob_se_array.h" + +namespace oceanbase +{ +using namespace common; + +namespace unittest +{ + +class TestObSEArray : public ::testing::Test +{ +public : + virtual void SetUp() {} + virtual void TearDown() {} +}; + +static int64_t g_count = 0; + +class TestObj +{ +public: + TestObj() : t_(0) { g_count++; } + explicit TestObj(const int v) : t_(v) { g_count++; } + TestObj(const TestObj &obj) { t_ = obj.t_; g_count++; } + ~TestObj() { g_count--; } + int get_value() const { return t_; } + TO_STRING_KV(K_(t)); +private: + int t_; +}; + +TEST(TestObSEArray, pop_back) +{ + static const int magic_num = 2651356; + static const int64_t LOCAL_ARRAY_SIZE = 4; + static const int64_t MAX_OBJ_COUNT = LOCAL_ARRAY_SIZE + 16; + ObSEArray a1; + ObSEArray a2; + + for (int64_t i = 0; i < MAX_OBJ_COUNT; i++) { + ASSERT_EQ(OB_SUCCESS, a1.push_back(TestObj(magic_num))); + ASSERT_EQ(OB_SUCCESS, a2.push_back(magic_num)); + } + + ASSERT_EQ(MAX_OBJ_COUNT, g_count); + + for (int64_t i = 0; i < MAX_OBJ_COUNT / 2; i++) { + a1.pop_back(); + a2.pop_back(); + } + + ASSERT_EQ(MAX_OBJ_COUNT - MAX_OBJ_COUNT / 2, g_count); + + { + TestObj tmp_obj; + ASSERT_EQ(OB_SUCCESS, a1.pop_back(tmp_obj)); + ASSERT_EQ(magic_num, tmp_obj.get_value()); + } + + int tmp = 0; + ASSERT_EQ(OB_SUCCESS, a2.pop_back(tmp)); + ASSERT_EQ(magic_num, tmp); + + ASSERT_EQ(MAX_OBJ_COUNT - MAX_OBJ_COUNT / 2 - 1, g_count); + + a1.destroy(); + a2.destroy(); + + ASSERT_EQ(0, g_count); +} + +} // end of unittest +} // end of oceanbase + +int main(int argc, char **argv) +{ + OB_LOGGER.set_file_name("test_ob_se_array.log", true); + OB_LOGGER.set_log_level("INFO"); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}