blob: dec962b31120d0dcdcb85b0e2a8db5fee01d161d [file] [log] [blame]
Brian Silvermanf665d692013-02-17 22:11:39 -08001#include <string>
2
Brian Silvermanfe457de2014-05-26 22:04:08 -07003#include <inttypes.h>
4
Brian Silvermanf665d692013-02-17 22:11:39 -08005#include "gtest/gtest.h"
6
7#include "aos/common/logging/logging_impl.h"
8#include "aos/common/time.h"
Brian Silverman54a368e2015-02-14 20:05:33 -05009#include "aos/common/logging/logging_printf_formats.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080010
11using ::testing::AssertionResult;
12using ::testing::AssertionSuccess;
13using ::testing::AssertionFailure;
14
15namespace aos {
16namespace logging {
17namespace testing {
18
19class TestLogImplementation : public LogImplementation {
Brian Silvermanf7986142014-04-21 17:42:35 -070020 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
Brian Silvermanf665d692013-02-17 22:11:39 -080021 virtual void DoLog(log_level level, const char *format, va_list ap) {
22 internal::FillInMessage(level, format, ap, &message_);
23
Brian Silvermanfe457de2014-05-26 22:04:08 -070024 if (level == FATAL) {
25 internal::PrintMessage(stderr, message_);
26 abort();
27 }
28
Brian Silvermanf665d692013-02-17 22:11:39 -080029 used_ = true;
30 }
31
32 LogMessage message_;
33
34 public:
35 const LogMessage &message() { return message_; }
36 bool used() { return used_; }
37 void reset_used() { used_ = false; }
38
39 TestLogImplementation() : used_(false) {}
40
41 bool used_;
42};
43class LoggingTest : public ::testing::Test {
44 protected:
45 AssertionResult WasAnythingLogged() {
46 if (log_implementation->used()) {
47 return AssertionSuccess() << "read message '" <<
48 log_implementation->message().message << "'";
49 }
50 return AssertionFailure();
51 }
52 AssertionResult WasLogged(log_level level, const std::string message) {
53 if (!log_implementation->used()) {
54 return AssertionFailure() << "nothing was logged";
55 }
56 if (log_implementation->message().level != level) {
57 return AssertionFailure() << "a message with level " <<
58 log_str(log_implementation->message().level) <<
59 " was logged instead of " << log_str(level);
60 }
61 internal::Context *context = internal::Context::Get();
62 if (log_implementation->message().source != context->source) {
Brian Silvermanf0bb8372014-04-30 15:58:55 -070063 LOG(FATAL, "got a message from %" PRIu32 ", but we're %" PRIu32 "\n",
Brian Silvermanf665d692013-02-17 22:11:39 -080064 static_cast<uint32_t>(log_implementation->message().source),
65 static_cast<uint32_t>(context->source));
66 }
Austin Schuhaebbc342015-01-25 02:25:13 -080067 if (log_implementation->message().name_length != context->name_size ||
68 memcmp(log_implementation->message().name, context->name,
69 context->name_size) !=
Brian Silvermanf0bb8372014-04-30 15:58:55 -070070 0) {
71 LOG(FATAL, "got a message from %.*s, but we're %s\n",
72 static_cast<int>(log_implementation->message().name_length),
Austin Schuhaebbc342015-01-25 02:25:13 -080073 log_implementation->message().name, context->name);
Brian Silvermanf665d692013-02-17 22:11:39 -080074 }
75 if (strstr(log_implementation->message().message, message.c_str())
76 == NULL) {
77 return AssertionFailure() << "got a message of '" <<
78 log_implementation->message().message <<
79 "' but expected it to contain '" << message << "'";
80 }
81
82 return AssertionSuccess() << log_implementation->message().message;
83 }
84
85 private:
86 virtual void SetUp() {
87 static bool first = true;
88 if (first) {
89 first = false;
90
91 Init();
Brian Silvermanf665d692013-02-17 22:11:39 -080092 AddImplementation(log_implementation = new TestLogImplementation());
93 }
94
95 log_implementation->reset_used();
96 }
97 virtual void TearDown() {
98 Cleanup();
99 }
100
101 static TestLogImplementation *log_implementation;
102};
103TestLogImplementation *LoggingTest::log_implementation(NULL);
104typedef LoggingTest LoggingDeathTest;
105
106// Tests both basic logging functionality and that the test setup works
107// correctly.
108TEST_F(LoggingTest, Basic) {
109 EXPECT_FALSE(WasAnythingLogged());
110 LOG(INFO, "test log 1\n");
111 EXPECT_TRUE(WasLogged(INFO, "test log 1\n"));
112 LOG(INFO, "test log 1.5\n");
113 // there's a subtle typo on purpose...
114 EXPECT_FALSE(WasLogged(INFO, "test log 15\n"));
115 LOG(ERROR, "test log 2=%d\n", 55);
116 EXPECT_TRUE(WasLogged(ERROR, "test log 2=55\n"));
117 LOG(ERROR, "test log 3\n");
118 EXPECT_FALSE(WasLogged(WARNING, "test log 3\n"));
119 LOG(WARNING, "test log 4\n");
120 EXPECT_TRUE(WasAnythingLogged());
121}
122TEST_F(LoggingTest, Cork) {
123 static const int begin_line = __LINE__;
124 LOG_CORK("first part ");
125 LOG_CORK("second part (=%d) ", 19);
126 EXPECT_FALSE(WasAnythingLogged());
127 LOG_CORK("third part ");
128 static const int end_line = __LINE__;
129 LOG_UNCORK(WARNING, "last part %d\n", 5);
130 std::stringstream expected;
131 expected << "logging_impl_test.cc: ";
132 expected << (begin_line + 1);
133 expected << "-";
134 expected << (end_line + 1);
135 expected << ": ";
Brian Silvermanc0a0d112013-09-19 21:08:49 -0700136 expected << __func__;
Brian Silvermanf665d692013-02-17 22:11:39 -0800137 expected << ": first part second part (=19) third part last part 5\n";
138 EXPECT_TRUE(WasLogged(WARNING, expected.str()));
139}
140
Brian Silvermanf665d692013-02-17 22:11:39 -0800141TEST_F(LoggingDeathTest, Fatal) {
142 ASSERT_EXIT(LOG(FATAL, "this should crash it\n"),
143 ::testing::KilledBySignal(SIGABRT),
144 "this should crash it");
145}
Brian Silvermanfe457de2014-05-26 22:04:08 -0700146
147TEST_F(LoggingDeathTest, PCHECK) {
148 EXPECT_DEATH(PCHECK(fprintf(stdin, "nope")),
149 ".*fprintf\\(stdin, \"nope\"\\).*failed.*");
150}
151
152TEST_F(LoggingTest, PCHECK) {
153 EXPECT_EQ(7, PCHECK(printf("abc123\n")));
154}
Brian Silvermanf665d692013-02-17 22:11:39 -0800155
156TEST_F(LoggingTest, PrintfDirectives) {
157 LOG(INFO, "test log %%1 %%d\n");
158 EXPECT_TRUE(WasLogged(INFO, "test log %1 %d\n"));
159 LOG_DYNAMIC(WARNING, "test log %%2 %%f\n");
160 EXPECT_TRUE(WasLogged(WARNING, "test log %2 %f\n"));
161 LOG_CORK("log 3 part %%1 %%d ");
162 LOG_UNCORK(DEBUG, "log 3 part %%2 %%f\n");
163 EXPECT_TRUE(WasLogged(DEBUG, "log 3 part %1 %d log 3 part %2 %f\n"));
164}
165
166TEST_F(LoggingTest, Timing) {
167 // For writing only.
168 //static const long kTimingCycles = 5000000;
169 static const long kTimingCycles = 5000;
170
171 time::Time start = time::Time::Now();
172 for (long i = 0; i < kTimingCycles; ++i) {
173 LOG(INFO, "a\n");
174 }
175 time::Time end = time::Time::Now();
176 time::Time diff = end - start;
Brian Silverman41abe012014-02-08 18:25:02 -0800177 printf("short message took %" PRId64 " nsec for %ld\n",
Brian Silvermanf665d692013-02-17 22:11:39 -0800178 diff.ToNSec(), kTimingCycles);
179
180 start = time::Time::Now();
181 for (long i = 0; i < kTimingCycles; ++i) {
182 LOG(INFO, "something longer than just \"a\" to log to test timing\n");
183 }
184 end = time::Time::Now();
185 diff = end - start;
Brian Silverman41abe012014-02-08 18:25:02 -0800186 printf("long message took %" PRId64 " nsec for %ld\n",
Brian Silvermanf665d692013-02-17 22:11:39 -0800187 diff.ToNSec(), kTimingCycles);
188}
189
Brian Silverman54a368e2015-02-14 20:05:33 -0500190TEST(LoggingPrintFormatTest, Time) {
191 char buffer[1024];
192
193 // Easy ones.
194 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
195 AOS_TIME_ARGS(2, 0)));
196 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
197 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
198 AOS_TIME_ARGS(2, 1)));
199 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
200
201 // This one should be exact.
202 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
203 AOS_TIME_ARGS(2, 1000)));
204 EXPECT_EQ("0000000002.000001s", ::std::string(buffer));
205
206 // Make sure rounding works correctly.
207 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
208 AOS_TIME_ARGS(2, 999)));
209 EXPECT_EQ("0000000002.000001s", ::std::string(buffer));
210 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
211 AOS_TIME_ARGS(2, 500)));
212 EXPECT_EQ("0000000002.000001s", ::std::string(buffer));
213 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
214 AOS_TIME_ARGS(2, 499)));
215 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
216
217 // This used to result in "0000000001.099500s".
218 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
219 AOS_TIME_ARGS(1, 995000000)));
220 EXPECT_EQ("0000000001.995000s", ::std::string(buffer));
221}
222
223TEST(LoggingPrintFormatTest, Base) {
224 char buffer[1024];
225
226 static const ::std::string kExpected1 =
227 "name(971)(01678): ERROR at 0000000001.995000s: ";
228 ASSERT_GT(sizeof(buffer), kExpected1.size());
229 ASSERT_EQ(
230 kExpected1.size(),
231 static_cast<size_t>(snprintf(
232 buffer, sizeof(buffer), AOS_LOGGING_BASE_FORMAT,
233 AOS_LOGGING_BASE_ARGS(4, "name", 971, 1678, ERROR, 1, 995000000))));
234 EXPECT_EQ(kExpected1, ::std::string(buffer));
235}
236
Brian Silvermanf665d692013-02-17 22:11:39 -0800237} // namespace testing
238} // namespace logging
239} // namespace aos