blob: fa70d471e19c1e518347cb57e65d5b1679285071 [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
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -05003#include <stdio.h>
4
5#include <vector>
Brian Silvermanf665d692013-02-17 22:11:39 -08006
Brian Silvermanb3616972013-03-05 19:58:10 -08007#include "gtest/gtest.h"
8
John Park33858a32018-09-28 23:05:48 -07009#include "aos/logging/implementations.h"
10#include "aos/mutex/mutex.h"
Sabina Davis2ed5ea22017-09-26 22:27:42 -070011#include "aos/once.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
23 // This class has to be a singleton so that everybody can get access to the
24 // same instance to read out the messages etc.
25 static TestLogImplementation *GetInstance() {
26 static Once<TestLogImplementation> once(CreateInstance);
27 return once.Get();
28 }
29
30 // Clears out all of the messages already recorded.
31 void ClearMessages() {
Brian Silverman459d37a2015-03-29 18:00:30 -040032 ::aos::MutexLocker locker(&messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080033 messages_.clear();
34 }
35
36 // Prints out all of the messages (like when a test fails).
37 void PrintAllMessages() {
Brian Silverman459d37a2015-03-29 18:00:30 -040038 ::aos::MutexLocker locker(&messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080039 for (auto it = messages_.begin(); it != messages_.end(); ++it) {
40 logging::internal::PrintMessage(stdout, *it);
41 }
42 }
43
Philipp Schradere41ed9d2015-03-15 22:57:13 +000044 void SetOutputFile(const char *filename) {
45 if (strcmp("-", filename) != 0) {
46 FILE *newfile = fopen(filename, "w");
47
48 if (newfile) {
49 output_file_ = newfile;
50 }
51 }
52 }
53
Austin Schuh1bf8a212019-05-26 22:13:14 -070054 bool fill_type_cache() override { return false; }
55
Philipp Schradere41ed9d2015-03-15 22:57:13 +000056 void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
57
Brian Silvermanb3616972013-03-05 19:58:10 -080058 private:
59 TestLogImplementation() {}
Philipp Schradere41ed9d2015-03-15 22:57:13 +000060 ~TestLogImplementation() {
61 if (output_file_ != stdout) {
62 fclose(output_file_);
63 }
64 }
Brian Silvermanb3616972013-03-05 19:58:10 -080065
66 static TestLogImplementation *CreateInstance() {
67 return new TestLogImplementation();
68 }
69
Brian Silvermanbe858a12014-04-30 17:37:28 -070070 virtual void HandleMessage(const LogMessage &message) override {
Brian Silverman459d37a2015-03-29 18:00:30 -040071 ::aos::MutexLocker 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 Silverman459d37a2015-03-29 18:00:30 -040082 ::aos::Mutex messages_mutex_;
Brian Silvermanb3616972013-03-05 19:58:10 -080083};
84
85class MyTestEventListener : public ::testing::EmptyTestEventListener {
86 virtual void OnTestStart(const ::testing::TestInfo &/*test_info*/) {
87 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
96 virtual void OnTestPartResult( const ::testing::TestPartResult &result) {
97 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:
107 break;
108 }
109 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n",
110 result.file_name(),
111 result.line_number(),
112 failure_type,
113 result.message());
114 }
115 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800116};
117
118void *DoEnableTestLogging() {
119 logging::Init();
120 logging::AddImplementation(TestLogImplementation::GetInstance());
121
122 ::testing::UnitTest::GetInstance()->listeners().Append(
123 new MyTestEventListener());
124
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -0500125 return nullptr;
Brian Silvermanb3616972013-03-05 19:58:10 -0800126}
127
128Once<void> enable_test_logging_once(DoEnableTestLogging);
129
130} // namespace
brians343bc112013-02-10 01:53:46 +0000131
Brian Silvermanb3616972013-03-05 19:58:10 -0800132void EnableTestLogging() {
133 enable_test_logging_once.Get();
134}
135
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000136void SetLogFileName(const char* filename) {
137 TestLogImplementation::GetInstance()->SetOutputFile(filename);
138}
139
140void ForcePrintLogsDuringTests() {
141 TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
142}
143
brians343bc112013-02-10 01:53:46 +0000144} // namespace testing
brians343bc112013-02-10 01:53:46 +0000145} // namespace aos