proxygen
ExceptionCounterTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
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 #include <condition_variable>
18 #include <mutex>
19 #include <sstream>
20 #include <stdexcept>
21 #include <thread>
22 
25 
26 struct MyException {};
27 
28 // clang-format off
29 [[noreturn]] void bar() {
30  throw std::runtime_error("hello");
31 }
32 
33 [[noreturn]] void foo() {
34  throw MyException();
35 }
36 
37 [[noreturn]] void baz() {
38  foo();
39 }
40 // clang-format on
41 
42 using namespace folly::exception_tracer;
43 
44 template <typename F>
45 void throwAndCatch(F f) {
46  try {
47  f();
48  } catch (...) {
49  // ignore
50  }
51 }
52 
53 TEST(ExceptionCounter, oneThread) {
55 
56  // Use volatile to prevent loop unrolling (it screws up stack frame grouping).
57  for (volatile int i = 0; i < 10; ++i) {
59  }
60 
61  auto stats = getExceptionStatistics();
62  EXPECT_EQ(stats.size(), 2);
63  EXPECT_EQ(stats[0].count, 10);
64  EXPECT_EQ(stats[1].count, 1);
65  EXPECT_EQ(*(stats[0].info.type), typeid(std::runtime_error));
66  EXPECT_EQ(*(stats[1].info.type), typeid(MyException));
67 }
68 
69 TEST(ExceptionCounter, testClearExceptionStatistics) {
71  auto stats = getExceptionStatistics();
72  EXPECT_EQ(stats.size(), 1);
73  stats = getExceptionStatistics();
74  EXPECT_EQ(stats.size(), 0);
75 }
76 
77 TEST(ExceptionCounter, testDifferentStacks) {
80  auto stats = getExceptionStatistics();
81  EXPECT_EQ(stats.size(), 2);
82 }
83 
84 TEST(ExceptionCounter, multyThreads) {
85  constexpr size_t kNumIterations = 10000;
86  constexpr size_t kNumThreads = 10;
87  std::vector<std::thread> threads;
88  threads.resize(kNumThreads);
89 
90  std::mutex preparedMutex;
91  std::mutex finishedMutex;
92  std::condition_variable preparedBarrier;
93  std::condition_variable finishedBarrier;
94  int preparedThreads = 0;
95  bool finished = false;
96 
97  for (auto& t : threads) {
98  t = std::thread([&]() {
99  for (size_t i = 0; i < kNumIterations; ++i) {
101  }
102 
103  {
104  std::unique_lock<std::mutex> lock(preparedMutex);
105  ++preparedThreads;
106  preparedBarrier.notify_one();
107  }
108 
109  std::unique_lock<std::mutex> lock(finishedMutex);
110  finishedBarrier.wait(lock, [&]() { return finished; });
111  });
112  }
113 
114  {
115  std::unique_lock<std::mutex> lock(preparedMutex);
116  preparedBarrier.wait(
117  lock, [&]() { return preparedThreads == kNumThreads; });
118  }
119 
120  auto stats = getExceptionStatistics();
121  EXPECT_EQ(stats.size(), 1);
122  EXPECT_EQ(stats[0].count, kNumIterations * kNumThreads);
123 
124  {
125  std::unique_lock<std::mutex> lock(finishedMutex);
126  finished = true;
127  finishedBarrier.notify_all();
128  }
129 
130  for (auto& t : threads) {
131  t.join();
132  }
133 }
def info()
Definition: deadlock.py:447
auto f
void baz()
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static size_t const kNumThreads
TEST(ExceptionCounter, oneThread)
std::vector< std::thread::id > threads
auto lock(SynchronizedLocker...lockersIn) -> std::tuple< typename SynchronizedLocker::LockedPtr... >
Definition: Synchronized.h:871
MyException(char const *const what)
int * count
std::vector< ExceptionStats > getExceptionStatistics()
std::mutex mutex
void bar()
void foo()
void throwAndCatch(F f)