blob: 1f6e460c79c75976febcdf542f06fa7bdad2b21b [file] [log] [blame]
Austin Schuhcc6070c2020-10-10 20:25:56 -07001#include "aos/realtime.h"
2
Austin Schuh77f3f222022-06-10 16:49:21 -07003#include "glog/logging.h"
Austin Schuh61226052022-06-20 09:40:08 -07004#include "glog/raw_logging.h"
Austin Schuhcc6070c2020-10-10 20:25:56 -07005#include "gtest/gtest.h"
6
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "aos/init.h"
8
Austin Schuh77f3f222022-06-10 16:49:21 -07009DECLARE_bool(die_on_malloc);
10
Stephan Pleinesf63bde82024-01-13 15:59:33 -080011namespace aos::testing {
Austin Schuhcc6070c2020-10-10 20:25:56 -070012
13// Tests that ScopedRealtime handles the simple case.
14TEST(RealtimeTest, ScopedRealtime) {
15 CheckNotRealtime();
16 {
17 ScopedRealtime rt;
18 CheckRealtime();
19 }
20 CheckNotRealtime();
21}
22
23// Tests that ScopedRealtime handles nesting.
24TEST(RealtimeTest, DoubleScopedRealtime) {
25 CheckNotRealtime();
26 {
27 ScopedRealtime rt;
28 CheckRealtime();
29 {
30 ScopedRealtime rt2;
31 CheckRealtime();
32 }
33 CheckRealtime();
34 }
35 CheckNotRealtime();
36}
37
38// Tests that ScopedRealtime handles nesting with ScopedNotRealtime.
39TEST(RealtimeTest, ScopedNotRealtime) {
40 CheckNotRealtime();
41 {
42 ScopedRealtime rt;
43 CheckRealtime();
44 {
45 ScopedNotRealtime nrt;
46 CheckNotRealtime();
47 }
48 CheckRealtime();
49 }
50 CheckNotRealtime();
51}
52
53// Tests that ScopedRealtimeRestorer works both when starting RT and nonrt.
54TEST(RealtimeTest, ScopedRealtimeRestorer) {
55 CheckNotRealtime();
56 {
57 ScopedRealtime rt;
58 CheckRealtime();
59 {
60 ScopedRealtimeRestorer restore;
61 CheckRealtime();
62
63 MarkRealtime(false);
64 CheckNotRealtime();
65 }
66 CheckRealtime();
67 }
68 CheckNotRealtime();
69
70 {
71 ScopedRealtimeRestorer restore;
72 CheckNotRealtime();
73
74 MarkRealtime(true);
75 CheckRealtime();
76 }
77 CheckNotRealtime();
78}
79
Austin Schuh34bd4f92022-06-27 16:39:06 -070080// Malloc hooks don't work with asan/msan.
81#if !__has_feature(address_sanitizer) && !__has_feature(memory_sanitizer)
82
Austin Schuh77f3f222022-06-10 16:49:21 -070083// Tests that CHECK statements give real error messages rather than die on
84// malloc.
85TEST(RealtimeDeathTest, Check) {
86 EXPECT_DEATH(
87 {
88 ScopedRealtime rt;
89 CHECK_EQ(1, 2) << ": Numbers aren't equal.";
90 },
91 "Numbers aren't equal");
92 EXPECT_DEATH(
93 {
94 ScopedRealtime rt;
95 CHECK_GT(1, 2) << ": Cute error message";
96 },
97 "Cute error message");
98}
99
100// Tests that CHECK statements give real error messages rather than die on
101// malloc.
102TEST(RealtimeDeathTest, Fatal) {
103 EXPECT_DEATH(
104 {
105 ScopedRealtime rt;
106 LOG(FATAL) << "Cute message here";
107 },
108 "Cute message here");
109}
110
Stephan Pleines4c22d8f2024-07-10 20:01:36 -0700111TEST(RealtimeDeathTest, Malloc) {
112 EXPECT_DEATH(
113 {
114 ScopedRealtime rt;
115 volatile int *a = reinterpret_cast<volatile int *>(malloc(sizeof(int)));
116 *a = 5;
117 EXPECT_EQ(*a, 5);
118 },
119 "RAW: Malloced");
120}
121
122TEST(RealtimeDeathTest, Realloc) {
123 EXPECT_DEATH(
124 {
125 void *a = malloc(sizeof(int));
126 ScopedRealtime rt;
127 volatile int *b =
128 reinterpret_cast<volatile int *>(realloc(a, sizeof(int) * 2));
129 *b = 5;
130 EXPECT_EQ(*b, 5);
131 },
132 "RAW: Delete"); // realloc free first, then allocates
133}
134
135TEST(RealtimeDeathTest, Calloc) {
136 EXPECT_DEATH(
137 {
138 ScopedRealtime rt;
139 volatile int *a =
140 reinterpret_cast<volatile int *>(calloc(1, sizeof(int)));
141 *a = 5;
142 EXPECT_EQ(*a, 5);
143 },
144 "RAW: Malloced");
145}
146
147TEST(RealtimeDeathTest, New) {
148 EXPECT_DEATH(
149 {
150 ScopedRealtime rt;
151 volatile int *a = new int;
152 *a = 5;
153 EXPECT_EQ(*a, 5);
154 },
155 "RAW: Malloced");
156}
157
158TEST(RealtimeDeathTest, NewArray) {
159 EXPECT_DEATH(
160 {
161 ScopedRealtime rt;
162 volatile int *a = new int[3];
163 *a = 5;
164 EXPECT_EQ(*a, 5);
165 },
166 "RAW: Malloced");
167}
168
Austin Schuh77f3f222022-06-10 16:49:21 -0700169// Tests that the signal handler drops RT permission and prints out a real
170// backtrace instead of crashing on the resulting mallocs.
171TEST(RealtimeDeathTest, SignalHandler) {
172 EXPECT_DEATH(
173 {
174 ScopedRealtime rt;
175 int x = reinterpret_cast<const volatile int *>(0)[0];
176 LOG(INFO) << x;
177 },
James Kuszmaul126dcff2022-08-12 16:30:05 -0700178 "\\*\\*\\* Aborted at .*");
Austin Schuh77f3f222022-06-10 16:49:21 -0700179}
180
Austin Schuh61226052022-06-20 09:40:08 -0700181// Tests that RAW_LOG(FATAL) explodes properly.
182TEST(RealtimeDeathTest, RawFatal) {
183 EXPECT_DEATH(
184 {
185 ScopedRealtime rt;
186 RAW_LOG(FATAL, "Cute message here\n");
187 },
188 "Cute message here");
189}
190
Austin Schuh34bd4f92022-06-27 16:39:06 -0700191#endif
192
Philipp Schrader36d77932024-02-01 18:31:19 -0800193// Tests that we see which CPUs we tried to set when it fails. This can be
194// useful for debugging.
195TEST(RealtimeDeathTest, SetAffinityErrorMessage) {
196 EXPECT_DEATH({ SetCurrentThreadAffinity(MakeCpusetFromCpus({1000})); },
197 "sched_setaffinity\\(0, sizeof\\(cpuset\\), &cpuset\\) == 0 "
198 "\\{CPUs 1000\\}: Invalid argument");
199 EXPECT_DEATH(
200 {
201 SetCurrentThreadAffinity(MakeCpusetFromCpus({1000, 1001}));
202 },
203 "sched_setaffinity\\(0, sizeof\\(cpuset\\), &cpuset\\) == 0 "
204 "\\{CPUs 1000, 1001\\}: Invalid argument");
205}
206
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800207} // namespace aos::testing
Austin Schuh77f3f222022-06-10 16:49:21 -0700208
209// We need a special gtest main to force die_on_malloc support on. Otherwise
210// we can't test CHECK statements before turning die_on_malloc on globally.
211GTEST_API_ int main(int argc, char **argv) {
212 ::testing::InitGoogleTest(&argc, argv);
213 FLAGS_logtostderr = true;
Austin Schuh34bd4f92022-06-27 16:39:06 -0700214
215#if !__has_feature(address_sanitizer) && !__has_feature(memory_sanitizer)
Austin Schuh77f3f222022-06-10 16:49:21 -0700216 FLAGS_die_on_malloc = true;
Austin Schuh34bd4f92022-06-27 16:39:06 -0700217#endif
Austin Schuh77f3f222022-06-10 16:49:21 -0700218
219 aos::InitGoogle(&argc, &argv);
220
221 return RUN_ALL_TESTS();
222}