blob: ad2cc037777bff76a22a8594331d5f281f32d068 [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"
Philipp Schrader790cb542023-07-05 21:06:52 -07007#include "gtest/gtest.h"
8
John Park33858a32018-09-28 23:05:48 -07009#include "aos/logging/implementations.h"
Brian Silverman1463c092020-10-30 17:28:24 -070010#include "aos/stl_mutex/stl_mutex.h"
Brian Silvermanb47f5552020-10-01 15:08:14 -070011#include "aos/thread_local.h"
Brian Silvermanb3616972013-03-05 19:58:10 -080012
13using ::aos::logging::LogMessage;
brians343bc112013-02-10 01:53:46 +000014
15namespace aos {
brians343bc112013-02-10 01:53:46 +000016namespace testing {
Brian Silvermanb3616972013-03-05 19:58:10 -080017namespace {
18
Brian Silvermanbe858a12014-04-30 17:37:28 -070019class TestLogImplementation : public logging::HandleMessageLogImplementation {
Brian Silvermanb3616972013-03-05 19:58:10 -080020 public:
21 const ::std::vector<LogMessage> &messages() { return messages_; }
22
Austin Schuh82c0c822019-05-27 19:55:20 -070023 ::aos::monotonic_clock::time_point monotonic_now() const override {
Austin Schuh82c0c822019-05-27 19:55:20 -070024 return ::aos::monotonic_clock::now();
25 }
26
Austin Schuhad9e5eb2021-11-19 20:33:55 -080027 std::string_view MyName() override { return "Name"; }
28
Brian Silvermanb3616972013-03-05 19:58:10 -080029 // This class has to be a singleton so that everybody can get access to the
30 // same instance to read out the messages etc.
Austin Schuha0c41ba2020-09-10 22:59:14 -070031 static std::shared_ptr<TestLogImplementation> GetInstance() {
32 static std::shared_ptr<TestLogImplementation> instance =
33 std::make_unique<TestLogImplementation>();
John Parkb5e47302020-01-08 19:58:18 -080034 return instance;
Brian Silvermanb3616972013-03-05 19:58:10 -080035 }
36
37 // Clears out all of the messages already recorded.
38 void ClearMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070039 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080040 messages_.clear();
41 }
42
43 // Prints out all of the messages (like when a test fails).
44 void PrintAllMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070045 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080046 for (auto it = messages_.begin(); it != messages_.end(); ++it) {
47 logging::internal::PrintMessage(stdout, *it);
48 }
49 }
50
Philipp Schradere41ed9d2015-03-15 22:57:13 +000051 void SetOutputFile(const char *filename) {
52 if (strcmp("-", filename) != 0) {
53 FILE *newfile = fopen(filename, "w");
54
55 if (newfile) {
56 output_file_ = newfile;
57 }
58 }
59 }
60
61 void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
62
Austin Schuha0c41ba2020-09-10 22:59:14 -070063 // Don't call these from outside this class.
Philipp Schradere41ed9d2015-03-15 22:57:13 +000064 ~TestLogImplementation() {
65 if (output_file_ != stdout) {
66 fclose(output_file_);
67 }
68 }
Brian Silvermanb3616972013-03-05 19:58:10 -080069
Austin Schuha0c41ba2020-09-10 22:59:14 -070070 private:
Brian Silvermanbe858a12014-04-30 17:37:28 -070071 virtual void HandleMessage(const LogMessage &message) override {
Brian Silverman1463c092020-10-30 17:28:24 -070072 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Philipp Schradere41ed9d2015-03-15 22:57:13 +000073 if (message.level == FATAL || print_as_messages_come_in_) {
74 logging::internal::PrintMessage(output_file_, message);
Brian Silvermanb3616972013-03-05 19:58:10 -080075 }
76
77 messages_.push_back(message);
78 }
79
80 ::std::vector<LogMessage> messages_;
Philipp Schradere41ed9d2015-03-15 22:57:13 +000081 bool print_as_messages_come_in_ = false;
82 FILE *output_file_ = stdout;
Brian Silverman1463c092020-10-30 17:28:24 -070083 aos::stl_mutex messages_mutex_;
Brian Silvermanb3616972013-03-05 19:58:10 -080084};
85
86class MyTestEventListener : public ::testing::EmptyTestEventListener {
Austin Schuh82c0c822019-05-27 19:55:20 -070087 virtual void OnTestStart(const ::testing::TestInfo & /*test_info*/) {
Brian Silvermanb3616972013-03-05 19:58:10 -080088 TestLogImplementation::GetInstance()->ClearMessages();
89 }
90 virtual void OnTestEnd(const ::testing::TestInfo &test_info) {
91 if (test_info.result()->Failed()) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +000092 printf("Test %s failed. Use '--print-logs' to see all log messages.\n",
Brian Silvermanb3616972013-03-05 19:58:10 -080093 test_info.name());
Brian Silvermanb3616972013-03-05 19:58:10 -080094 }
95 }
Brian Silvermanb91a37d2013-03-09 17:54:30 -080096
Austin Schuha0c41ba2020-09-10 22:59:14 -070097 virtual void OnTestPartResult(const ::testing::TestPartResult &result) {
Brian Silvermanb91a37d2013-03-09 17:54:30 -080098 if (result.failed()) {
99 const char *failure_type = "unknown";
100 switch (result.type()) {
101 case ::testing::TestPartResult::Type::kNonFatalFailure:
102 failure_type = "EXPECT";
103 break;
104 case ::testing::TestPartResult::Type::kFatalFailure:
105 failure_type = "ASSERT";
106 break;
107 case ::testing::TestPartResult::Type::kSuccess:
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700108 case ::testing::TestPartResult::Type::kSkip:
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800109 break;
110 }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700111 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n", result.file_name(),
112 result.line_number(), failure_type, result.message());
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800113 }
114 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800115};
116
117void *DoEnableTestLogging() {
Tyler Chatow4b471e12020-01-05 20:19:36 -0800118 logging::SetImplementation(TestLogImplementation::GetInstance());
Brian Silvermanb3616972013-03-05 19:58:10 -0800119
120 ::testing::UnitTest::GetInstance()->listeners().Append(
121 new MyTestEventListener());
122
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500123 return nullptr;
Brian Silvermanb3616972013-03-05 19:58:10 -0800124}
125
John Parkb5e47302020-01-08 19:58:18 -0800126static absl::once_flag enable_test_logging_once;
Brian Silvermanb3616972013-03-05 19:58:10 -0800127
128} // namespace
brians343bc112013-02-10 01:53:46 +0000129
Brian Silvermanb3616972013-03-05 19:58:10 -0800130void EnableTestLogging() {
John Parkb5e47302020-01-08 19:58:18 -0800131 absl::call_once(enable_test_logging_once, DoEnableTestLogging);
Brian Silvermanb3616972013-03-05 19:58:10 -0800132}
133
Austin Schuha0c41ba2020-09-10 22:59:14 -0700134void SetLogFileName(const char *filename) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000135 TestLogImplementation::GetInstance()->SetOutputFile(filename);
136}
137
138void ForcePrintLogsDuringTests() {
139 TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
140}
141
brians343bc112013-02-10 01:53:46 +0000142} // namespace testing
brians343bc112013-02-10 01:53:46 +0000143} // namespace aos