blob: d2466c931b30bc2a0c3121a70db6c22a1dc16edc [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
Austin Schuhad9e5eb2021-11-19 20:33:55 -080026 std::string_view MyName() override { return "Name"; }
27
Brian Silvermanb3616972013-03-05 19:58:10 -080028 // This class has to be a singleton so that everybody can get access to the
29 // same instance to read out the messages etc.
Austin Schuha0c41ba2020-09-10 22:59:14 -070030 static std::shared_ptr<TestLogImplementation> GetInstance() {
31 static std::shared_ptr<TestLogImplementation> instance =
32 std::make_unique<TestLogImplementation>();
John Parkb5e47302020-01-08 19:58:18 -080033 return instance;
Brian Silvermanb3616972013-03-05 19:58:10 -080034 }
35
36 // Clears out all of the messages already recorded.
37 void ClearMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070038 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080039 messages_.clear();
40 }
41
42 // Prints out all of the messages (like when a test fails).
43 void PrintAllMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070044 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080045 for (auto it = messages_.begin(); it != messages_.end(); ++it) {
46 logging::internal::PrintMessage(stdout, *it);
47 }
48 }
49
Philipp Schradere41ed9d2015-03-15 22:57:13 +000050 void SetOutputFile(const char *filename) {
51 if (strcmp("-", filename) != 0) {
52 FILE *newfile = fopen(filename, "w");
53
54 if (newfile) {
55 output_file_ = newfile;
56 }
57 }
58 }
59
60 void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
61
Austin Schuha0c41ba2020-09-10 22:59:14 -070062 // Don't call these from outside this class.
Philipp Schradere41ed9d2015-03-15 22:57:13 +000063 ~TestLogImplementation() {
64 if (output_file_ != stdout) {
65 fclose(output_file_);
66 }
67 }
Brian Silvermanb3616972013-03-05 19:58:10 -080068
Austin Schuha0c41ba2020-09-10 22:59:14 -070069 private:
Brian Silvermanbe858a12014-04-30 17:37:28 -070070 virtual void HandleMessage(const LogMessage &message) override {
Brian Silverman1463c092020-10-30 17:28:24 -070071 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Philipp Schradere41ed9d2015-03-15 22:57:13 +000072 if (message.level == FATAL || print_as_messages_come_in_) {
73 logging::internal::PrintMessage(output_file_, message);
Brian Silvermanb3616972013-03-05 19:58:10 -080074 }
75
76 messages_.push_back(message);
77 }
78
79 ::std::vector<LogMessage> messages_;
Philipp Schradere41ed9d2015-03-15 22:57:13 +000080 bool print_as_messages_come_in_ = false;
81 FILE *output_file_ = stdout;
Brian Silverman1463c092020-10-30 17:28:24 -070082 aos::stl_mutex messages_mutex_;
Brian Silvermanb3616972013-03-05 19:58:10 -080083};
84
85class MyTestEventListener : public ::testing::EmptyTestEventListener {
Austin Schuh82c0c822019-05-27 19:55:20 -070086 virtual void OnTestStart(const ::testing::TestInfo & /*test_info*/) {
Brian Silvermanb3616972013-03-05 19:58:10 -080087 TestLogImplementation::GetInstance()->ClearMessages();
88 }
89 virtual void OnTestEnd(const ::testing::TestInfo &test_info) {
90 if (test_info.result()->Failed()) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +000091 printf("Test %s failed. Use '--print-logs' to see all log messages.\n",
Brian Silvermanb3616972013-03-05 19:58:10 -080092 test_info.name());
Brian Silvermanb3616972013-03-05 19:58:10 -080093 }
94 }
Brian Silvermanb91a37d2013-03-09 17:54:30 -080095
Austin Schuha0c41ba2020-09-10 22:59:14 -070096 virtual void OnTestPartResult(const ::testing::TestPartResult &result) {
Brian Silvermanb91a37d2013-03-09 17:54:30 -080097 if (result.failed()) {
98 const char *failure_type = "unknown";
99 switch (result.type()) {
100 case ::testing::TestPartResult::Type::kNonFatalFailure:
101 failure_type = "EXPECT";
102 break;
103 case ::testing::TestPartResult::Type::kFatalFailure:
104 failure_type = "ASSERT";
105 break;
106 case ::testing::TestPartResult::Type::kSuccess:
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700107 case ::testing::TestPartResult::Type::kSkip:
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800108 break;
109 }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700110 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n", result.file_name(),
111 result.line_number(), failure_type, result.message());
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800112 }
113 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800114};
115
116void *DoEnableTestLogging() {
Tyler Chatow4b471e12020-01-05 20:19:36 -0800117 logging::SetImplementation(TestLogImplementation::GetInstance());
Brian Silvermanb3616972013-03-05 19:58:10 -0800118
119 ::testing::UnitTest::GetInstance()->listeners().Append(
120 new MyTestEventListener());
121
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500122 return nullptr;
Brian Silvermanb3616972013-03-05 19:58:10 -0800123}
124
John Parkb5e47302020-01-08 19:58:18 -0800125static absl::once_flag enable_test_logging_once;
Brian Silvermanb3616972013-03-05 19:58:10 -0800126
127} // namespace
brians343bc112013-02-10 01:53:46 +0000128
Brian Silvermanb3616972013-03-05 19:58:10 -0800129void EnableTestLogging() {
John Parkb5e47302020-01-08 19:58:18 -0800130 absl::call_once(enable_test_logging_once, DoEnableTestLogging);
Brian Silvermanb3616972013-03-05 19:58:10 -0800131}
132
Austin Schuha0c41ba2020-09-10 22:59:14 -0700133void SetLogFileName(const char *filename) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000134 TestLogImplementation::GetInstance()->SetOutputFile(filename);
135}
136
137void ForcePrintLogsDuringTests() {
138 TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
139}
140
brians343bc112013-02-10 01:53:46 +0000141} // namespace testing
brians343bc112013-02-10 01:53:46 +0000142} // namespace aos