blob: cdbec94311e2783ea1ea8abd3069e4d090eeb503 [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
Brian Silvermancb5da1f2015-12-05 22:19:58 -05009#include "aos/common/logging/implementations.h"
Brian Silvermanb3616972013-03-05 19:58:10 -080010#include "aos/common/once.h"
Brian Silverman459d37a2015-03-29 18:00:30 -040011#include "aos/common/mutex.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
54 void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
55
Brian Silvermanb3616972013-03-05 19:58:10 -080056 private:
57 TestLogImplementation() {}
Philipp Schradere41ed9d2015-03-15 22:57:13 +000058 ~TestLogImplementation() {
59 if (output_file_ != stdout) {
60 fclose(output_file_);
61 }
62 }
Brian Silvermanb3616972013-03-05 19:58:10 -080063
64 static TestLogImplementation *CreateInstance() {
65 return new TestLogImplementation();
66 }
67
Brian Silvermanbe858a12014-04-30 17:37:28 -070068 virtual void HandleMessage(const LogMessage &message) override {
Brian Silverman459d37a2015-03-29 18:00:30 -040069 ::aos::MutexLocker 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 Silverman459d37a2015-03-29 18:00:30 -040080 ::aos::Mutex messages_mutex_;
Brian Silvermanb3616972013-03-05 19:58:10 -080081};
82
83class MyTestEventListener : public ::testing::EmptyTestEventListener {
84 virtual void OnTestStart(const ::testing::TestInfo &/*test_info*/) {
85 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
94 virtual void OnTestPartResult( const ::testing::TestPartResult &result) {
95 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:
105 break;
106 }
107 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n",
108 result.file_name(),
109 result.line_number(),
110 failure_type,
111 result.message());
112 }
113 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800114};
115
116void *DoEnableTestLogging() {
117 logging::Init();
118 logging::AddImplementation(TestLogImplementation::GetInstance());
119
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
126Once<void> enable_test_logging_once(DoEnableTestLogging);
127
128} // namespace
brians343bc112013-02-10 01:53:46 +0000129
Brian Silvermanb3616972013-03-05 19:58:10 -0800130void EnableTestLogging() {
131 enable_test_logging_once.Get();
132}
133
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000134void SetLogFileName(const char* filename) {
135 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