1 //===--- rtsan_test.cpp - Realtime Sanitizer --------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Introduces basic functional tests for the realtime sanitizer. 10 // Not meant to be exhaustive, testing all interceptors, please see 11 // test_rtsan_interceptors.cpp for those tests. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "gtest/gtest.h" 16 17 #include "rtsan_test_utilities.h" 18 #include <rtsan.h> 19 #include <sanitizer_common/sanitizer_platform.h> 20 #include <sanitizer_common/sanitizer_platform_interceptors.h> 21 22 #include <array> 23 #include <atomic> 24 #include <chrono> 25 #include <fstream> 26 #include <mutex> 27 #include <shared_mutex> 28 #include <thread> 29 30 #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ 31 __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200 32 #define SI_MAC_DEPLOYMENT_AT_LEAST_10_12 1 33 #else 34 #define SI_MAC_DEPLOYMENT_AT_LEAST_10_12 0 35 #endif 36 37 #define RTSAN_TEST_SHARED_MUTEX (!(SI_MAC) || SI_MAC_DEPLOYMENT_AT_LEAST_10_12) 38 39 using namespace testing; 40 using namespace rtsan_testing; 41 using namespace std::chrono_literals; 42 43 TEST(TestRtsan, VectorPushBackAllocationDiesWhenRealtime) { 44 std::vector<float> vec; 45 auto Func = [&vec]() { vec.push_back(0.4f); }; 46 ExpectRealtimeDeath(Func); 47 ASSERT_EQ(0u, vec.size()); 48 ExpectNonRealtimeSurvival(Func); 49 ASSERT_EQ(1u, vec.size()); 50 } 51 52 TEST(TestRtsan, DestructionOfObjectOnHeapDiesWhenRealtime) { 53 auto allocated_ptr = std::make_unique<std::array<float, 256>>(); 54 auto Func = [&allocated_ptr]() { allocated_ptr.reset(); }; 55 ExpectRealtimeDeath(Func); 56 ASSERT_NE(nullptr, allocated_ptr.get()); 57 ExpectNonRealtimeSurvival(Func); 58 ASSERT_EQ(nullptr, allocated_ptr.get()); 59 } 60 61 TEST(TestRtsan, SleepingAThreadDiesWhenRealtime) { 62 auto Func = []() { std::this_thread::sleep_for(1us); }; 63 ExpectRealtimeDeath(Func); 64 ExpectNonRealtimeSurvival(Func); 65 } 66 67 TEST(TestRtsan, IfstreamCreationDiesWhenRealtime) { 68 auto Func = []() { std::ifstream ifs{"./file.txt"}; }; 69 ExpectRealtimeDeath(Func); 70 ExpectNonRealtimeSurvival(Func); 71 std::remove("./file.txt"); 72 } 73 74 TEST(TestRtsan, OfstreamCreationDiesWhenRealtime) { 75 auto Func = []() { std::ofstream ofs{"./file.txt"}; }; 76 ExpectRealtimeDeath(Func); 77 ExpectNonRealtimeSurvival(Func); 78 std::remove("./file.txt"); 79 } 80 81 TEST(TestRtsan, LockingAMutexDiesWhenRealtime) { 82 std::mutex mutex; 83 auto Func = [&]() { mutex.lock(); }; 84 ExpectRealtimeDeath(Func); 85 ExpectNonRealtimeSurvival(Func); 86 } 87 88 TEST(TestRtsan, UnlockingAMutexDiesWhenRealtime) { 89 std::mutex mutex; 90 mutex.lock(); 91 auto Func = [&]() { mutex.unlock(); }; 92 ExpectRealtimeDeath(Func); 93 ExpectNonRealtimeSurvival(Func); 94 } 95 96 #if RTSAN_TEST_SHARED_MUTEX 97 98 TEST(TestRtsan, LockingASharedMutexDiesWhenRealtime) { 99 std::shared_mutex mutex; 100 auto Func = [&]() { mutex.lock(); }; 101 ExpectRealtimeDeath(Func); 102 ExpectNonRealtimeSurvival(Func); 103 } 104 105 TEST(TestRtsan, UnlockingASharedMutexDiesWhenRealtime) { 106 std::shared_mutex mutex; 107 mutex.lock(); 108 auto Func = [&]() { mutex.unlock(); }; 109 ExpectRealtimeDeath(Func); 110 ExpectNonRealtimeSurvival(Func); 111 } 112 113 TEST(TestRtsan, SharedLockingASharedMutexDiesWhenRealtime) { 114 std::shared_mutex mutex; 115 auto Func = [&]() { mutex.lock_shared(); }; 116 ExpectRealtimeDeath(Func); 117 ExpectNonRealtimeSurvival(Func); 118 } 119 120 TEST(TestRtsan, SharedUnlockingASharedMutexDiesWhenRealtime) { 121 std::shared_mutex mutex; 122 mutex.lock_shared(); 123 auto Func = [&]() { mutex.unlock_shared(); }; 124 ExpectRealtimeDeath(Func); 125 ExpectNonRealtimeSurvival(Func); 126 } 127 128 #endif // RTSAN_TEST_SHARED_MUTEX 129 130 TEST(TestRtsan, LaunchingAThreadDiesWhenRealtime) { 131 auto Func = [&]() { 132 std::thread Thread{[]() {}}; 133 Thread.join(); 134 }; 135 ExpectRealtimeDeath(Func); 136 ExpectNonRealtimeSurvival(Func); 137 } 138 139 namespace { 140 void InvokeStdFunction(std::function<void()> &&function) { function(); } 141 } // namespace 142 143 TEST(TestRtsan, CopyingALambdaWithLargeCaptureDiesWhenRealtime) { 144 std::array<float, 16> lots_of_data; 145 auto lambda = [lots_of_data]() mutable { 146 // Stop everything getting optimised out 147 lots_of_data[3] = 0.25f; 148 EXPECT_EQ(16, lots_of_data.size()); 149 EXPECT_EQ(0.25f, lots_of_data[3]); 150 }; 151 auto Func = [&]() { InvokeStdFunction(lambda); }; 152 ExpectRealtimeDeath(Func); 153 ExpectNonRealtimeSurvival(Func); 154 } 155 156 TEST(TestRtsan, AccessingALargeAtomicVariableDiesWhenRealtime) { 157 std::atomic<float> small_atomic{0.0f}; 158 ASSERT_TRUE(small_atomic.is_lock_free()); 159 RealtimeInvoke([&small_atomic]() { float x = small_atomic.load(); }); 160 161 std::atomic<std::array<float, 2048>> large_atomic; 162 ASSERT_FALSE(large_atomic.is_lock_free()); 163 auto Func = [&]() { auto x = large_atomic.load(); }; 164 ExpectRealtimeDeath(Func); 165 ExpectNonRealtimeSurvival(Func); 166 } 167 168 TEST(TestRtsan, FirstCoutDiesWhenRealtime) { 169 auto Func = []() { std::cout << "Hello, world!" << std::endl; }; 170 ExpectRealtimeDeath(Func); 171 ExpectNonRealtimeSurvival(Func); 172 } 173 174 TEST(TestRtsan, SecondCoutDiesWhenRealtime) { 175 std::cout << "Hello, world"; 176 auto Func = []() { std::cout << "Hello, again!" << std::endl; }; 177 ExpectRealtimeDeath(Func); 178 ExpectNonRealtimeSurvival(Func); 179 } 180 181 TEST(TestRtsan, PrintfDiesWhenRealtime) { 182 auto Func = []() { printf("Hello, world!\n"); }; 183 ExpectRealtimeDeath(Func); 184 ExpectNonRealtimeSurvival(Func); 185 } 186 187 TEST(TestRtsan, ThrowingAnExceptionDiesWhenRealtime) { 188 auto Func = [&]() { 189 try { 190 throw std::exception(); 191 } catch (std::exception &) { 192 } 193 }; 194 ExpectRealtimeDeath(Func); 195 ExpectNonRealtimeSurvival(Func); 196 } 197 198 TEST(TestRtsan, DoesNotDieIfTurnedOff) { 199 std::mutex mutex; 200 auto RealtimeUnsafeFunc = [&]() { 201 __rtsan_off(); 202 mutex.lock(); 203 mutex.unlock(); 204 __rtsan_on(); 205 }; 206 RealtimeInvoke(RealtimeUnsafeFunc); 207 } 208