From 10837458d53d5421b4bd81254fefe6efb27b096a Mon Sep 17 00:00:00 2001 From: Przemyslaw Skibinski Date: Thu, 9 Jun 2022 20:53:49 +0200 Subject: [PATCH] [unittest] PS-269: Initial Percona Server 8.0.12 tree ----------------------------------------------------------- PS-7949 Fix memry leak in gcs_xcom_control_interface-t test https://jira.percona.com/browse/PS-7949 ----------------------------------------------------------- PS-7949 Fix memory leaks in temptable::Allocator tests https://jira.percona.com/browse/PS-7949 --- unittest/gunit/CMakeLists.txt | 7 ++- unittest/gunit/dd.h | 2 +- unittest/gunit/innodb/lob/lot0buf.cc | 1 + unittest/gunit/innodb/log0log-t.cc | 5 -- .../xcom/gcs_xcom_control_interface-t.cc | 2 + unittest/gunit/log_timestamp-t.cc | 2 +- unittest/gunit/m_string-t.cc | 1 + unittest/gunit/mdl-t.cc | 6 ++- unittest/gunit/mysys_my_b_vprintf-t.cc | 3 +- unittest/gunit/mysys_pathfuncs-t.cc | 2 +- unittest/gunit/segfault-t.cc | 3 +- unittest/gunit/temptable_allocator-t.cc | 46 +++++++++++++--- unittest/gunit/temptable_storage-t.cc | 52 ++++++++++++------- unittest/gunit/xplugin/xpl/CMakeLists.txt | 4 ++ .../xplugin/xpl/mysql_function_names.cmake | 1 - 15 files changed, 97 insertions(+), 40 deletions(-) diff --git a/unittest/gunit/CMakeLists.txt b/unittest/gunit/CMakeLists.txt index 363a539cad18..442edc42bcda 100644 --- a/unittest/gunit/CMakeLists.txt +++ b/unittest/gunit/CMakeLists.txt @@ -126,7 +126,6 @@ SET(TESTS charset_bug32788301 collation_loader cost_estimate - dbug decimal dns_srv_data dphyp @@ -330,6 +329,12 @@ IF(HAS_WARN_FLAG) ADD_COMPILE_FLAGS(segfault-t.cc COMPILE_FLAGS ${HAS_WARN_FLAG}) ENDIF() +# Avoid 'requires dynamic R_X86_64_PC32 reloc' linker error for dd_sdi-t.cc +# when built with ASAN +IF(WITH_ASAN) + ADD_CXX_COMPILE_FLAGS_TO_FILES(-fPIC FILES dd_sdi-t.cc) +ENDIF() + # Warnings about missing PGO profile data are not useful for unit tests. DISABLE_MISSING_PROFILE_WARNING() diff --git a/unittest/gunit/dd.h b/unittest/gunit/dd.h index dc1d8d8ea146..ca54ba25db51 100644 --- a/unittest/gunit/dd.h +++ b/unittest/gunit/dd.h @@ -82,7 +82,7 @@ class Mock_dd_HANDLER : public Base_mock_HANDLER { Mock_dd_HANDLER(handlerton *hton, TABLE_SHARE *share) : Base_mock_HANDLER(hton, share) {} - virtual ~Mock_dd_HANDLER() = default; + ~Mock_dd_HANDLER() override {} }; /** diff --git a/unittest/gunit/innodb/lob/lot0buf.cc b/unittest/gunit/innodb/lob/lot0buf.cc index e59ee1deb893..a112eb81ac91 100644 --- a/unittest/gunit/innodb/lob/lot0buf.cc +++ b/unittest/gunit/innodb/lob/lot0buf.cc @@ -31,6 +31,7 @@ this program; if not, write to the Free Software Foundation, Inc., #include "lot0buf.h" #include "mach0data.h" +#include "my_compiler.h" #include "ut0byte.h" #include "ut0ut.h" diff --git a/unittest/gunit/innodb/log0log-t.cc b/unittest/gunit/innodb/log0log-t.cc index 9c1a6d14ee07..d811cb84fecf 100644 --- a/unittest/gunit/innodb/log0log-t.cc +++ b/unittest/gunit/innodb/log0log-t.cc @@ -239,11 +239,6 @@ static bool log_test_recovery() { } else { srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE; - - /* XXX: Shouldn't this be guaranteed within log0recv.cc ? */ - while (srv_thread_is_active(srv_threads.m_recv_writer)) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } } recv_sys_close(); diff --git a/unittest/gunit/libmysqlgcs/xcom/gcs_xcom_control_interface-t.cc b/unittest/gunit/libmysqlgcs/xcom/gcs_xcom_control_interface-t.cc index 2280b0dfd537..9a1c208303de 100644 --- a/unittest/gunit/libmysqlgcs/xcom/gcs_xcom_control_interface-t.cc +++ b/unittest/gunit/libmysqlgcs/xcom/gcs_xcom_control_interface-t.cc @@ -889,6 +889,8 @@ TEST_F(XComControlTest, JoinTestSkipOwnNodeAndCycleThroughPeerNodes) { result = xcom_control_if->leave(); ASSERT_EQ(GCS_OK, result); ASSERT_FALSE(xcom_control_if->is_xcom_running()); + + free(con); } TEST_F(XComControlTest, JoinTestAllPeersUnavailable) { diff --git a/unittest/gunit/log_timestamp-t.cc b/unittest/gunit/log_timestamp-t.cc index 5642ddd91375..19df6ab6da3a 100644 --- a/unittest/gunit/log_timestamp-t.cc +++ b/unittest/gunit/log_timestamp-t.cc @@ -28,7 +28,7 @@ #include "test_utils.h" #include -#include "../sql/log.h" +#include "sql/log.h" // CET: 32 bytes // date (10), 'T', time (8), '.', microseconds (6), timezone offset (6) diff --git a/unittest/gunit/m_string-t.cc b/unittest/gunit/m_string-t.cc index 774f4acaeda2..61c896de5075 100644 --- a/unittest/gunit/m_string-t.cc +++ b/unittest/gunit/m_string-t.cc @@ -63,6 +63,7 @@ TEST(MString, HumanReadableSize) { data_size *= 1000; EXPECT_EQ("1025000Y", HumanReadable(data_size)); data_size *= 1000; + EXPECT_EQ("1025000000Y", HumanReadable(data_size)); data_size *= static_cast(std::numeric_limits::max()); diff --git a/unittest/gunit/mdl-t.cc b/unittest/gunit/mdl-t.cc index 34ea754c8e11..bf30a8acb646 100644 --- a/unittest/gunit/mdl-t.cc +++ b/unittest/gunit/mdl-t.cc @@ -3779,7 +3779,11 @@ TEST_F(MDLTest, FindLockOwner) { Verify that correct error is reported when the MDL system exhausts the LF Pinbox. */ -TEST_F(MDLTest, ExhaustPinbox) { +/** + Disabled, because Percona Server allows up to 2^32 pins + and this test would take a lot of time +*/ +TEST_F(MDLTest, DISABLED_ExhaustPinbox) { for (int i = 0; i < 65535; ++i) { MDL_context c; EXPECT_FALSE(test_drive_fix_pins(&c)); diff --git a/unittest/gunit/mysys_my_b_vprintf-t.cc b/unittest/gunit/mysys_my_b_vprintf-t.cc index a5a12a3a5d80..ac47b23c018f 100644 --- a/unittest/gunit/mysys_my_b_vprintf-t.cc +++ b/unittest/gunit/mysys_my_b_vprintf-t.cc @@ -30,7 +30,8 @@ void test1(const char *res, const char *fmt, ...) { IO_CACHE info; va_list args; size_t len; - init_io_cache(&info, -1, 0, WRITE_CACHE, 0, true, MYF(0)); + int init_res = init_io_cache(&info, -1, 0, WRITE_CACHE, 0, true, MYF(0)); + EXPECT_EQ(init_res, 0); memset(info.write_buffer, 0, 64); /* RECORD_CACHE_SIZE is 64K */ va_start(args, fmt); len = my_b_vprintf(&info, fmt, args); diff --git a/unittest/gunit/mysys_pathfuncs-t.cc b/unittest/gunit/mysys_pathfuncs-t.cc index 98ae05835b69..d64815eacb1b 100644 --- a/unittest/gunit/mysys_pathfuncs-t.cc +++ b/unittest/gunit/mysys_pathfuncs-t.cc @@ -152,7 +152,7 @@ TEST(Mysys, CreateTempFile) { File fileno = create_temp_file(dst, "/tmp", prefix, 42, UNLINK_FILE, 0); EXPECT_GE(fileno, 0); my_close(fileno, 0); - EXPECT_THAT(dst, MatchesRegex("/tmp/[a]+fd=[0-9]+")); + EXPECT_THAT(dst, MatchesRegex("/tmp/[a]+(fd=[0-9]+|[a-zA-Z0-9]+)")); aset(dst, 0xaa); char *env_tmpdir = getenv("TMPDIR"); diff --git a/unittest/gunit/segfault-t.cc b/unittest/gunit/segfault-t.cc index 1763ebfe030f..5d5c9255de9d 100644 --- a/unittest/gunit/segfault-t.cc +++ b/unittest/gunit/segfault-t.cc @@ -154,7 +154,8 @@ TEST_F(FatalSignalDeathTest, Segfault) { #elif defined(HAVE_ASAN) /* gcc 4.8.1 with '-fsanitize=address -O1' */ /* Newer versions of ASAN give other error message, disable it */ -// EXPECT_DEATH_IF_SUPPORTED(*pint= 42, ".*ASAN:SIGSEGV.*"); + int *pint = nullptr; + EXPECT_DEATH_IF_SUPPORTED(*pint= 42, ".*(AddressSanitizer|ASAN):(DEADLYSIGNAL|SIGSEGV).*"); #elif defined(__APPLE__) && defined(__aarch64__) && defined(NDEBUG) // Disable also in non-debug mode on MacOS 11 arm, with -O1 or above, we get // Result: died but not with expected error. diff --git a/unittest/gunit/temptable_allocator-t.cc b/unittest/gunit/temptable_allocator-t.cc index 6afb14eba963..09a3f016f7bf 100644 --- a/unittest/gunit/temptable_allocator-t.cc +++ b/unittest/gunit/temptable_allocator-t.cc @@ -500,6 +500,26 @@ TEST_F(TempTableAllocator, block_size_cap) { EXPECT_TRUE(shared_block.is_empty()); } +struct AllocatorRaii { + AllocatorRaii(temptable::Allocator *allocator) + : m_allocator(allocator) {} + + void deallocate_all() { + for (const auto &[ptr, size] : allocs) { + m_allocator->deallocate(ptr, size); + } + } + + uint8_t *allocate(size_t n_elements) { + auto *ptr = m_allocator->allocate(n_elements); + allocs.emplace_back(ptr, n_elements); + return ptr; + } + + temptable::Allocator *m_allocator; + std::vector> allocs; +}; + TEST_F( TempTableAllocator, table_resource_monitor_increases_then_drops_to_0_when_allocation_is_backed_by_shared_block) { @@ -648,9 +668,14 @@ TEST_F(TempTableAllocator, shared_block_utilization_shall_not_impact_the_block_size_growth_policy) { temptable::TableResourceMonitor table_resource_monitor(16 * 1024 * 1024); temptable::Block shared_block; + temptable::Allocator a1(&shared_block, table_resource_monitor); temptable::Allocator a2(&shared_block, table_resource_monitor); - auto r11 = a1.allocate(512_KiB); + + AllocatorRaii a1_raii(&a1); + AllocatorRaii a2_raii(&a2); + + auto r11 = a1_raii.allocate(512_KiB); temptable::Block b11 = temptable::Block(temptable::Chunk(r11)); EXPECT_EQ(b11, shared_block); EXPECT_EQ(b11.size(), shared_block.size()); @@ -662,7 +687,7 @@ TEST_F(TempTableAllocator, // size big. // 4. Returns a pointer from shared_block. - auto r12 = a1.allocate(256_KiB); + auto r12 = a1_raii.allocate(256_KiB); temptable::Block b12 = temptable::Block(temptable::Chunk(r12)); EXPECT_EQ(b12, shared_block); EXPECT_EQ(b12.size(), shared_block.size()); @@ -672,7 +697,7 @@ TEST_F(TempTableAllocator, // 512KiB) to accomodate the 256KiB request. // 3. Returns a pointer from shared_block. - auto r13 = a1.allocate(512_KiB); + auto r13 = a1_raii.allocate(512_KiB); temptable::Block b13 = temptable::Block(temptable::Chunk(r13)); EXPECT_NE(b13, shared_block); EXPECT_NE(b13, b12); @@ -685,7 +710,7 @@ TEST_F(TempTableAllocator, // 4. It allocates the block of 2MiB of size. // 5. Returns a pointer from new block. - auto r21 = a2.allocate(512_KiB); + auto r21 = a2_raii.allocate(512_KiB); temptable::Block b21 = temptable::Block(temptable::Chunk(r21)); EXPECT_NE(b21, shared_block); EXPECT_EQ(b21.size(), 1_MiB); @@ -697,7 +722,7 @@ TEST_F(TempTableAllocator, // 4. It allocates the block of 1MiB of size. // 5. Returns a pointer from new block. - auto r14 = a1.allocate(128_KiB); + auto r14 = a1_raii.allocate(128_KiB); temptable::Block b14 = temptable::Block(temptable::Chunk(r14)); EXPECT_EQ(b14, shared_block); EXPECT_EQ(b14.size(), shared_block.size()); @@ -707,7 +732,7 @@ TEST_F(TempTableAllocator, // 256KiB = 256KiB) to accomodate the 128KiB request. // 3. Returns a pointer from shared_block. - auto r15 = a1.allocate(1_MiB - 512_KiB); + auto r15 = a1_raii.allocate(1_MiB - 512_KiB); temptable::Block b15 = temptable::Block(temptable::Chunk(r15)); EXPECT_NE(b15, shared_block); EXPECT_EQ(b15.size(), 2_MiB); @@ -720,7 +745,7 @@ TEST_F(TempTableAllocator, // 4. It allocates the block of 2MiB of size. // 3. Returns a pointer from new block. - auto r22 = a2.allocate(1_MiB); + auto r22 = a2_raii.allocate(1_MiB); temptable::Block b22 = temptable::Block(temptable::Chunk(r22)); EXPECT_NE(b22, shared_block); EXPECT_EQ(b22.size(), 2_MiB); @@ -730,6 +755,13 @@ TEST_F(TempTableAllocator, // 3. It uses the block-size growth policy to compute the block-size. // 4. It allocates the block of 2MiB of size. // 5. Returns a pointer from new block. + + a2_raii.deallocate_all(); + a1_raii.deallocate_all(); + + // Physically deallocate the shared-block (allocator keeps it alive + // intentionally) + shared_block.destroy(); } // Create some aliases to make our life easier when generating the test-cases diff --git a/unittest/gunit/temptable_storage-t.cc b/unittest/gunit/temptable_storage-t.cc index 73dbbb852f34..7b90a02859bb 100644 --- a/unittest/gunit/temptable_storage-t.cc +++ b/unittest/gunit/temptable_storage-t.cc @@ -33,29 +33,37 @@ TEST(StorageTest, Iterate) { std::thread t([]() { temptable::TableResourceMonitor table_resource_monitor(16 * 1024 * 1024); temptable::Block shared_block; - temptable::Allocator allocator(&shared_block, - table_resource_monitor); - temptable::Storage storage(&allocator); - storage.element_size(sizeof(uint64_t)); - - for (uint64_t i = 0; i < 10000; ++i) { - *static_cast(storage.allocate_back()) = i; - } - - uint64_t i = 0; - for (auto it = storage.begin(); it != storage.end(); ++it, ++i) { - EXPECT_EQ(i, *static_cast(*it)); + { + temptable::Allocator allocator(&shared_block, + table_resource_monitor); + temptable::Storage storage(&allocator); + + storage.element_size(sizeof(uint64_t)); + + for (uint64_t i = 0; i < 10000; ++i) { + *static_cast(storage.allocate_back()) = i; + } + + uint64_t i = 0; + for (auto it = storage.begin(); it != storage.end(); ++it, ++i) { + EXPECT_EQ(i, *static_cast(*it)); + } + + i = storage.size(); + auto it = storage.end(); + for (; it != storage.begin();) { + --it; + --i; + EXPECT_EQ(i, *static_cast(*it)); + } + EXPECT_EQ(0u, i); } - i = storage.size(); - auto it = storage.end(); - for (; it != storage.begin();) { - --it; - --i; - EXPECT_EQ(i, *static_cast(*it)); - } - EXPECT_EQ(0u, i); + // Deallocate the shared-block (allocator keeps it alive + // intentionally) + // Must be done after storage is destructed + shared_block.destroy(); }); t.join(); } @@ -79,6 +87,10 @@ TEST(StorageTest, AllocatorRebind) { rebound_alloc.deallocate(ptr2, 50); alloc.deallocate(shared_eater, 1048576); + + // Deallocate the shared-block (allocator keeps it alive + // intentionally) + shared_block.destroy(); }; std::thread t(thread_function); t.join(); diff --git a/unittest/gunit/xplugin/xpl/CMakeLists.txt b/unittest/gunit/xplugin/xpl/CMakeLists.txt index c5312f4c5300..2b7bdb42693b 100644 --- a/unittest/gunit/xplugin/xpl/CMakeLists.txt +++ b/unittest/gunit/xplugin/xpl/CMakeLists.txt @@ -71,6 +71,10 @@ IF(WIN32) SET_TARGET_PROPERTIES(${XPL_UNIT_TESTS} PROPERTIES COMPILE_FLAGS "/wd4373") ENDIF(WIN32) +IF(MY_COMPILER_IS_CLANG) + STRING_APPEND(CMAKE_CXX_FLAGS " -Wno-deprecated") +ENDIF() + TARGET_LINK_LIBRARIES(${XPL_UNIT_TESTS} ${GCOV_LDFLAGS} ${MYSQLX_CLIENT_LIB} diff --git a/unittest/gunit/xplugin/xpl/mysql_function_names.cmake b/unittest/gunit/xplugin/xpl/mysql_function_names.cmake index f1fbf2ce6c96..c61d385db755 100644 --- a/unittest/gunit/xplugin/xpl/mysql_function_names.cmake +++ b/unittest/gunit/xplugin/xpl/mysql_function_names.cmake @@ -74,4 +74,3 @@ GET_OTHER_FUNCTION_NAMES(${PROJECT_SOURCE_DIR}/sql/sql_yacc.yy OTHER_MYSQL_FUNCT CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mysql_function_names_t.cc.in ${MYSQLX_GENERATE_DIR}/mysql_function_names_t.cc) -