blob: a40b5e98ab91b1c6fc2ba61a5d5625a850e96963 [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"
Brian Silverman459d37a2015-03-29 18:00:30 -040013#include "aos/common/mutex.h"
Brian Silvermanb3616972013-03-05 19:58:10 -080014
15using ::aos::logging::LogMessage;
brians343bc112013-02-10 01:53:46 +000016
17namespace aos {
18namespace common {
19namespace testing {
Brian Silvermanb3616972013-03-05 19:58:10 -080020namespace {
21
Brian Silvermanbe858a12014-04-30 17:37:28 -070022class TestLogImplementation : public logging::HandleMessageLogImplementation {
Brian Silvermanb3616972013-03-05 19:58:10 -080023 public:
24 const ::std::vector<LogMessage> &messages() { return messages_; }
25
26 // This class has to be a singleton so that everybody can get access to the
27 // same instance to read out the messages etc.
28 static TestLogImplementation *GetInstance() {
29 static Once<TestLogImplementation> once(CreateInstance);
30 return once.Get();
31 }
32
33 // Clears out all of the messages already recorded.
34 void ClearMessages() {
Brian Silverman459d37a2015-03-29 18:00:30 -040035 ::aos::MutexLocker locker(&messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080036 messages_.clear();
37 }
38
39 // Prints out all of the messages (like when a test fails).
40 void PrintAllMessages() {
Brian Silverman459d37a2015-03-29 18:00:30 -040041 ::aos::MutexLocker locker(&messages_mutex_);
Brian Silvermanb3616972013-03-05 19:58:10 -080042 for (auto it = messages_.begin(); it != messages_.end(); ++it) {
43 logging::internal::PrintMessage(stdout, *it);
44 }
45 }
46
Philipp Schradere41ed9d2015-03-15 22:57:13 +000047 void SetOutputFile(const char *filename) {
48 if (strcmp("-", filename) != 0) {
49 FILE *newfile = fopen(filename, "w");
50
51 if (newfile) {
52 output_file_ = newfile;
53 }
54 }
55 }
56
57 void PrintMessagesAsTheyComeIn() { print_as_messages_come_in_ = true; }
58
Brian Silvermanb3616972013-03-05 19:58:10 -080059 private:
60 TestLogImplementation() {}
Philipp Schradere41ed9d2015-03-15 22:57:13 +000061 ~TestLogImplementation() {
62 if (output_file_ != stdout) {
63 fclose(output_file_);
64 }
65 }
Brian Silvermanb3616972013-03-05 19:58:10 -080066
67 static TestLogImplementation *CreateInstance() {
68 return new TestLogImplementation();
69 }
70
Brian Silvermanbe858a12014-04-30 17:37:28 -070071 virtual void HandleMessage(const LogMessage &message) override {
Brian Silverman459d37a2015-03-29 18:00:30 -040072 ::aos::MutexLocker 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 Silverman459d37a2015-03-29 18:00:30 -040083 ::aos::Mutex messages_mutex_;
Brian Silvermanb3616972013-03-05 19:58:10 -080084};
85
86class MyTestEventListener : public ::testing::EmptyTestEventListener {
87 virtual void OnTestStart(const ::testing::TestInfo &/*test_info*/) {
88 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
97 virtual void OnTestPartResult( const ::testing::TestPartResult &result) {
98 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:
108 break;
109 }
110 log_do(ERROR, "%s: %d: gtest %s failure\n%s\n",
111 result.file_name(),
112 result.line_number(),
113 failure_type,
114 result.message());
115 }
116 }
Brian Silvermanb3616972013-03-05 19:58:10 -0800117};
118
119void *DoEnableTestLogging() {
120 logging::Init();
121 logging::AddImplementation(TestLogImplementation::GetInstance());
122
123 ::testing::UnitTest::GetInstance()->listeners().Append(
124 new MyTestEventListener());
125
126 return NULL;
127}
128
129Once<void> enable_test_logging_once(DoEnableTestLogging);
130
Brian Silverman797e71e2013-09-06 17:29:39 -0700131const size_t kCoreSize = 0x100000;
132
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700133void TerminateExitHandler() {
134 _exit(EXIT_SUCCESS);
135}
136
Brian Silvermanb3616972013-03-05 19:58:10 -0800137} // namespace
brians343bc112013-02-10 01:53:46 +0000138
139GlobalCoreInstance::GlobalCoreInstance() {
brians343bc112013-02-10 01:53:46 +0000140 global_core = &global_core_data_;
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700141 global_core->owner = true;
142 // Use mmap(2) manually instead of through malloc(3) so that we can pass
143 // MAP_SHARED which allows forked processes to communicate using the
144 // "shared" memory.
Brian Silverman797e71e2013-09-06 17:29:39 -0700145 void *memory = mmap(NULL, kCoreSize, PROT_READ | PROT_WRITE,
146 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
Brian Silvermanfe457de2014-05-26 22:04:08 -0700147 CHECK_NE(memory, MAP_FAILED);
brians343bc112013-02-10 01:53:46 +0000148
Brian Silverman01be0002014-05-10 15:44:38 -0700149 aos_core_use_address_as_shared_mem(memory, kCoreSize);
Brian Silvermanb3616972013-03-05 19:58:10 -0800150
151 EnableTestLogging();
brians343bc112013-02-10 01:53:46 +0000152}
153
154GlobalCoreInstance::~GlobalCoreInstance() {
Brian Silvermanfe457de2014-05-26 22:04:08 -0700155 PCHECK(munmap(global_core->mem_struct, kCoreSize));
brians343bc112013-02-10 01:53:46 +0000156 global_core = NULL;
157}
158
Brian Silvermanb3616972013-03-05 19:58:10 -0800159void EnableTestLogging() {
160 enable_test_logging_once.Get();
161}
162
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700163void PreventExit() {
Brian Silvermanfe457de2014-05-26 22:04:08 -0700164 CHECK_EQ(atexit(TerminateExitHandler), 0);
Brian Silvermaneeb62ca2013-09-11 15:08:03 -0700165}
166
Philipp Schradere41ed9d2015-03-15 22:57:13 +0000167void SetLogFileName(const char* filename) {
168 TestLogImplementation::GetInstance()->SetOutputFile(filename);
169}
170
171void ForcePrintLogsDuringTests() {
172 TestLogImplementation::GetInstance()->PrintMessagesAsTheyComeIn();
173}
174
brians343bc112013-02-10 01:53:46 +0000175} // namespace testing
176} // namespace common
177} // namespace aos