blob: d71d0238f550f6dfa1403d604e47ca8e60b10b67 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#include "aos/common/queue_testutils.h"
Brian Silvermanf665d692013-02-17 22:11:39 -08002
3#include <string.h>
Brian Silverman797e71e2013-09-06 17:29:39 -07004#include <sys/mman.h>
Brian Silvermaneeb62ca2013-09-11 15:08:03 -07005#include <unistd.h>
6#include <stdlib.h>
Brian Silvermanf665d692013-02-17 22:11:39 -08007
Brian Silvermanb3616972013-03-05 19:58:10 -08008#include "gtest/gtest.h"
9
brians343bc112013-02-10 01:53:46 +000010#include "aos/common/queue.h"
Brian Silvermanb3616972013-03-05 19:58:10 -080011#include "aos/common/logging/logging_impl.h"
12#include "aos/common/once.h"
13
14using ::aos::logging::LogMessage;
brians343bc112013-02-10 01:53:46 +000015
16namespace aos {
17namespace common {
18namespace testing {
Brian Silvermanb3616972013-03-05 19:58:10 -080019namespace {
20
Brian Silvermanbe858a12014-04-30 17:37:28 -070021class TestLogImplementation : public logging::HandleMessageLogImplementation {
Brian Silvermanb3616972013-03-05 19:58:10 -080022 public:
23 const ::std::vector<LogMessage> &messages() { return messages_; }
24
25 // This class has to be a singleton so that everybody can get access to the
26 // same instance to read out the messages etc.
27 static TestLogImplementation *GetInstance() {
28 static Once<TestLogImplementation> once(CreateInstance);
29 return once.Get();
30 }
31
32 // Clears out all of the messages already recorded.
33 void ClearMessages() {
34 messages_.clear();
35 }
36
37 // Prints out all of the messages (like when a test fails).
38 void PrintAllMessages() {
39 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 {
Philipp Schradere41ed9d2015-03-15 22:57:13 +000069 if (message.level == FATAL || print_as_messages_come_in_) {
70 logging::internal::PrintMessage(output_file_, message);
Brian Silvermanb3616972013-03-05 19:58:10 -080071 }
72
73 messages_.push_back(message);
74 }
75
76 ::std::vector<LogMessage> messages_;
Philipp Schradere41ed9d2015-03-15 22:57:13 +000077 bool print_as_messages_come_in_ = false;
78 FILE *output_file_ = stdout;
Brian Silvermanb3616972013-03-05 19:58:10 -080079};
80
81class MyTestEventListener : public ::testing::EmptyTestEventListener {
82 virtual void OnTestStart(const ::testing::TestInfo &/*test_info*/) {
83 TestLogImplementation::GetInstance()->ClearMessages();
84 }
85 virtual void OnTestEnd(const ::testing::TestInfo &test_info) {
86 if (test_info.result()->Failed()) {
Philipp Schradere41ed9d2015-03-15 22:57:13 +000087 printf("Test %s failed. Use '--print-logs' to see all log messages.\n",
Brian Silvermanb3616972013-03-05 19:58:10 -080088 test_info.name());
Brian Silvermanb3616972013-03-05 19:58:10 -080089 }
90 }
Brian Silvermanb91a37d2013-03-09 17:54:30 -080091
92 virtual void OnTestPartResult( const ::testing::TestPartResult &result) {
93 if (result.failed()) {
94 const char *failure_type = "unknown";
95 switch (result.type()) {
96 case ::testing::TestPartResult::Type::kNonFatalFailure:
97 failure_type = "EXPECT";
98 break;
99 case ::testing::TestPartResult::Type::kFatalFailure:
100 failure_type = "ASSERT";
101 break;
102 case ::testing::TestPartResult::Type::kSuccess:
103 break;
104 }
105 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n",
106 result.file_name(),
107 result.line_number(),
108 failure_type,
109 result.message());
110 }
111 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800112};
113
114void *DoEnableTestLogging() {
115 logging::Init();
116 logging::AddImplementation(TestLogImplementation::GetInstance());
117
118 ::testing::UnitTest::GetInstance()->listeners().Append(
119 new MyTestEventListener());
120
121 return NULL;
122}
123
124Once<void> enable_test_logging_once(DoEnableTestLogging);
125
Brian Silverman797e71e2013-09-06 17:29:39 -0700126const size_t kCoreSize = 0x100000;
127
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700128void TerminateExitHandler() {
129 _exit(EXIT_SUCCESS);
130}
131
Brian Silvermanb3616972013-03-05 19:58:10 -0800132} // namespace
brians343bc112013-02-10 01:53:46 +0000133
134GlobalCoreInstance::GlobalCoreInstance() {
brians343bc112013-02-10 01:53:46 +0000135 global_core = &global_core_data_;
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700136 global_core->owner = true;
137 // Use mmap(2) manually instead of through malloc(3) so that we can pass
138 // MAP_SHARED which allows forked processes to communicate using the
139 // "shared" memory.
Brian Silverman797e71e2013-09-06 17:29:39 -0700140 void *memory = mmap(NULL, kCoreSize, PROT_READ | PROT_WRITE,
141 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
Brian Silvermanfe457de2014-05-26 22:04:08 -0700142 CHECK_NE(memory, MAP_FAILED);
brians343bc112013-02-10 01:53:46 +0000143
Brian Silverman01be0002014-05-10 15:44:38 -0700144 aos_core_use_address_as_shared_mem(memory, kCoreSize);
Brian Silvermanb3616972013-03-05 19:58:10 -0800145
146 EnableTestLogging();
brians343bc112013-02-10 01:53:46 +0000147}
148
149GlobalCoreInstance::~GlobalCoreInstance() {
Brian Silvermanfe457de2014-05-26 22:04:08 -0700150 PCHECK(munmap(global_core->mem_struct, kCoreSize));
brians343bc112013-02-10 01:53:46 +0000151 global_core = NULL;
152}
153
Brian Silvermanb3616972013-03-05 19:58:10 -0800154void EnableTestLogging() {
155 enable_test_logging_once.Get();
156}
157
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700158void PreventExit() {
Brian Silvermanfe457de2014-05-26 22:04:08 -0700159 CHECK_EQ(atexit(TerminateExitHandler), 0);
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700160}
161
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000162void SetLogFileName(const char* filename) {
163 TestLogImplementation::GetInstance()->SetOutputFile(filename);
164}
165
166void ForcePrintLogsDuringTests() {
167 TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
168}
169
brians343bc112013-02-10 01:53:46 +0000170} // namespace testing
171} // namespace common
172} // namespace aos