blob: 56875bb29942cbeaf1f66268792e4b479ab545c7 [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 Silvermanb3616972013-03-05 19:58:10 -080011
12using ::aos::logging::LogMessage;
brians343bc112013-02-10 01:53:46 +000013
Stephan Pleinesf63bde82024-01-13 15:59:33 -080014namespace aos::testing {
Brian Silvermanb3616972013-03-05 19:58:10 -080015namespace {
16
Brian Silvermanbe858a12014-04-30 17:37:28 -070017class TestLogImplementation : public logging::HandleMessageLogImplementation {
Brian Silvermanb3616972013-03-05 19:58:10 -080018 public:
19 const ::std::vector<LogMessage> &messages() { return messages_; }
20
Austin Schuh82c0c822019-05-27 19:55:20 -070021 ::aos::monotonic_clock::time_point monotonic_now() const override {
Austin Schuh82c0c822019-05-27 19:55:20 -070022 return ::aos::monotonic_clock::now();
23 }
24
Austin Schuhad9e5eb2021-11-19 20:33:55 -080025 std::string_view MyName() override { return "Name"; }
26
Brian Silvermanb3616972013-03-05 19:58:10 -080027 // This class has to be a singleton so that everybody can get access to the
28 // same instance to read out the messages etc.
Austin Schuha0c41ba2020-09-10 22:59:14 -070029 static std::shared_ptr<TestLogImplementation> GetInstance() {
30 static std::shared_ptr<TestLogImplementation> instance =
31 std::make_unique<TestLogImplementation>();
John Parkb5e47302020-01-08 19:58:18 -080032 return instance;
Brian Silvermanb3616972013-03-05 19:58:10 -080033 }
34
35 // Clears out all of the messages already recorded.
36 void ClearMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070037 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080038 messages_.clear();
39 }
40
41 // Prints out all of the messages (like when a test fails).
42 void PrintAllMessages() {
Brian Silverman1463c092020-10-30 17:28:24 -070043 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080044 for (auto it = messages_.begin(); it != messages_.end(); ++it) {
45 logging::internal::PrintMessage(stdout, *it);
46 }
47 }
48
Philipp Schradere41ed9d2015-03-15 22:57:13 +000049 void SetOutputFile(const char *filename) {
50 if (strcmp("-", filename) != 0) {
51 FILE *newfile = fopen(filename, "w");
52
53 if (newfile) {
54 output_file_ = newfile;
55 }
56 }
57 }
58
59 void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
60
Austin Schuha0c41ba2020-09-10 22:59:14 -070061 // Don't call these from outside this class.
Philipp Schradere41ed9d2015-03-15 22:57:13 +000062 ~TestLogImplementation() {
63 if (output_file_ != stdout) {
64 fclose(output_file_);
65 }
66 }
Brian Silvermanb3616972013-03-05 19:58:10 -080067
Austin Schuha0c41ba2020-09-10 22:59:14 -070068 private:
Brian Silvermanbe858a12014-04-30 17:37:28 -070069 virtual void HandleMessage(const LogMessage &message) override {
Brian Silverman1463c092020-10-30 17:28:24 -070070 std::unique_lock<aos::stl_mutex> locker(messages_mutex_);
Philipp Schradere41ed9d2015-03-15 22:57:13 +000071 if (message.level == FATAL || print_as_messages_come_in_) {
72 logging::internal::PrintMessage(output_file_, message);
Brian Silvermanb3616972013-03-05 19:58:10 -080073 }
74
75 messages_.push_back(message);
76 }
77
78 ::std::vector<LogMessage> messages_;
Philipp Schradere41ed9d2015-03-15 22:57:13 +000079 bool print_as_messages_come_in_ = false;
80 FILE *output_file_ = stdout;
Brian Silverman1463c092020-10-30 17:28:24 -070081 aos::stl_mutex messages_mutex_;
Brian Silvermanb3616972013-03-05 19:58:10 -080082};
83
84class MyTestEventListener : public ::testing::EmptyTestEventListener {
Austin Schuh82c0c822019-05-27 19:55:20 -070085 virtual void OnTestStart(const ::testing::TestInfo & /*test_info*/) {
Brian Silvermanb3616972013-03-05 19:58:10 -080086 TestLogImplementation::GetInstance()->ClearMessages();
87 }
88 virtual void OnTestEnd(const ::testing::TestInfo &test_info) {
89 if (test_info.result()->Failed()) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +000090 printf("Test %s failed. Use '--print-logs' to see all log messages.\n",
Brian Silvermanb3616972013-03-05 19:58:10 -080091 test_info.name());
Brian Silvermanb3616972013-03-05 19:58:10 -080092 }
93 }
Brian Silvermanb91a37d2013-03-09 17:54:30 -080094
Austin Schuha0c41ba2020-09-10 22:59:14 -070095 virtual void OnTestPartResult(const ::testing::TestPartResult &result) {
Brian Silvermanb91a37d2013-03-09 17:54:30 -080096 if (result.failed()) {
97 const char *failure_type = "unknown";
98 switch (result.type()) {
99 case ::testing::TestPartResult::Type::kNonFatalFailure:
100 failure_type = "EXPECT";
101 break;
102 case ::testing::TestPartResult::Type::kFatalFailure:
103 failure_type = "ASSERT";
104 break;
105 case ::testing::TestPartResult::Type::kSuccess:
James Kuszmaulf4bf9fe2021-05-10 22:58:24 -0700106 case ::testing::TestPartResult::Type::kSkip:
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800107 break;
108 }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700109 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n", result.file_name(),
110 result.line_number(), failure_type, result.message());
Brian Silvermanb91a37d2013-03-09 17:54:30 -0800111 }
112 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800113};
114
115void *DoEnableTestLogging() {
Tyler Chatow4b471e12020-01-05 20:19:36 -0800116 logging::SetImplementation(TestLogImplementation::GetInstance());
Brian Silvermanb3616972013-03-05 19:58:10 -0800117
118 ::testing::UnitTest::GetInstance()->listeners().Append(
119 new MyTestEventListener());
120
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500121 return nullptr;
Brian Silvermanb3616972013-03-05 19:58:10 -0800122}
123
John Parkb5e47302020-01-08 19:58:18 -0800124static absl::once_flag enable_test_logging_once;
Brian Silvermanb3616972013-03-05 19:58:10 -0800125
126} // namespace
brians343bc112013-02-10 01:53:46 +0000127
Brian Silvermanb3616972013-03-05 19:58:10 -0800128void EnableTestLogging() {
John Parkb5e47302020-01-08 19:58:18 -0800129 absl::call_once(enable_test_logging_once, DoEnableTestLogging);
Brian Silvermanb3616972013-03-05 19:58:10 -0800130}
131
Austin Schuha0c41ba2020-09-10 22:59:14 -0700132void SetLogFileName(const char *filename) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000133 TestLogImplementation::GetInstance()->SetOutputFile(filename);
134}
135
136void ForcePrintLogsDuringTests() {
137 TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
138}
139
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800140} // namespace aos::testing