xref: /aosp_15_r20/external/libcxx/test/support/assert_checkpoint.h (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1*58b9f456SAndroid Build Coastguard Worker #ifndef SUPPORT_ASSERT_CHECKPOINT_H
2*58b9f456SAndroid Build Coastguard Worker #define SUPPORT_ASSERT_CHECKPOINT_H
3*58b9f456SAndroid Build Coastguard Worker 
4*58b9f456SAndroid Build Coastguard Worker #include <csignal>
5*58b9f456SAndroid Build Coastguard Worker #include <iostream>
6*58b9f456SAndroid Build Coastguard Worker #include <cstdlib>
7*58b9f456SAndroid Build Coastguard Worker 
8*58b9f456SAndroid Build Coastguard Worker struct Checkpoint {
9*58b9f456SAndroid Build Coastguard Worker   const char* file;
10*58b9f456SAndroid Build Coastguard Worker   const char* func;
11*58b9f456SAndroid Build Coastguard Worker   int line;
12*58b9f456SAndroid Build Coastguard Worker   const char* msg;
13*58b9f456SAndroid Build Coastguard Worker 
CheckpointCheckpoint14*58b9f456SAndroid Build Coastguard Worker   Checkpoint() : file(nullptr), func(nullptr), line(-1), msg(nullptr) {}
CheckpointCheckpoint15*58b9f456SAndroid Build Coastguard Worker   Checkpoint(const char* xfile, const char* xfunc, int xline, const char* xmsg)
16*58b9f456SAndroid Build Coastguard Worker       : file(xfile), func(xfunc), line(xline), msg(xmsg)
17*58b9f456SAndroid Build Coastguard Worker   {}
18*58b9f456SAndroid Build Coastguard Worker 
19*58b9f456SAndroid Build Coastguard Worker   template <class Stream>
printCheckpoint20*58b9f456SAndroid Build Coastguard Worker   void print(Stream& s) const {
21*58b9f456SAndroid Build Coastguard Worker       if (!file) {
22*58b9f456SAndroid Build Coastguard Worker           s << "NO CHECKPOINT\n";
23*58b9f456SAndroid Build Coastguard Worker           return;
24*58b9f456SAndroid Build Coastguard Worker       }
25*58b9f456SAndroid Build Coastguard Worker       s << file << ":" << line << " " << func << ": Checkpoint";
26*58b9f456SAndroid Build Coastguard Worker       if (msg)
27*58b9f456SAndroid Build Coastguard Worker         s << " '" << msg << "'";
28*58b9f456SAndroid Build Coastguard Worker       s << std::endl;
29*58b9f456SAndroid Build Coastguard Worker   }
30*58b9f456SAndroid Build Coastguard Worker };
31*58b9f456SAndroid Build Coastguard Worker 
globalCheckpoint()32*58b9f456SAndroid Build Coastguard Worker inline Checkpoint& globalCheckpoint() {
33*58b9f456SAndroid Build Coastguard Worker     static Checkpoint C;
34*58b9f456SAndroid Build Coastguard Worker     return C;
35*58b9f456SAndroid Build Coastguard Worker }
36*58b9f456SAndroid Build Coastguard Worker 
clearCheckpoint()37*58b9f456SAndroid Build Coastguard Worker inline void clearCheckpoint() {
38*58b9f456SAndroid Build Coastguard Worker     globalCheckpoint() = Checkpoint();
39*58b9f456SAndroid Build Coastguard Worker }
40*58b9f456SAndroid Build Coastguard Worker 
41*58b9f456SAndroid Build Coastguard Worker #if defined(__GNUC__)
42*58b9f456SAndroid Build Coastguard Worker #define CHECKPOINT_FUNCTION_NAME __PRETTY_FUNCTION__
43*58b9f456SAndroid Build Coastguard Worker #else
44*58b9f456SAndroid Build Coastguard Worker #define CHECKPOINT_FUNCTION_NAME __func__
45*58b9f456SAndroid Build Coastguard Worker #endif
46*58b9f456SAndroid Build Coastguard Worker 
47*58b9f456SAndroid Build Coastguard Worker #define CHECKPOINT(msg) globalCheckpoint() = Checkpoint(__FILE__, CHECKPOINT_FUNCTION_NAME, __LINE__, msg);
48*58b9f456SAndroid Build Coastguard Worker 
checkpointSignalHandler(int signal)49*58b9f456SAndroid Build Coastguard Worker inline void checkpointSignalHandler(int signal) {
50*58b9f456SAndroid Build Coastguard Worker     if (signal == SIGABRT) {
51*58b9f456SAndroid Build Coastguard Worker         globalCheckpoint().print(std::cerr);
52*58b9f456SAndroid Build Coastguard Worker     } else {
53*58b9f456SAndroid Build Coastguard Worker         std::cerr << "Unexpected signal " << signal << " received\n";
54*58b9f456SAndroid Build Coastguard Worker     }
55*58b9f456SAndroid Build Coastguard Worker     std::_Exit(EXIT_FAILURE);
56*58b9f456SAndroid Build Coastguard Worker }
57*58b9f456SAndroid Build Coastguard Worker 
initCheckpointHandler()58*58b9f456SAndroid Build Coastguard Worker inline bool initCheckpointHandler() {
59*58b9f456SAndroid Build Coastguard Worker     typedef void(*HandlerT)(int);
60*58b9f456SAndroid Build Coastguard Worker     static bool isInit = false;
61*58b9f456SAndroid Build Coastguard Worker     if (isInit) return true;
62*58b9f456SAndroid Build Coastguard Worker     HandlerT prev_h = std::signal(SIGABRT, checkpointSignalHandler);
63*58b9f456SAndroid Build Coastguard Worker     if (prev_h == SIG_ERR) {
64*58b9f456SAndroid Build Coastguard Worker         std::cerr << "Setup failed.\n";
65*58b9f456SAndroid Build Coastguard Worker         std::_Exit(EXIT_FAILURE);
66*58b9f456SAndroid Build Coastguard Worker     }
67*58b9f456SAndroid Build Coastguard Worker     isInit = true;
68*58b9f456SAndroid Build Coastguard Worker     return false;
69*58b9f456SAndroid Build Coastguard Worker }
70*58b9f456SAndroid Build Coastguard Worker 
71*58b9f456SAndroid Build Coastguard Worker static bool initDummy = initCheckpointHandler();
72*58b9f456SAndroid Build Coastguard Worker 
73*58b9f456SAndroid Build Coastguard Worker #endif
74