File: TestStackTrace.hpp

package info (click to toggle)
kokkos 4.7.01-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 16,636 kB
  • sloc: cpp: 223,676; sh: 2,446; makefile: 2,437; python: 91; fortran: 4; ansic: 2
file content (150 lines) | stat: -rw-r--r-- 4,771 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//@HEADER
// ************************************************************************
//
//                        Kokkos v. 4.0
//       Copyright (2022) National Technology & Engineering
//               Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
// See https://kokkos.org/LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//@HEADER
#include <iostream>
#include <gtest/gtest.h>
#include "Kokkos_Core.hpp"

#include <impl/Kokkos_Stacktrace.hpp>

namespace Test {

void stacktrace_test_f0(std::ostream& out);

int stacktrace_test_f1(std::ostream& out);

void stacktrace_test_f2(std::ostream& out);

int stacktrace_test_f3(std::ostream& out, const int level);

void stacktrace_test_f4();

void my_fancy_handler();

size_t find_first_non_whitespace(const std::string& s, const size_t start_pos) {
  constexpr size_t num_ws_chars = 3;
  const char ws_chars[]         = "\n\t ";
  return s.find_first_not_of(ws_chars, start_pos, num_ws_chars);
}

void test_stacktrace(bool bTerminate, bool bCustom = true) {
  stacktrace_test_f1(std::cout);
  bool bDynamic = false;
  {
    std::stringstream sstream;
    Kokkos::Impl::print_saved_stacktrace(sstream);
    std::string foutput = sstream.str();

    bDynamic = std::string::npos != foutput.find("stacktrace");

    if (bDynamic) {
      printf("test_f1:\n%s \n", foutput.c_str());
      ASSERT_NE(std::string::npos, foutput.find("stacktrace_test_f1"));
      for (auto x : {"stacktrace_test_f0", "stacktrace_test_f2",
                     "stacktrace_test_f3", "stacktrace_test_f4"}) {
        ASSERT_EQ(std::string::npos, foutput.find(x));
      }
    }
  }

  {
    std::stringstream sstream;
    Kokkos::Impl::print_demangled_saved_stacktrace(sstream);

    if (bDynamic) {
      std::string foutput = sstream.str();
      printf("demangled test_f1:\n%s \n", foutput.c_str());
      ASSERT_NE(std::string::npos, foutput.find("Test::stacktrace_test_f1"));
      for (auto x : {"stacktrace_test_f0", "stacktrace_test_f2",
                     "stacktrace_test_f3", "stacktrace_test_f4"}) {
        ASSERT_EQ(std::string::npos, foutput.find(x));
      }
      EXPECT_EQ(0u, find_first_non_whitespace(foutput, 0));
    }
  }

  int val = stacktrace_test_f3(std::cout, 4);

  // Don't remove this, otherwise the compiler will optimize away call sequences
  // via
  printf("StackTrace f3(std::cout, 4) returned: %i\n", val);

  // TODO test by making sure that f3 and f1, but no other functions,
  // appear in the stack trace, and that f3 appears 5 times.
  // Fix that f3 doesn't show up when compiling with -O3
  {
    std::stringstream sstream;
    Kokkos::Impl::print_saved_stacktrace(sstream);

    if (bDynamic) {
      std::string foutput = sstream.str();
      printf("test_f3:\n%s \n", foutput.c_str());
      for (auto x : {"stacktrace_test_f1", "stacktrace_test_f3"}) {
        ASSERT_NE(std::string::npos, foutput.find(x));
      }
    }
    // TODO make sure stacktrace_test_f2/4 don't show up
    // TODO make sure stacktrace_test_f3 shows up 5 times
  }

  {
    std::stringstream sstream;
    Kokkos::Impl::print_demangled_saved_stacktrace(sstream);

    if (bDynamic) {
      std::string foutput = sstream.str();
      printf("demangled test_f3:\n%s \n", foutput.c_str());
      for (auto x : {"stacktrace_test_f1", "stacktrace_test_f3"}) {
        ASSERT_NE(std::string::npos, foutput.find(x));
      }
      EXPECT_EQ(0u, find_first_non_whitespace(foutput, 0));
    }

    // TODO make sure stacktrace_test_f2/4 don't show up
    // TODO make sure stacktrace_test_f3 shows up 5 times
  }
  std::cout << "Test setting std::terminate handler that prints "
               "the last saved stack trace"
            << std::endl;

  stacktrace_test_f4();

  if (bCustom) {
    Kokkos::Impl::set_kokkos_terminate_handler(my_fancy_handler);
  } else {
    Kokkos::Impl::set_kokkos_terminate_handler();
  }

  // TODO test that this prints "Oh noes!" and the correct stacktrace.
  if (bTerminate) {
    std::terminate();
  }
}

TEST(defaultdevicetype, stacktrace_normal) { test_stacktrace(false); }

TEST(defaultdevicetype_DeathTest, stacktrace_terminate) {
  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  ASSERT_DEATH({ test_stacktrace(true); },
               "I am the custom std::terminate handler.");
}

TEST(defaultdevicetype_DeathTest, stacktrace_generic_term) {
  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  ASSERT_DEATH({ test_stacktrace(true, false); },
               "Kokkos observes that std::terminate has been called");
}

}  // namespace Test