blob: d0cea26f4effc15490802313bda304e653d96c26 [file] [log] [blame]
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05001#include "aos/testing/test_logging.h"
Brian Silvermanf665d692013-02-17 22:11:39 -08002
Tyler Chatowbf0609c2021-07-31 16:13:27 -07003#include <cstdio>
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05004#include <vector>
Brian Silvermanf665d692013-02-17 22:11:39 -08005
Austin Schuha0c41ba2020-09-10 22:59:14 -07006#include "absl/base/call_once.h"
John Park33858a32018-09-28 23:05:48 -07007#include "aos/logging/implementations.h"
Brian Silverman1463c092020-10-30 17:28:24 -07008#include "aos/stl_mutex/stl_mutex.h"
Brian Silvermanb47f5552020-10-01 15:08:14 -07009#include "aos/thread_local.h"
Tyler Chatowbf0609c2021-07-31 16:13:27 -070010#include "gtest/gtest.h"
Brian Silvermanb3616972013-03-05 19:58:10 -080011
12using ::aos::logging::LogMessage;
brians343bc112013-02-10 01:53:46 +000013
14namespace aos {
brians343bc112013-02-10 01:53:46 +000015namespace testing {
Brian Silvermanb3616972013-03-05 19:58:10 -080016namespace {
17
Brian Silvermanbe858a12014-04-30 17:37:28 -070018class TestLogImplementation : public logging::HandleMessageLogImplementation {
Brian Silvermanb3616972013-03-05 19:58:10 -080019 public:
20 const ::std::vector<LogMessage> &messages() { return messages_; }
21
Austin Schuh82c0c822019-05-27 19:55:20 -070022 ::aos::monotonic_clock::time_point monotonic_now() const override {
Austin Schuh82c0c822019-05-27 19:55:20 -070023 return ::aos::monotonic_clock::now();
24 }
25
Brian Silvermanb3616972013-03-05 19:58:10 -080026 // This class has to be a singleton so that everybody can get access to the
27 // same instance to read out the messages etc.
Austin Schuha0c41ba2020-09-10 22:59:14 -070028 static std::shared_ptr<TestLogImplementation> GetInstance() {
29 static std::shared_ptr<TestLogImplementation> instance =
30 std::make_unique<TestLogImplementation>();
John Parkb5e47302020-01-08 19:58:18 -080031 return instance;
Brian Silvermanb3616972013-03-05 19:58:10 -080032 }
33
34 // Clears out all of the messages already recorded.
35 void ClearMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070036 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080037 messages_.clear();
38 }
39
40 // Prints out all of the messages (like when a test fails).
41 void PrintAllMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070042 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080043 for (auto it = messages_.begin(); it != messages_.end(); ++it) {
44 logging::internal::PrintMessage(stdout, *it);
45 }
46 }
47
Philipp Schradere41ed9d2015-03-15 22:57:13 +000048 void SetOutputFile(const char *filename) {
49 if (strcmp("-", filename) != 0) {
50 FILE *newfile = fopen(filename, "w");
51
52 if (newfile) {
53 output_file_ = newfile;
54 }
55 }
56 }
57
58 void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
59
Austin Schuha0c41ba2020-09-10 22:59:14 -070060 // Don't call these from outside this class.
Philipp Schradere41ed9d2015-03-15 22:57:13 +000061 ~TestLogImplementation() {
62 if (output_file_ != stdout) {
63 fclose(output_file_);
64 }
65 }
Brian Silvermanb3616972013-03-05 19:58:10 -080066
Austin Schuha0c41ba2020-09-10 22:59:14 -070067 private:
Brian Silvermanbe858a12014-04-30 17:37:28 -070068 virtual void HandleMessage(const LogMessage &message) override {
Brian Silverman1463c092020-10-30 17:28:24 -070069 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Philipp Schradere41ed9d2015-03-15 22:57:13 +000070 if (message.level == FATAL || print_as_messages_come_in_) {
71 logging::internal::PrintMessage(output_file_, message);
Brian Silvermanb3616972013-03-05 19:58:10 -080072 }
73
74 messages_.push_back(message);
75 }
76
77 ::std::vector<LogMessage> messages_;
Philipp Schradere41ed9d2015-03-15 22:57:13 +000078 bool print_as_messages_come_in_ = false;
79 FILE *output_file_ = stdout;
Brian Silverman1463c092020-10-30 17:28:24 -070080 aos::stl_mutex messages_mutex_;
Brian Silvermanb3616972013-03-05 19:58:10 -080081};
82
83class MyTestEventListener : public ::testing::EmptyTestEventListener {
Austin Schuh82c0c822019-05-27 19:55:20 -070084 virtual void OnTestStart(const ::testing::TestInfo & /*test_info*/) {
Brian Silvermanb3616972013-03-05 19:58:10 -080085 TestLogImplementation::GetInstance()->ClearMessages();
86 }
87 virtual void OnTestEnd(const ::testing::TestInfo &test_info) {
88 if (test_info.result()->Failed()) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +000089 printf("Test %s failed. Use '--print-logs' to see all log messages.\n",
Brian Silvermanb3616972013-03-05 19:58:10 -080090 test_info.name());
Brian Silvermanb3616972013-03-05 19:58:10 -080091 }
92 }
Brian Silvermanb91a37d2013-03-09 17:54:30 -080093
Austin Schuha0c41ba2020-09-10 22:59:14 -070094 virtual void OnTestPartResult(const ::testing::TestPartResult &result) {
Brian Silvermanb91a37d2013-03-09 17:54:30 -080095 if (result.failed()) {
96 const char *failure_type = "unknown";
97 switch (result.type()) {
98 case ::testing::TestPartResult::Type::kNonFatalFailure:
99 failure_type = "EXPECT";
100 break;
101 case ::testing::TestPartResult::Type::kFatalFailure:
102 failure_type = "ASSERT";
103 break;
104 case ::testing::TestPartResult::Type::kSuccess:
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700105 case ::testing::TestPartResult::Type::kSkip:
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800106 break;
107 }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700108 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n", result.file_name(),
109 result.line_number(), failure_type, result.message());
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800110 }
111 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800112};
113
114void *DoEnableTestLogging() {
Tyler Chatow4b471e12020-01-05 20:19:36 -0800115 logging::SetImplementation(TestLogImplementation::GetInstance());
Brian Silvermanb3616972013-03-05 19:58:10 -0800116
117 ::testing::UnitTest::GetInstance()->listeners().Append(
118 new MyTestEventListener());
119
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500120 return nullptr;
Brian Silvermanb3616972013-03-05 19:58:10 -0800121}
122
John Parkb5e47302020-01-08 19:58:18 -0800123static absl::once_flag enable_test_logging_once;
Brian Silvermanb3616972013-03-05 19:58:10 -0800124
125} // namespace
brians343bc112013-02-10 01:53:46 +0000126
Brian Silvermanb3616972013-03-05 19:58:10 -0800127void EnableTestLogging() {
John Parkb5e47302020-01-08 19:58:18 -0800128 absl::call_once(enable_test_logging_once, DoEnableTestLogging);
Brian Silvermanb3616972013-03-05 19:58:10 -0800129}
130
Austin Schuha0c41ba2020-09-10 22:59:14 -0700131void SetLogFileName(const char *filename) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000132 TestLogImplementation::GetInstance()->SetOutputFile(filename);
133}
134
135void ForcePrintLogsDuringTests() {
136 TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
137}
138
brians343bc112013-02-10 01:53:46 +0000139} // namespace testing
brians343bc112013-02-10 01:53:46 +0000140} // namespace aos