a1a7c99e256634fc6e7701c7059106f27b679149
[folly.git] / folly / experimental / symbolizer / test / StackTraceTest.cpp
1 /*
2  * Copyright 2017 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 <folly/experimental/symbolizer/StackTrace.h>
18 #include <folly/experimental/symbolizer/Symbolizer.h>
19
20 #include <glog/logging.h>
21
22 #include <folly/portability/GTest.h>
23
24 using namespace folly;
25 using namespace folly::symbolizer;
26
27 FOLLY_NOINLINE void foo1();
28 FOLLY_NOINLINE void foo2();
29
30 void verifyStackTraces() {
31   constexpr size_t kMaxAddresses = 100;
32   FrameArray<kMaxAddresses> fa;
33   CHECK(getStackTrace(fa));
34
35   FrameArray<kMaxAddresses> faSafe;
36   CHECK(getStackTraceSafe(faSafe));
37
38   CHECK_EQ(fa.frameCount, faSafe.frameCount);
39
40   if (VLOG_IS_ON(1)) {
41     Symbolizer symbolizer;
42     OStreamSymbolizePrinter printer(std::cerr, SymbolizePrinter::COLOR_IF_TTY);
43
44     symbolizer.symbolize(fa);
45     VLOG(1) << "getStackTrace\n";
46     printer.println(fa);
47
48     symbolizer.symbolize(faSafe);
49     VLOG(1) << "getStackTraceSafe\n";
50     printer.println(faSafe);
51   }
52
53   // Other than the top 2 frames (this one and getStackTrace /
54   // getStackTraceSafe), the stack traces should be identical
55   for (size_t i = 2; i < fa.frameCount; ++i) {
56     LOG(INFO) << "i=" << i << " " << std::hex << "0x" << fa.addresses[i]
57               << " 0x" << faSafe.addresses[i];
58     EXPECT_EQ(fa.addresses[i], faSafe.addresses[i]);
59   }
60 }
61
62 void foo1() {
63   foo2();
64 }
65
66 void foo2() {
67   verifyStackTraces();
68 }
69
70 volatile bool handled = false;
71 void handler(int /* num */, siginfo_t* /* info */, void* /* ctx */) {
72   // Yes, getStackTrace and VLOG aren't async-signal-safe, but signals
73   // raised with raise() aren't "async" signals.
74   foo1();
75   handled = true;
76 }
77
78 TEST(StackTraceTest, Simple) {
79   foo1();
80 }
81
82 TEST(StackTraceTest, Signal) {
83   struct sigaction sa;
84   memset(&sa, 0, sizeof(sa));
85   sa.sa_sigaction = handler;
86   sa.sa_flags = SA_RESETHAND | SA_SIGINFO;
87   CHECK_ERR(sigaction(SIGUSR1, &sa, nullptr));
88   raise(SIGUSR1);
89   EXPECT_TRUE(handled);
90 }
91
92 int main(int argc, char *argv[]) {
93   testing::InitGoogleTest(&argc, argv);
94   gflags::ParseCommandLineFlags(&argc, &argv, true);
95   google::InitGoogleLogging(argv[0]);
96   return RUN_ALL_TESTS();
97 }