2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <condition_variable>
23 #include <folly/experimental/exception_tracer/ExceptionCounterLib.h>
24 #include <folly/portability/GTest.h>
26 struct MyException {};
28 [[noreturn]] void bar() {
29 throw std::runtime_error("hello");
32 [[noreturn]] void foo() {
36 [[noreturn]] void baz() {
40 using namespace folly::exception_tracer;
43 void throwAndCatch(F f) {
51 TEST(ExceptionCounter, oneThread) {
54 // Use volatile to prevent loop unrolling (it screws up stack frame grouping).
55 for (volatile int i = 0; i < 10; ++i) {
59 auto stats = getExceptionStatistics();
60 EXPECT_EQ(stats.size(), 2);
61 EXPECT_EQ(stats[0].count, 10);
62 EXPECT_EQ(stats[1].count, 1);
63 EXPECT_EQ(*(stats[0].info.type), typeid(std::runtime_error));
64 EXPECT_EQ(*(stats[1].info.type), typeid(MyException));
67 TEST(ExceptionCounter, testClearExceptionStatistics) {
69 auto stats = getExceptionStatistics();
70 EXPECT_EQ(stats.size(), 1);
71 stats = getExceptionStatistics();
72 EXPECT_EQ(stats.size(), 0);
75 TEST(ExceptionCounter, testDifferentStacks) {
78 auto stats = getExceptionStatistics();
79 EXPECT_EQ(stats.size(), 2);
82 TEST(ExceptionCounter, multyThreads) {
83 constexpr size_t kNumIterations = 10000;
84 constexpr size_t kNumThreads = 10;
85 std::vector<std::thread> threads;
86 threads.resize(kNumThreads);
88 std::mutex preparedMutex;
89 std::mutex finishedMutex;
90 std::condition_variable preparedBarrier;
91 std::condition_variable finishedBarrier;
92 int preparedThreads = 0;
93 bool finished = false;
95 for (auto& t : threads) {
96 t = std::thread([&]() {
97 for (size_t i = 0; i < kNumIterations; ++i) {
102 std::unique_lock<std::mutex> lock(preparedMutex);
104 preparedBarrier.notify_one();
107 std::unique_lock<std::mutex> lock(finishedMutex);
108 finishedBarrier.wait(lock, [&]() { return finished; });
113 std::unique_lock<std::mutex> lock(preparedMutex);
114 preparedBarrier.wait(lock,
115 [&]() { return preparedThreads == kNumThreads; });
118 auto stats = getExceptionStatistics();
119 EXPECT_EQ(stats.size(), 1);
120 EXPECT_EQ(stats[0].count, kNumIterations * kNumThreads);
123 std::unique_lock<std::mutex> lock(finishedMutex);
125 finishedBarrier.notify_all();
128 for (auto& t : threads) {