From 3a0dd70d4ca695f5f00016c9fe98c4c2fe7d71c2 Mon Sep 17 00:00:00 2001 From: sbiscigl Date: Thu, 15 Aug 2024 14:30:50 -0400 Subject: [PATCH] add test checking for memory leaks using crt mem tracer --- .../CMakeLists.txt | 89 +++++++++++-------- .../RunTestsWithMemTracer.cpp | 29 ++++++ .../include/aws/testing/MemoryTesting.h | 15 ++++ .../source/MemoryTesting.cpp | 30 +++++++ tools/scripts/run_integration_tests.py | 11 +++ 5 files changed, 137 insertions(+), 37 deletions(-) create mode 100644 tests/aws-cpp-sdk-s3-crt-integration-tests/RunTestsWithMemTracer.cpp diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/CMakeLists.txt b/tests/aws-cpp-sdk-s3-crt-integration-tests/CMakeLists.txt index 9f87611adb5..25723437141 100644 --- a/tests/aws-cpp-sdk-s3-crt-integration-tests/CMakeLists.txt +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/CMakeLists.txt @@ -1,37 +1,52 @@ -add_project(aws-cpp-sdk-s3-crt-integration-tests - "Tests for the AWS S3 CRT C++ SDK" - aws-cpp-sdk-s3-crt - testing-resources - aws-cpp-sdk-core) - -file(GLOB AWS_S3_CRT_SRC - "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" -) - -file(GLOB AWS_S3_CRT_INTEGRATION_TESTS_SRC - ${AWS_S3_CRT_SRC} -) - -add_definitions(-DRESOURCES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/resources") - -if(MSVC AND BUILD_SHARED_LIBS) - add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) -endif() - -enable_testing() - -if(PLATFORM_ANDROID AND BUILD_SHARED_LIBS) - add_library(${PROJECT_NAME} ${AWS_S3_CRT_INTEGRATION_TESTS_SRC}) -else() - add_executable(${PROJECT_NAME} ${AWS_S3_CRT_INTEGRATION_TESTS_SRC}) -endif() - -set_compiler_flags(${PROJECT_NAME}) -set_compiler_warnings(${PROJECT_NAME}) - -target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS}) - -if(MSVC AND BUILD_SHARED_LIBS) - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/DELAYLOAD:aws-cpp-sdk-s3-crt.dll /DELAYLOAD:aws-cpp-sdk-core.dll") - target_link_libraries(${PROJECT_NAME} delayimp.lib) -endif() \ No newline at end of file +set(TEST_LIST "aws-cpp-sdk-s3-crt-integration-tests:RunTests.cpp") + +# Only run memlimiter test if we are building with custom memory management +if (CUSTOM_MEMORY_MANAGEMENT) + list(APPEND TEST_LIST "aws-cpp-sdk-s3-crt-memory-checked-integration-tests:RunTestsWithMemTracer.cpp") +endif () + +foreach(TEST IN LISTS TEST_LIST) + string(REPLACE ":" ";" TEST_ITEMS "${TEST}") + list(GET TEST_ITEMS 0 TEST_PROJECT_NAME) + list(GET TEST_ITEMS 1 TEST_MAIN_FILE) + + add_project("${TEST_PROJECT_NAME}" + "Tests for the AWS S3 CRT C++ SDK" + aws-cpp-sdk-s3-crt + testing-resources + aws-cpp-sdk-core) + + file(GLOB AWS_S3_CRT_SRC + "${TEST_MAIN_FILE}" + "BucketAndObjectOperationTest.cpp" + "S3ExpressTest.cpp" + ) + + file(GLOB AWS_S3_CRT_INTEGRATION_TESTS_SRC + ${AWS_S3_CRT_SRC} + ) + + add_definitions(-DRESOURCES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/resources") + + if(MSVC AND BUILD_SHARED_LIBS) + add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) + endif() + + enable_testing() + + if(PLATFORM_ANDROID AND BUILD_SHARED_LIBS) + add_library(${PROJECT_NAME} ${AWS_S3_CRT_INTEGRATION_TESTS_SRC}) + else() + add_executable(${PROJECT_NAME} ${AWS_S3_CRT_INTEGRATION_TESTS_SRC}) + endif() + + set_compiler_flags(${PROJECT_NAME}) + set_compiler_warnings(${PROJECT_NAME}) + + target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS}) + + if(MSVC AND BUILD_SHARED_LIBS) + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/DELAYLOAD:aws-cpp-sdk-s3-crt.dll /DELAYLOAD:aws-cpp-sdk-core.dll") + target_link_libraries(${PROJECT_NAME} delayimp.lib) + endif() +endforeach () diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/RunTestsWithMemTracer.cpp b/tests/aws-cpp-sdk-s3-crt-integration-tests/RunTestsWithMemTracer.cpp new file mode 100644 index 00000000000..b0fbe1b1930 --- /dev/null +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/RunTestsWithMemTracer.cpp @@ -0,0 +1,29 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include +#include +#include +#include +#include + +int main(int argc, char** argv) { + Aws::Testing::SetDefaultSigPipeHandler(); + Aws::SDKOptions options; + options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace; + CRTMemTracerMemorySystem memorySystem{}; + options.memoryManagementOptions.memoryManager = &memorySystem; + Aws::Testing::InitPlatformTest(options); + Aws::Testing::ParseArgs(argc, argv); + + Aws::InitAPI(options); + ::testing::InitGoogleTest(&argc, argv); + int exitCode = RUN_ALL_TESTS(); + + Aws::ShutdownAPI(options); + memorySystem.AssertNoLeaks(); + Aws::Testing::ShutdownPlatformTest(options); + return exitCode; +} diff --git a/tests/testing-resources/include/aws/testing/MemoryTesting.h b/tests/testing-resources/include/aws/testing/MemoryTesting.h index be3c69ec6bc..23069a3301c 100644 --- a/tests/testing-resources/include/aws/testing/MemoryTesting.h +++ b/tests/testing-resources/include/aws/testing/MemoryTesting.h @@ -9,12 +9,14 @@ #include #include +#include #include #include #include #include #include +#include // Could be folded into ExactTestMemorySystem, tracks some aggregate stats class AWS_TESTING_API BaseTestMemorySystem : public Aws::Utils::Memory::MemorySystemInterface @@ -108,6 +110,19 @@ class AWS_TESTING_API ExactTestMemorySystem : public BaseTestMemorySystem }; +class AWS_TESTING_API CRTMemTracerMemorySystem : public Aws::Utils::Memory::MemorySystemInterface +{ +public: + CRTMemTracerMemorySystem(); + void Begin() override {} + void End() override {} + void* AllocateMemory(std::size_t blockSize, std::size_t alignment, const char* allocationTag) override; + void FreeMemory(void* memoryPtr) override; + void AssertNoLeaks(); +private: + std::unique_ptr> mem_tracer_; +}; + #ifdef USE_AWS_MEMORY_MANAGEMENT // Utility macros to put at the start and end of tests diff --git a/tests/testing-resources/source/MemoryTesting.cpp b/tests/testing-resources/source/MemoryTesting.cpp index ed4d8adba25..3c105ddada6 100644 --- a/tests/testing-resources/source/MemoryTesting.cpp +++ b/tests/testing-resources/source/MemoryTesting.cpp @@ -127,6 +127,36 @@ void ExactTestMemorySystem::Cleanup() free(m_buckets); } +CRTMemTracerMemorySystem::CRTMemTracerMemorySystem(): + mem_tracer_{ + aws_mem_tracer_new( + aws_default_allocator(), + nullptr, + AWS_MEMTRACE_STACKS, + 10), + aws_mem_tracer_destroy} +{}; + +void* CRTMemTracerMemorySystem::AllocateMemory(std::size_t blockSize, std::size_t alignment, const char* allocationTag) +{ + AWS_UNREFERENCED_PARAM(alignment); + AWS_UNREFERENCED_PARAM(allocationTag); + return aws_mem_acquire(mem_tracer_.get(), blockSize); +} + +void CRTMemTracerMemorySystem::FreeMemory(void* memoryPtr) +{ + aws_mem_release(mem_tracer_.get(), memoryPtr); +} + +void CRTMemTracerMemorySystem::AssertNoLeaks() +{ + const size_t leaked_allocations = aws_mem_tracer_count(mem_tracer_.get()); + const size_t leaked_bytes = aws_mem_tracer_bytes(mem_tracer_.get()); + EXPECT_EQ(0ul, leaked_allocations); + EXPECT_EQ(0ul, leaked_bytes); +} + void ExactTestMemorySystem::GrowFreePool() { // malloc enough memory to hold the linked list pointer as well as the desired number of TaggedMemoryTrackers diff --git a/tools/scripts/run_integration_tests.py b/tools/scripts/run_integration_tests.py index f9df5418170..48d0dd9c47c 100644 --- a/tools/scripts/run_integration_tests.py +++ b/tools/scripts/run_integration_tests.py @@ -55,6 +55,17 @@ def main(): "aws-cpp-sdk-ec2-integration-tests", "aws-cpp-sdk-timestream-query-integration-tests"] + # check for existence of these binaries before adding them to tests + # as they will not always be present + cmake_dependent_tests = [ + "aws-cpp-sdk-s3-crt-memory-checked-integration-tests" + ] + + for test in cmake_dependent_tests: + test_exe = os.path.join(arguments["testDir"], test if test_has_parent_dir else "", test) + exe_extension + if os.path.isfile(test_exe): + test_list.append("aws-cpp-sdk-s3-crt-memory-checked-integration-tests") + random.shuffle(test_list) for testName in test_list: