xref: /aosp_15_r20/system/libbase/include/android-base/silent_death_test.h (revision 8f0ba417480079999ba552f1087ae592091b9d02)
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <signal.h>
20 #include <gtest/gtest.h>
21 
22 #include <array>
23 #include <memory>
24 
25 #if !defined(__BIONIC__)
26 #define sigaction64 sigaction
27 #endif
28 
29 // INTRODUCTION
30 //
31 // It can be useful to disable debuggerd stack traces/tombstones in death tests.
32 // Reasons include:
33 //
34 //   1. speeding up death tests
35 //   2. reducing the noise in logcat (for humans)
36 //   3. avoiding bots from thinking that expected deaths should be reported in
37 //      stability metrics/have bugs auto-filed
38 //
39 // When writing new death tests, inherit the test suite from SilentDeathTest
40 // defined below.
41 //
42 // Only use ScopedSilentDeath in a test case/suite if changing the test base
43 // class from testing::Test to SilentDeathTest adds additional complextity when
44 // test suite code is shared between death and non-death tests.
45 //
46 // EXAMPLES
47 //
48 // For example, use SilentDeathTest for this simple case where there's no shared
49 // setup or teardown:
50 //
51 //   using FooDeathTest = SilentDeathTest;
52 //
53 //   TEST(FooTest, DoesThis) {
54 //     // normal test
55 //   }
56 //
57 //   TEST_F(FooDeathTest, DoesThat) {
58 //     // death test
59 //   }
60 //
61 // Alternatively, use ScopedSilentDeath if you already have a Test subclass for
62 // shared setup or teardown:
63 //
64 //   class FooTest : public testing::Test { ... /* shared setup/teardown */ };
65 //
66 //   using FooDeathTest = FooTest;
67 //
68 //   TEST_F(FooTest, DoesThis) {
69 //     // normal test
70 //   }
71 //
72 //   TEST_F(FooDeathTest, DoesThat) {
73 //     ScopedSilentDeath _silentDeath;
74 //     // death test
75 //   }
76 //
77 // NOTES
78 //
79 // When writing death tests, consider using ASSERT_EXIT() and EXPECT_EXIT()
80 // rather than the more obvious ASSERT_DEATH()/EXPECT_DEATH() macros... The
81 // advantage is that you can specify a regular expression that you expect
82 // the abort message to match, and can be explicit about what signal you expect
83 // to die with, and you can also test for *successful* exits too. Examples:
84 //
85 //   ASSERT_DEATH(foo(), "some text\\. some more\\.");
86 //
87 //   ASSERT_EXIT(bar(), testing::ExitedWithCode(0), "Success");
88 //
89 //   ASSERT_EXIT(baz(), testing::KilledBySignal(SIGABRT),
90 //               "expected detail message \\(blah\\)");
91 //
92 // As you can see the regular expression functionality is there for
93 // ASSERT_DEATH() too, but it's important to realize that it's a regular
94 // expression, so (as in the first and third examples), you'll need to quote
95 // any metacharacters (and because it's a string literal, you'll either need
96 // extra quoting or want to use a raw string).
97 
98 class ScopedSilentDeath {
99  public:
ScopedSilentDeath()100   ScopedSilentDeath() {
101 #if !defined(_WIN32)
102     for (int signo : SUPPRESSED_SIGNALS) {
103       struct sigaction64 action = {.sa_handler = SIG_DFL};
104       sigaction64(signo, &action, &previous_);
105     }
106 #endif
107   }
108 
~ScopedSilentDeath()109   ~ScopedSilentDeath() {
110 #if !defined(_WIN32)
111     for (int signo : SUPPRESSED_SIGNALS) {
112       sigaction64(signo, &previous_, nullptr);
113     }
114 #endif
115   }
116 
117  private:
118 #if !defined(_WIN32)
119   static constexpr std::array<int, 4> SUPPRESSED_SIGNALS = {SIGABRT, SIGBUS, SIGSEGV, SIGSYS};
120 
121   struct sigaction64 previous_;
122 #endif
123 };
124 
125 class SilentDeathTest : public testing::Test {
126  protected:
SetUp()127   void SetUp() override {
128     silent_death_ = std::unique_ptr<ScopedSilentDeath>(new ScopedSilentDeath);
129   }
130 
TearDown()131   void TearDown() override { silent_death_.reset(); }
132 
133  private:
134   std::unique_ptr<ScopedSilentDeath> silent_death_;
135 };
136