aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/compiler-rt/lib/rtsan/tests/rtsan_test_functional.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/compiler-rt/lib/rtsan/tests/rtsan_test_functional.cpp')
-rw-r--r--contrib/llvm-project/compiler-rt/lib/rtsan/tests/rtsan_test_functional.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/contrib/llvm-project/compiler-rt/lib/rtsan/tests/rtsan_test_functional.cpp b/contrib/llvm-project/compiler-rt/lib/rtsan/tests/rtsan_test_functional.cpp
new file mode 100644
index 000000000000..97afb1eefb64
--- /dev/null
+++ b/contrib/llvm-project/compiler-rt/lib/rtsan/tests/rtsan_test_functional.cpp
@@ -0,0 +1,207 @@
+//===--- rtsan_test.cpp - Realtime Sanitizer --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Introduces basic functional tests for the realtime sanitizer.
+// Not meant to be exhaustive, testing all interceptors, please see
+// test_rtsan_interceptors.cpp for those tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "rtsan_test_utilities.h"
+#include <rtsan.h>
+#include <sanitizer_common/sanitizer_platform.h>
+#include <sanitizer_common/sanitizer_platform_interceptors.h>
+
+#include <array>
+#include <atomic>
+#include <chrono>
+#include <fstream>
+#include <mutex>
+#include <shared_mutex>
+#include <thread>
+
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
+#define SI_MAC_DEPLOYMENT_AT_LEAST_10_12 1
+#else
+#define SI_MAC_DEPLOYMENT_AT_LEAST_10_12 0
+#endif
+
+#define RTSAN_TEST_SHARED_MUTEX (!(SI_MAC) || SI_MAC_DEPLOYMENT_AT_LEAST_10_12)
+
+using namespace testing;
+using namespace rtsan_testing;
+using namespace std::chrono_literals;
+
+TEST(TestRtsan, VectorPushBackAllocationDiesWhenRealtime) {
+ std::vector<float> vec;
+ auto Func = [&vec]() { vec.push_back(0.4f); };
+ ExpectRealtimeDeath(Func);
+ ASSERT_EQ(0u, vec.size());
+ ExpectNonRealtimeSurvival(Func);
+ ASSERT_EQ(1u, vec.size());
+}
+
+TEST(TestRtsan, DestructionOfObjectOnHeapDiesWhenRealtime) {
+ auto allocated_ptr = std::make_unique<std::array<float, 256>>();
+ auto Func = [&allocated_ptr]() { allocated_ptr.reset(); };
+ ExpectRealtimeDeath(Func);
+ ASSERT_NE(nullptr, allocated_ptr.get());
+ ExpectNonRealtimeSurvival(Func);
+ ASSERT_EQ(nullptr, allocated_ptr.get());
+}
+
+TEST(TestRtsan, SleepingAThreadDiesWhenRealtime) {
+ auto Func = []() { std::this_thread::sleep_for(1us); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, IfstreamCreationDiesWhenRealtime) {
+ auto Func = []() { std::ifstream ifs{"./file.txt"}; };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+ std::remove("./file.txt");
+}
+
+TEST(TestRtsan, OfstreamCreationDiesWhenRealtime) {
+ auto Func = []() { std::ofstream ofs{"./file.txt"}; };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+ std::remove("./file.txt");
+}
+
+TEST(TestRtsan, LockingAMutexDiesWhenRealtime) {
+ std::mutex mutex;
+ auto Func = [&]() { mutex.lock(); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, UnlockingAMutexDiesWhenRealtime) {
+ std::mutex mutex;
+ mutex.lock();
+ auto Func = [&]() { mutex.unlock(); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+#if RTSAN_TEST_SHARED_MUTEX
+
+TEST(TestRtsan, LockingASharedMutexDiesWhenRealtime) {
+ std::shared_mutex mutex;
+ auto Func = [&]() { mutex.lock(); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, UnlockingASharedMutexDiesWhenRealtime) {
+ std::shared_mutex mutex;
+ mutex.lock();
+ auto Func = [&]() { mutex.unlock(); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, SharedLockingASharedMutexDiesWhenRealtime) {
+ std::shared_mutex mutex;
+ auto Func = [&]() { mutex.lock_shared(); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, SharedUnlockingASharedMutexDiesWhenRealtime) {
+ std::shared_mutex mutex;
+ mutex.lock_shared();
+ auto Func = [&]() { mutex.unlock_shared(); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+#endif // RTSAN_TEST_SHARED_MUTEX
+
+TEST(TestRtsan, LaunchingAThreadDiesWhenRealtime) {
+ auto Func = [&]() {
+ std::thread Thread{[]() {}};
+ Thread.join();
+ };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+namespace {
+void InvokeStdFunction(std::function<void()> &&function) { function(); }
+} // namespace
+
+TEST(TestRtsan, CopyingALambdaWithLargeCaptureDiesWhenRealtime) {
+ std::array<float, 16> lots_of_data;
+ auto lambda = [lots_of_data]() mutable {
+ // Stop everything getting optimised out
+ lots_of_data[3] = 0.25f;
+ EXPECT_EQ(16, lots_of_data.size());
+ EXPECT_EQ(0.25f, lots_of_data[3]);
+ };
+ auto Func = [&]() { InvokeStdFunction(lambda); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, AccessingALargeAtomicVariableDiesWhenRealtime) {
+ std::atomic<float> small_atomic{0.0f};
+ ASSERT_TRUE(small_atomic.is_lock_free());
+ RealtimeInvoke([&small_atomic]() { float x = small_atomic.load(); });
+
+ std::atomic<std::array<float, 2048>> large_atomic;
+ ASSERT_FALSE(large_atomic.is_lock_free());
+ auto Func = [&]() { auto x = large_atomic.load(); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, FirstCoutDiesWhenRealtime) {
+ auto Func = []() { std::cout << "Hello, world!" << std::endl; };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, SecondCoutDiesWhenRealtime) {
+ std::cout << "Hello, world";
+ auto Func = []() { std::cout << "Hello, again!" << std::endl; };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, PrintfDiesWhenRealtime) {
+ auto Func = []() { printf("Hello, world!\n"); };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, ThrowingAnExceptionDiesWhenRealtime) {
+ auto Func = [&]() {
+ try {
+ throw std::exception();
+ } catch (std::exception &) {
+ }
+ };
+ ExpectRealtimeDeath(Func);
+ ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsan, DoesNotDieIfTurnedOff) {
+ std::mutex mutex;
+ auto RealtimeUnsafeFunc = [&]() {
+ __rtsan_off();
+ mutex.lock();
+ mutex.unlock();
+ __rtsan_on();
+ };
+ RealtimeInvoke(RealtimeUnsafeFunc);
+}