debug_mode_helper.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef TEST_SUPPORT_DEBUG_MODE_HELPER_H
  9. #define TEST_SUPPORT_DEBUG_MODE_HELPER_H
  10. #ifndef _LIBCPP_DEBUG
  11. #error _LIBCPP_DEBUG must be defined before including this header
  12. #endif
  13. #include <ciso646>
  14. #ifndef _LIBCPP_VERSION
  15. #error "This header may only be used for libc++ tests"
  16. #endif
  17. #include <__debug>
  18. #include <utility>
  19. #include <cstddef>
  20. #include <cstdlib>
  21. #include <cassert>
  22. #include <string_view>
  23. #include <sstream>
  24. #include <iostream>
  25. #include <unistd.h>
  26. #include <sys/wait.h>
  27. #include "test_macros.h"
  28. #include "assert_checkpoint.h"
  29. #include "test_allocator.h"
  30. #if TEST_STD_VER < 11
  31. # error "C++11 or greater is required to use this header"
  32. #endif
  33. struct DebugInfoMatcher {
  34. static const int any_line = -1;
  35. static constexpr const char* any_file = "*";
  36. static constexpr const char* any_msg = "*";
  37. constexpr DebugInfoMatcher() : is_empty(true), msg(any_msg, __builtin_strlen(any_msg)), file(any_file, __builtin_strlen(any_file)), line(any_line) { }
  38. constexpr DebugInfoMatcher(const char* msg, const char* file = any_file, int line = any_line)
  39. : is_empty(false), msg(msg, __builtin_strlen(msg)), file(file, __builtin_strlen(file)), line(line) {}
  40. bool Matches(std::__libcpp_debug_info const& got) const {
  41. assert(!empty() && "empty matcher");
  42. if (CheckLineMatches(got.__line_) && CheckFileMatches(got.__file_) &&
  43. CheckMessageMatches(got.__msg_))
  44. return true;
  45. // Write to stdout because that's the file descriptor captured by the parent
  46. // process.
  47. std::cout << "Failed to match debug info!\n"
  48. << ToString() << "\n"
  49. << "VS\n"
  50. << got.what() << "\n";
  51. return false;
  52. }
  53. std::string ToString() const {
  54. std::stringstream ss;
  55. ss << "msg = \"" << msg << "\"\n"
  56. << "line = " << (line == any_line ? "'*'" : std::to_string(line)) << "\n"
  57. << "file = " << (file == any_file ? "'*'" : any_file) << "";
  58. return ss.str();
  59. }
  60. bool empty() const { return is_empty; }
  61. private:
  62. bool CheckLineMatches(int got_line) const {
  63. if (line == any_line)
  64. return true;
  65. return got_line == line;
  66. }
  67. bool CheckFileMatches(std::string_view got_file) const {
  68. assert(!empty() && "empty matcher");
  69. if (file == any_file)
  70. return true;
  71. std::size_t found_at = got_file.find(file);
  72. if (found_at == std::string_view::npos)
  73. return false;
  74. // require the match start at the beginning of the file or immediately after
  75. // a directory separator.
  76. if (found_at != 0) {
  77. char last_char = got_file[found_at - 1];
  78. if (last_char != '/' && last_char != '\\')
  79. return false;
  80. }
  81. // require the match goes until the end of the string.
  82. return got_file.substr(found_at) == file;
  83. }
  84. bool CheckMessageMatches(std::string_view got_msg) const {
  85. assert(!empty() && "empty matcher");
  86. if (msg == any_msg)
  87. return true;
  88. std::size_t found_at = got_msg.find(msg);
  89. if (found_at == std::string_view::npos)
  90. return false;
  91. // Allow any match
  92. return true;
  93. }
  94. private:
  95. bool is_empty;
  96. std::string_view msg;
  97. std::string_view file;
  98. int line;
  99. };
  100. static constexpr DebugInfoMatcher AnyMatcher(DebugInfoMatcher::any_msg);
  101. inline DebugInfoMatcher& GlobalMatcher() {
  102. static DebugInfoMatcher GMatch;
  103. return GMatch;
  104. }
  105. struct DeathTest {
  106. enum ResultKind {
  107. RK_DidNotDie, RK_MatchFound, RK_MatchFailure, RK_SetupFailure, RK_Unknown
  108. };
  109. static const char* ResultKindToString(ResultKind RK) {
  110. #define CASE(K) case K: return #K
  111. switch (RK) {
  112. CASE(RK_MatchFailure);
  113. CASE(RK_DidNotDie);
  114. CASE(RK_SetupFailure);
  115. CASE(RK_MatchFound);
  116. CASE(RK_Unknown);
  117. }
  118. return "not a result kind";
  119. }
  120. static bool IsValidResultKind(int val) {
  121. return val >= RK_DidNotDie && val <= RK_Unknown;
  122. }
  123. TEST_NORETURN static void DeathTestDebugHandler(std::__libcpp_debug_info const& info) {
  124. assert(!GlobalMatcher().empty());
  125. if (GlobalMatcher().Matches(info)) {
  126. std::exit(RK_MatchFound);
  127. }
  128. std::exit(RK_MatchFailure);
  129. }
  130. DeathTest(DebugInfoMatcher const& Matcher) : matcher_(Matcher) {}
  131. template <class Func>
  132. ResultKind Run(Func&& f) {
  133. int pipe_res = pipe(stdout_pipe_fd_);
  134. assert(pipe_res != -1 && "failed to create pipe");
  135. pipe_res = pipe(stderr_pipe_fd_);
  136. assert(pipe_res != -1 && "failed to create pipe");
  137. pid_t child_pid = fork();
  138. assert(child_pid != -1 &&
  139. "failed to fork a process to perform a death test");
  140. child_pid_ = child_pid;
  141. if (child_pid_ == 0) {
  142. RunForChild(std::forward<Func>(f));
  143. assert(false && "unreachable");
  144. }
  145. return RunForParent();
  146. }
  147. int getChildExitCode() const { return exit_code_; }
  148. std::string const& getChildStdOut() const { return stdout_from_child_; }
  149. std::string const& getChildStdErr() const { return stderr_from_child_; }
  150. private:
  151. template <class Func>
  152. TEST_NORETURN void RunForChild(Func&& f) {
  153. close(GetStdOutReadFD()); // don't need to read from the pipe in the child.
  154. close(GetStdErrReadFD());
  155. auto DupFD = [](int DestFD, int TargetFD) {
  156. int dup_result = dup2(DestFD, TargetFD);
  157. if (dup_result == -1)
  158. std::exit(RK_SetupFailure);
  159. };
  160. DupFD(GetStdOutWriteFD(), STDOUT_FILENO);
  161. DupFD(GetStdErrWriteFD(), STDERR_FILENO);
  162. GlobalMatcher() = matcher_;
  163. std::__libcpp_set_debug_function(&DeathTestDebugHandler);
  164. f();
  165. std::exit(RK_DidNotDie);
  166. }
  167. static std::string ReadChildIOUntilEnd(int FD) {
  168. std::string error_msg;
  169. char buffer[256];
  170. int num_read;
  171. do {
  172. while ((num_read = read(FD, buffer, 255)) > 0) {
  173. buffer[num_read] = '\0';
  174. error_msg += buffer;
  175. }
  176. } while (num_read == -1 && errno == EINTR);
  177. return error_msg;
  178. }
  179. void CaptureIOFromChild() {
  180. close(GetStdOutWriteFD()); // no need to write from the parent process
  181. close(GetStdErrWriteFD());
  182. stdout_from_child_ = ReadChildIOUntilEnd(GetStdOutReadFD());
  183. stderr_from_child_ = ReadChildIOUntilEnd(GetStdErrReadFD());
  184. close(GetStdOutReadFD());
  185. close(GetStdErrReadFD());
  186. }
  187. ResultKind RunForParent() {
  188. CaptureIOFromChild();
  189. int status_value;
  190. pid_t result = waitpid(child_pid_, &status_value, 0);
  191. assert(result != -1 && "there is no child process to wait for");
  192. if (WIFEXITED(status_value)) {
  193. exit_code_ = WEXITSTATUS(status_value);
  194. if (!IsValidResultKind(exit_code_))
  195. return RK_Unknown;
  196. return static_cast<ResultKind>(exit_code_);
  197. }
  198. return RK_Unknown;
  199. }
  200. DeathTest(DeathTest const&) = delete;
  201. DeathTest& operator=(DeathTest const&) = delete;
  202. int GetStdOutReadFD() const {
  203. return stdout_pipe_fd_[0];
  204. }
  205. int GetStdOutWriteFD() const {
  206. return stdout_pipe_fd_[1];
  207. }
  208. int GetStdErrReadFD() const {
  209. return stderr_pipe_fd_[0];
  210. }
  211. int GetStdErrWriteFD() const {
  212. return stderr_pipe_fd_[1];
  213. }
  214. private:
  215. DebugInfoMatcher matcher_;
  216. pid_t child_pid_ = -1;
  217. int exit_code_ = -1;
  218. int stdout_pipe_fd_[2];
  219. int stderr_pipe_fd_[2];
  220. std::string stdout_from_child_;
  221. std::string stderr_from_child_;
  222. };
  223. template <class Func>
  224. inline bool ExpectDeath(const char* stmt, Func&& func, DebugInfoMatcher Matcher) {
  225. DeathTest DT(Matcher);
  226. DeathTest::ResultKind RK = DT.Run(func);
  227. auto OnFailure = [&](const char* msg) {
  228. std::cerr << "EXPECT_DEATH( " << stmt << " ) failed! (" << msg << ")\n\n";
  229. if (RK != DeathTest::RK_Unknown) {
  230. std::cerr << "child exit code: " << DT.getChildExitCode() << "\n";
  231. }
  232. if (!DT.getChildStdErr().empty()) {
  233. std::cerr << "---------- standard err ----------\n";
  234. std::cerr << DT.getChildStdErr() << "\n";
  235. }
  236. if (!DT.getChildStdOut().empty()) {
  237. std::cerr << "---------- standard out ----------\n";
  238. std::cerr << DT.getChildStdOut() << "\n";
  239. }
  240. return false;
  241. };
  242. switch (RK) {
  243. case DeathTest::RK_MatchFound:
  244. return true;
  245. case DeathTest::RK_SetupFailure:
  246. return OnFailure("child failed to setup test environment");
  247. case DeathTest::RK_Unknown:
  248. return OnFailure("reason unknown");
  249. case DeathTest::RK_DidNotDie:
  250. return OnFailure("child did not die");
  251. case DeathTest::RK_MatchFailure:
  252. return OnFailure("matcher failed");
  253. }
  254. }
  255. template <class Func>
  256. inline bool ExpectDeath(const char* stmt, Func&& func) {
  257. return ExpectDeath(stmt, func, AnyMatcher);
  258. }
  259. /// Assert that the specified expression throws a libc++ debug exception.
  260. #define EXPECT_DEATH(...) assert((ExpectDeath(#__VA_ARGS__, [&]() { __VA_ARGS__; } )))
  261. #define EXPECT_DEATH_MATCHES(Matcher, ...) assert((ExpectDeath(#__VA_ARGS__, [&]() { __VA_ARGS__; }, Matcher)))
  262. #endif // TEST_SUPPORT_DEBUG_MODE_HELPER_H