blob: 6b85358cca0327a5385deda787c6626b8ba32244 [file] [log] [blame]
Tyler Chatow4b471e12020-01-05 20:19:36 -08001#include "aos/logging/implementations.h"
2
Brian Silvermanfe457de2014-05-26 22:04:08 -07003#include <inttypes.h>
4
Austin Schuhf2a50ba2016-12-24 16:16:26 -08005#include <chrono>
6#include <string>
7
Tyler Chatow4b471e12020-01-05 20:19:36 -08008#include "aos/logging/printf_formats.h"
9#include "aos/time/time.h"
Brian Silverman1463c092020-10-30 17:28:24 -070010
11#include "glog/logging.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080012#include "gtest/gtest.h"
13
Tyler Chatow4b471e12020-01-05 20:19:36 -080014using ::testing::AssertionFailure;
Brian Silvermanf665d692013-02-17 22:11:39 -080015using ::testing::AssertionResult;
16using ::testing::AssertionSuccess;
Brian Silvermanf665d692013-02-17 22:11:39 -080017
18namespace aos {
19namespace logging {
20namespace testing {
21
Austin Schuhf2a50ba2016-12-24 16:16:26 -080022namespace chrono = ::std::chrono;
23
Alex Perrycb7da4b2019-08-28 19:35:56 -070024class TestLogImplementation : public LogImplementation {
25 virtual ::aos::monotonic_clock::time_point monotonic_now() const {
26 return ::aos::monotonic_clock::now();
27 }
28
29 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0))) void DoLog(
30 log_level level, const char *format, va_list ap) override {
Austin Schuh82c0c822019-05-27 19:55:20 -070031 internal::FillInMessage(level, monotonic_now(), format, ap, &message_);
Brian Silvermanf665d692013-02-17 22:11:39 -080032
Brian Silvermanfe457de2014-05-26 22:04:08 -070033 if (level == FATAL) {
34 internal::PrintMessage(stderr, message_);
35 abort();
36 }
37
Brian Silvermanf665d692013-02-17 22:11:39 -080038 used_ = true;
39 }
40
41 LogMessage message_;
42
43 public:
44 const LogMessage &message() { return message_; }
45 bool used() { return used_; }
Brian Silvermanf665d692013-02-17 22:11:39 -080046
Austin Schuha0c41ba2020-09-10 22:59:14 -070047 bool used_ = false;
Brian Silvermanf665d692013-02-17 22:11:39 -080048};
49class LoggingTest : public ::testing::Test {
50 protected:
51 AssertionResult WasAnythingLogged() {
52 if (log_implementation->used()) {
Tyler Chatow4b471e12020-01-05 20:19:36 -080053 return AssertionSuccess() << "read message '"
54 << log_implementation->message().message << "'";
Brian Silvermanf665d692013-02-17 22:11:39 -080055 }
56 return AssertionFailure();
57 }
58 AssertionResult WasLogged(log_level level, const std::string message) {
59 if (!log_implementation->used()) {
60 return AssertionFailure() << "nothing was logged";
61 }
62 if (log_implementation->message().level != level) {
Tyler Chatow4b471e12020-01-05 20:19:36 -080063 return AssertionFailure() << "a message with level "
64 << log_str(log_implementation->message().level)
65 << " was logged instead of " << log_str(level);
Brian Silvermanf665d692013-02-17 22:11:39 -080066 }
67 internal::Context *context = internal::Context::Get();
68 if (log_implementation->message().source != context->source) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070069 AOS_LOG(FATAL, "got a message from %" PRIu32 ", but we're %" PRIu32 "\n",
70 static_cast<uint32_t>(log_implementation->message().source),
71 static_cast<uint32_t>(context->source));
Brian Silvermanf665d692013-02-17 22:11:39 -080072 }
Austin Schuhaebbc342015-01-25 02:25:13 -080073 if (log_implementation->message().name_length != context->name_size ||
74 memcmp(log_implementation->message().name, context->name,
Tyler Chatow4b471e12020-01-05 20:19:36 -080075 context->name_size) != 0) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070076 AOS_LOG(FATAL, "got a message from %.*s, but we're %s\n",
77 static_cast<int>(log_implementation->message().name_length),
78 log_implementation->message().name, context->name);
Brian Silvermanf665d692013-02-17 22:11:39 -080079 }
Tyler Chatow4b471e12020-01-05 20:19:36 -080080 if (strstr(log_implementation->message().message, message.c_str()) ==
81 NULL) {
82 return AssertionFailure()
83 << "got a message of '" << log_implementation->message().message
84 << "' but expected it to contain '" << message << "'";
Brian Silvermanf665d692013-02-17 22:11:39 -080085 }
86
87 return AssertionSuccess() << log_implementation->message().message;
88 }
89
90 private:
Brian Silvermancb5da1f2015-12-05 22:19:58 -050091 void SetUp() override {
Austin Schuha0c41ba2020-09-10 22:59:14 -070092 log_implementation = std::make_shared<TestLogImplementation>();
93 SetImplementation(log_implementation);
Brian Silvermanf665d692013-02-17 22:11:39 -080094 }
Austin Schuha0c41ba2020-09-10 22:59:14 -070095 void TearDown() override {
96 SetImplementation(nullptr);
Austin Schuha0c41ba2020-09-10 22:59:14 -070097 internal::Context::DeleteNow();
98 CHECK_EQ(log_implementation.use_count(), 1);
99 log_implementation.reset();
100 }
Brian Silvermanf665d692013-02-17 22:11:39 -0800101
Austin Schuha0c41ba2020-09-10 22:59:14 -0700102 std::shared_ptr<TestLogImplementation> log_implementation;
Brian Silvermanf665d692013-02-17 22:11:39 -0800103};
Brian Silvermanf665d692013-02-17 22:11:39 -0800104typedef 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());
Austin Schuhf257f3c2019-10-27 21:00:43 -0700110 AOS_LOG(INFO, "test log 1\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800111 EXPECT_TRUE(WasLogged(INFO, "test log 1\n"));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700112 AOS_LOG(INFO, "test log 1.5\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800113 // there's a subtle typo on purpose...
114 EXPECT_FALSE(WasLogged(INFO, "test log 15\n"));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700115 AOS_LOG(ERROR, "test log 2=%d\n", 55);
Brian Silvermanf665d692013-02-17 22:11:39 -0800116 EXPECT_TRUE(WasLogged(ERROR, "test log 2=55\n"));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700117 AOS_LOG(ERROR, "test log 3\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800118 EXPECT_FALSE(WasLogged(WARNING, "test log 3\n"));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700119 AOS_LOG(WARNING, "test log 4\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800120 EXPECT_TRUE(WasAnythingLogged());
121}
Brian Silvermanf665d692013-02-17 22:11:39 -0800122
Brian Silvermanf665d692013-02-17 22:11:39 -0800123TEST_F(LoggingDeathTest, Fatal) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700124 ASSERT_EXIT(AOS_LOG(FATAL, "this should crash it\n"),
125 ::testing::KilledBySignal(SIGABRT), "this should crash it");
Brian Silvermanf665d692013-02-17 22:11:39 -0800126}
Brian Silvermanfe457de2014-05-26 22:04:08 -0700127
128TEST_F(LoggingDeathTest, PCHECK) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700129 EXPECT_DEATH(AOS_PCHECK(fprintf(stdin, "nope")),
Brian Silvermanfe457de2014-05-26 22:04:08 -0700130 ".*fprintf\\(stdin, \"nope\"\\).*failed.*");
131}
132
Austin Schuhf257f3c2019-10-27 21:00:43 -0700133TEST_F(LoggingTest, PCHECK) { EXPECT_EQ(7, AOS_PCHECK(printf("abc123\n"))); }
Brian Silvermanf665d692013-02-17 22:11:39 -0800134
135TEST_F(LoggingTest, PrintfDirectives) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700136 AOS_LOG(INFO, "test log %%1 %%d\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800137 EXPECT_TRUE(WasLogged(INFO, "test log %1 %d\n"));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700138 AOS_LOG_DYNAMIC(WARNING, "test log %%2 %%f\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800139 EXPECT_TRUE(WasLogged(WARNING, "test log %2 %f\n"));
Brian Silvermanf665d692013-02-17 22:11:39 -0800140}
141
142TEST_F(LoggingTest, Timing) {
143 // For writing only.
Tyler Chatow4b471e12020-01-05 20:19:36 -0800144 // static const long kTimingCycles = 5000000;
Brian Silvermanf665d692013-02-17 22:11:39 -0800145 static const long kTimingCycles = 5000;
146
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800147 monotonic_clock::time_point start = monotonic_clock::now();
Brian Silvermanf665d692013-02-17 22:11:39 -0800148 for (long i = 0; i < kTimingCycles; ++i) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700149 AOS_LOG(INFO, "a\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800150 }
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800151 monotonic_clock::time_point end = monotonic_clock::now();
152 auto diff = end - start;
Brian Silverman41abe012014-02-08 18:25:02 -0800153 printf("short message took %" PRId64 " nsec for %ld\n",
Alex Perrycb7da4b2019-08-28 19:35:56 -0700154 static_cast<int64_t>(
155 chrono::duration_cast<chrono::nanoseconds>(diff).count()),
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800156 kTimingCycles);
Brian Silvermanf665d692013-02-17 22:11:39 -0800157
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800158 start = monotonic_clock::now();
Brian Silvermanf665d692013-02-17 22:11:39 -0800159 for (long i = 0; i < kTimingCycles; ++i) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700160 AOS_LOG(INFO, "something longer than just \"a\" to log to test timing\n");
Brian Silvermanf665d692013-02-17 22:11:39 -0800161 }
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800162 end = monotonic_clock::now();
Brian Silvermanf665d692013-02-17 22:11:39 -0800163 diff = end - start;
Brian Silverman41abe012014-02-08 18:25:02 -0800164 printf("long message took %" PRId64 " nsec for %ld\n",
Alex Perrycb7da4b2019-08-28 19:35:56 -0700165 static_cast<int64_t>(
166 chrono::duration_cast<chrono::nanoseconds>(diff).count()),
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800167 kTimingCycles);
Brian Silvermanf665d692013-02-17 22:11:39 -0800168}
169
Brian Silverman54a368e2015-02-14 20:05:33 -0500170TEST(LoggingPrintFormatTest, Time) {
171 char buffer[1024];
172
173 // Easy ones.
174 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
175 AOS_TIME_ARGS(2, 0)));
176 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
177 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
178 AOS_TIME_ARGS(2, 1)));
179 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
180
181 // This one should be exact.
182 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
183 AOS_TIME_ARGS(2, 1000)));
184 EXPECT_EQ("0000000002.000001s", ::std::string(buffer));
185
186 // Make sure rounding works correctly.
187 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
188 AOS_TIME_ARGS(2, 999)));
Austin Schuh648b3612017-11-20 01:02:24 -0800189 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
Brian Silverman54a368e2015-02-14 20:05:33 -0500190 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
191 AOS_TIME_ARGS(2, 500)));
Austin Schuh648b3612017-11-20 01:02:24 -0800192 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
Brian Silverman54a368e2015-02-14 20:05:33 -0500193 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
194 AOS_TIME_ARGS(2, 499)));
195 EXPECT_EQ("0000000002.000000s", ::std::string(buffer));
196
197 // This used to result in "0000000001.099500s".
198 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
199 AOS_TIME_ARGS(1, 995000000)));
200 EXPECT_EQ("0000000001.995000s", ::std::string(buffer));
Austin Schuh648b3612017-11-20 01:02:24 -0800201
202 // This used to result in "0000000001.099500s".
203 ASSERT_EQ(18, snprintf(buffer, sizeof(buffer), AOS_TIME_FORMAT,
204 AOS_TIME_ARGS(1, 999999999)));
205 EXPECT_EQ("0000000001.999999s", ::std::string(buffer));
Brian Silverman54a368e2015-02-14 20:05:33 -0500206}
207
208TEST(LoggingPrintFormatTest, Base) {
209 char buffer[1024];
210
211 static const ::std::string kExpected1 =
212 "name(971)(01678): ERROR at 0000000001.995000s: ";
213 ASSERT_GT(sizeof(buffer), kExpected1.size());
214 ASSERT_EQ(
215 kExpected1.size(),
216 static_cast<size_t>(snprintf(
217 buffer, sizeof(buffer), AOS_LOGGING_BASE_FORMAT,
218 AOS_LOGGING_BASE_ARGS(4, "name", 971, 1678, ERROR, 1, 995000000))));
219 EXPECT_EQ(kExpected1, ::std::string(buffer));
220}
221
Tyler Chatow67ddb032020-01-12 14:30:04 -0800222TEST(ScopedLogRestorerTest, RestoreTest) {
Austin Schuha0c41ba2020-09-10 22:59:14 -0700223 SetImplementation(std::make_shared<StreamLogImplementation>(stdout));
224 LogImplementation *curr_impl = GetImplementation().get();
Tyler Chatow67ddb032020-01-12 14:30:04 -0800225
226 {
227 ScopedLogRestorer log_restorer;
228
Austin Schuha0c41ba2020-09-10 22:59:14 -0700229 log_restorer.Swap(
230 std::make_shared<CallbackLogImplementation>([](const LogMessage &) {}));
231 ASSERT_NE(curr_impl, GetImplementation().get());
Tyler Chatow67ddb032020-01-12 14:30:04 -0800232 }
233
Austin Schuha0c41ba2020-09-10 22:59:14 -0700234 ASSERT_EQ(curr_impl, GetImplementation().get());
Tyler Chatow67ddb032020-01-12 14:30:04 -0800235}
236
Brian Silvermanf665d692013-02-17 22:11:39 -0800237} // namespace testing
238} // namespace logging
239} // namespace aos