xref: /llvm-project/compiler-rt/lib/gwp_asan/tests/harness.h (revision 478648e2c0adbafa5e4cb10eb53aadbdf7de97d9)
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