1a95edb9dSMitch Phillips //===-- harness.h -----------------------------------------------*- C++ -*-===// 2a95edb9dSMitch Phillips // 3a95edb9dSMitch Phillips // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a95edb9dSMitch Phillips // See https://llvm.org/LICENSE.txt for license information. 5a95edb9dSMitch Phillips // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a95edb9dSMitch Phillips // 7a95edb9dSMitch Phillips //===----------------------------------------------------------------------===// 8a95edb9dSMitch Phillips 9a95edb9dSMitch Phillips #ifndef GWP_ASAN_TESTS_HARNESS_H_ 10a95edb9dSMitch Phillips #define GWP_ASAN_TESTS_HARNESS_H_ 11a95edb9dSMitch Phillips 1227d69b2fSMitch Phillips #include <stdarg.h> 13a95edb9dSMitch Phillips 145556616bSKostya Kortchinsky #if defined(__Fuchsia__) 15*478648e2SCaslyn Tonelli #ifndef ZXTEST_USE_STREAMABLE_MACROS 1621fc42b2SAlex Brachet #define ZXTEST_USE_STREAMABLE_MACROS 17*478648e2SCaslyn Tonelli #endif 185556616bSKostya Kortchinsky #include <zxtest/zxtest.h> 19b27f657fSAlex Brachet namespace testing = zxtest; 20f2a1726dSCaslyn Tonelli // zxtest defines a different ASSERT_DEATH, taking a lambda and an error message 21f2a1726dSCaslyn Tonelli // if death didn't occur, versus gtest taking a statement and a string to search 22f2a1726dSCaslyn Tonelli // for in the dying process. zxtest doesn't define an EXPECT_DEATH, so we use 23f2a1726dSCaslyn Tonelli // that in the tests below (which works as intended for gtest), and we define 24f2a1726dSCaslyn Tonelli // EXPECT_DEATH as a wrapper for zxtest's ASSERT_DEATH. Note that zxtest drops 25f2a1726dSCaslyn Tonelli // the functionality for checking for a particular message in death. 26f2a1726dSCaslyn Tonelli #define EXPECT_DEATH(X, Y) ASSERT_DEATH(([&] { X; }), "") 275556616bSKostya Kortchinsky #else 2827d69b2fSMitch Phillips #include "gtest/gtest.h" 295556616bSKostya Kortchinsky #endif 30a95edb9dSMitch Phillips 31a95edb9dSMitch Phillips #include "gwp_asan/guarded_pool_allocator.h" 327339ca27SMitch Phillips #include "gwp_asan/optional/backtrace.h" 33a8520f69SMitch Phillips #include "gwp_asan/optional/printf.h" 34a6258684SMitch Phillips #include "gwp_asan/optional/segv_handler.h" 350bfc4890SMitch Phillips #include "gwp_asan/options.h" 36a95edb9dSMitch Phillips 3727d69b2fSMitch Phillips namespace gwp_asan { 3827d69b2fSMitch Phillips namespace test { 3927d69b2fSMitch Phillips // This printf-function getter allows other platforms (e.g. Android) to define 4027d69b2fSMitch Phillips // their own signal-safe Printf function. In LLVM, we use 4127d69b2fSMitch Phillips // `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf 4227d69b2fSMitch Phillips // for this purpose. 43a8520f69SMitch Phillips Printf_t getPrintfFunction(); 4427d69b2fSMitch Phillips }; // namespace test 4527d69b2fSMitch Phillips }; // namespace gwp_asan 4627d69b2fSMitch Phillips 4735b5499dSMitch Phillips char *AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA); 4835b5499dSMitch Phillips void DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 4935b5499dSMitch Phillips void DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 5035b5499dSMitch Phillips void TouchMemory(void *Ptr); 5135b5499dSMitch Phillips 52bc949f92SMitch Phillips void CheckOnlyOneGwpAsanCrash(const std::string &OutputBuffer); 53bc949f92SMitch Phillips 54b27f657fSAlex Brachet class DefaultGuardedPoolAllocator : public ::testing::Test { 55a95edb9dSMitch Phillips public: 56596d0614SEvgenii Stepanov void SetUp() override { 57a95edb9dSMitch Phillips gwp_asan::options::Options Opts; 58a95edb9dSMitch Phillips MaxSimultaneousAllocations = Opts.MaxSimultaneousAllocations; 59a95edb9dSMitch Phillips GPA.init(Opts); 60a95edb9dSMitch Phillips } 61a95edb9dSMitch Phillips 62596d0614SEvgenii Stepanov void TearDown() override { GPA.uninitTestOnly(); } 63596d0614SEvgenii Stepanov 64a95edb9dSMitch Phillips protected: 65a95edb9dSMitch Phillips gwp_asan::GuardedPoolAllocator GPA; 66a95edb9dSMitch Phillips decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 67a95edb9dSMitch Phillips MaxSimultaneousAllocations; 68a95edb9dSMitch Phillips }; 69a95edb9dSMitch Phillips 70b27f657fSAlex Brachet class CustomGuardedPoolAllocator : public ::testing::Test { 71a95edb9dSMitch Phillips public: 72a95edb9dSMitch Phillips void 73a95edb9dSMitch Phillips InitNumSlots(decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 74a95edb9dSMitch Phillips MaxSimultaneousAllocationsArg) { 75a95edb9dSMitch Phillips gwp_asan::options::Options Opts; 76a95edb9dSMitch Phillips Opts.MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg; 77a95edb9dSMitch Phillips MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg; 78a95edb9dSMitch Phillips GPA.init(Opts); 79a95edb9dSMitch Phillips } 80a95edb9dSMitch Phillips 81596d0614SEvgenii Stepanov void TearDown() override { GPA.uninitTestOnly(); } 82596d0614SEvgenii Stepanov 83a95edb9dSMitch Phillips protected: 84a95edb9dSMitch Phillips gwp_asan::GuardedPoolAllocator GPA; 85a95edb9dSMitch Phillips decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 86a95edb9dSMitch Phillips MaxSimultaneousAllocations; 87a95edb9dSMitch Phillips }; 88a95edb9dSMitch Phillips 8935b5499dSMitch Phillips class BacktraceGuardedPoolAllocator 90b27f657fSAlex Brachet : public ::testing::TestWithParam</* Recoverable */ bool> { 917339ca27SMitch Phillips public: 92596d0614SEvgenii Stepanov void SetUp() override { 937339ca27SMitch Phillips gwp_asan::options::Options Opts; 94a8520f69SMitch Phillips Opts.Backtrace = gwp_asan::backtrace::getBacktraceFunction(); 957339ca27SMitch Phillips GPA.init(Opts); 96a6258684SMitch Phillips 9735b5499dSMitch Phillips // In recoverable mode, capture GWP-ASan logs to an internal buffer so that 9835b5499dSMitch Phillips // we can search it in unit tests. For non-recoverable tests, the default 9935b5499dSMitch Phillips // buffer is fine, as any tests should be EXPECT_DEATH()'d. 10035b5499dSMitch Phillips Recoverable = GetParam(); 10135b5499dSMitch Phillips gwp_asan::Printf_t PrintfFunction = PrintfToBuffer; 10235b5499dSMitch Phillips GetOutputBuffer().clear(); 10335b5499dSMitch Phillips if (!Recoverable) 10435b5499dSMitch Phillips PrintfFunction = gwp_asan::test::getPrintfFunction(); 10535b5499dSMitch Phillips 106a8520f69SMitch Phillips gwp_asan::segv_handler::installSignalHandlers( 10735b5499dSMitch Phillips &GPA, PrintfFunction, gwp_asan::backtrace::getPrintBacktraceFunction(), 10835b5499dSMitch Phillips gwp_asan::backtrace::getSegvBacktraceFunction(), 10935b5499dSMitch Phillips /* Recoverable */ Recoverable); 1107339ca27SMitch Phillips } 1117339ca27SMitch Phillips 112a6258684SMitch Phillips void TearDown() override { 113a6258684SMitch Phillips GPA.uninitTestOnly(); 114a8520f69SMitch Phillips gwp_asan::segv_handler::uninstallSignalHandlers(); 115a6258684SMitch Phillips } 116596d0614SEvgenii Stepanov 1177339ca27SMitch Phillips protected: 11835b5499dSMitch Phillips static std::string &GetOutputBuffer() { 11935b5499dSMitch Phillips static std::string Buffer; 12035b5499dSMitch Phillips return Buffer; 12135b5499dSMitch Phillips } 12235b5499dSMitch Phillips 12335b5499dSMitch Phillips __attribute__((format(printf, 1, 2))) static void 12435b5499dSMitch Phillips PrintfToBuffer(const char *Format, ...) { 12535b5499dSMitch Phillips va_list AP; 12635b5499dSMitch Phillips va_start(AP, Format); 12735b5499dSMitch Phillips char Buffer[8192]; 12835b5499dSMitch Phillips vsnprintf(Buffer, sizeof(Buffer), Format, AP); 12935b5499dSMitch Phillips GetOutputBuffer() += Buffer; 13035b5499dSMitch Phillips va_end(AP); 13135b5499dSMitch Phillips } 13235b5499dSMitch Phillips 1337339ca27SMitch Phillips gwp_asan::GuardedPoolAllocator GPA; 13435b5499dSMitch Phillips bool Recoverable; 1357339ca27SMitch Phillips }; 1367339ca27SMitch Phillips 137dd1c4bd0SMitch Phillips // https://github.com/google/googletest/blob/master/docs/advanced.md#death-tests-and-threads 138dd1c4bd0SMitch Phillips using DefaultGuardedPoolAllocatorDeathTest = DefaultGuardedPoolAllocator; 139dd1c4bd0SMitch Phillips using CustomGuardedPoolAllocatorDeathTest = CustomGuardedPoolAllocator; 140dd1c4bd0SMitch Phillips using BacktraceGuardedPoolAllocatorDeathTest = BacktraceGuardedPoolAllocator; 141dd1c4bd0SMitch Phillips 142a95edb9dSMitch Phillips #endif // GWP_ASAN_TESTS_HARNESS_H_ 143