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