blob: b52ce8f634597c87b496e165b556962434bedc3a [file] [log] [blame]
Tom Cherry43f3f762020-05-14 22:28:09 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "LogBuffer.h"
18
19#include <unistd.h>
20
Tom Cherryb398a7c2020-05-20 12:09:22 -070021#include <limits>
Tom Cherry43f3f762020-05-14 22:28:09 -070022#include <memory>
Tom Cherryb398a7c2020-05-20 12:09:22 -070023#include <regex>
Tom Cherry43f3f762020-05-14 22:28:09 -070024#include <vector>
25
26#include <android-base/stringprintf.h>
27#include <android-base/strings.h>
28#include <gtest/gtest.h>
29
30#include "ChattyLogBuffer.h"
31#include "LogReaderList.h"
32#include "LogReaderThread.h"
33#include "LogStatistics.h"
34#include "LogTags.h"
35#include "LogWhiteBlackList.h"
36#include "LogWriter.h"
37
38using android::base::Join;
Tom Cherryb398a7c2020-05-20 12:09:22 -070039using android::base::Split;
Tom Cherry43f3f762020-05-14 22:28:09 -070040using android::base::StringPrintf;
41
Tom Cherrya5151972020-05-15 11:39:58 -070042#ifndef __ANDROID__
43unsigned long __android_logger_get_buffer_size(log_id_t) {
44 return 1024 * 1024;
45}
46
47bool __android_logger_valid_buffer_size(unsigned long) {
48 return true;
49}
50#endif
51
Tom Cherry43f3f762020-05-14 22:28:09 -070052void android::prdebug(const char* fmt, ...) {
53 va_list ap;
54 va_start(ap, fmt);
55 vfprintf(stderr, fmt, ap);
56 fprintf(stderr, "\n");
57 va_end(ap);
58}
59
60char* android::uidToName(uid_t) {
61 return nullptr;
62}
63
Tom Cherryb398a7c2020-05-20 12:09:22 -070064struct LogMessage {
65 logger_entry entry;
66 std::string message;
67 bool regex_compare = false; // Only set for expected messages, when true 'message' should be
68 // interpretted as a regex.
69};
70
71std::vector<std::string> CompareLoggerEntries(const logger_entry& expected,
72 const logger_entry& result, bool ignore_len) {
73 std::vector<std::string> errors;
74 if (!ignore_len && expected.len != result.len) {
75 errors.emplace_back(
76 StringPrintf("len: expected %" PRIu16 " vs %" PRIu16, expected.len, result.len));
77 }
78 if (expected.hdr_size != result.hdr_size) {
79 errors.emplace_back(StringPrintf("hdr_size: %" PRIu16 " vs %" PRIu16, expected.hdr_size,
80 result.hdr_size));
81 }
82 if (expected.pid != result.pid) {
83 errors.emplace_back(
84 StringPrintf("pid: expected %" PRIi32 " vs %" PRIi32, expected.pid, result.pid));
85 }
86 if (expected.tid != result.tid) {
87 errors.emplace_back(
88 StringPrintf("tid: expected %" PRIu32 " vs %" PRIu32, expected.tid, result.tid));
89 }
90 if (expected.sec != result.sec) {
91 errors.emplace_back(
92 StringPrintf("sec: expected %" PRIu32 " vs %" PRIu32, expected.sec, result.sec));
93 }
94 if (expected.nsec != result.nsec) {
95 errors.emplace_back(
96 StringPrintf("nsec: expected %" PRIu32 " vs %" PRIu32, expected.nsec, result.nsec));
97 }
98 if (expected.lid != result.lid) {
99 errors.emplace_back(
100 StringPrintf("lid: expected %" PRIu32 " vs %" PRIu32, expected.lid, result.lid));
101 }
102 if (expected.uid != result.uid) {
103 errors.emplace_back(
104 StringPrintf("uid: expected %" PRIu32 " vs %" PRIu32, expected.uid, result.uid));
105 }
106 return errors;
107}
108
109std::string MakePrintable(std::string in) {
110 if (in.size() > 80) {
111 in = in.substr(0, 80) + "...";
112 }
113 std::string result;
114 for (const char c : in) {
115 if (isprint(c)) {
116 result.push_back(c);
117 } else {
118 result.append(StringPrintf("\\%02x", static_cast<int>(c) & 0xFF));
119 }
120 }
121 return result;
122}
123
124std::string CompareMessages(const std::string& expected, const std::string& result) {
125 if (expected == result) {
126 return {};
127 }
128 size_t diff_index = 0;
129 for (; diff_index < std::min(expected.size(), result.size()); ++diff_index) {
130 if (expected[diff_index] != result[diff_index]) {
131 break;
132 }
133 }
134
135 if (diff_index < 10) {
136 auto expected_short = MakePrintable(expected);
137 auto result_short = MakePrintable(result);
138 return StringPrintf("msg: expected '%s' vs '%s'", expected_short.c_str(),
139 result_short.c_str());
140 }
141
142 auto expected_short = MakePrintable(expected.substr(diff_index));
143 auto result_short = MakePrintable(result.substr(diff_index));
144 return StringPrintf("msg: index %zu: expected '%s' vs '%s'", diff_index, expected_short.c_str(),
145 result_short.c_str());
146}
147
148std::string CompareRegexMessages(const std::string& expected, const std::string& result) {
149 auto expected_pieces = Split(expected, std::string("\0", 1));
150 auto result_pieces = Split(result, std::string("\0", 1));
151
152 if (expected_pieces.size() != 3 || result_pieces.size() != 3) {
153 return StringPrintf(
154 "msg: should have 3 null delimited strings found %d in expected, %d in result: "
155 "'%s' vs '%s'",
156 static_cast<int>(expected_pieces.size()), static_cast<int>(result_pieces.size()),
157 MakePrintable(expected).c_str(), MakePrintable(result).c_str());
158 }
159 if (expected_pieces[0] != result_pieces[0]) {
160 return StringPrintf("msg: tag/priority mismatch expected '%s' vs '%s'",
161 MakePrintable(expected_pieces[0]).c_str(),
162 MakePrintable(result_pieces[0]).c_str());
163 }
164 std::regex expected_tag_regex(expected_pieces[1]);
165 if (!std::regex_search(result_pieces[1], expected_tag_regex)) {
166 return StringPrintf("msg: message regex mismatch expected '%s' vs '%s'",
167 MakePrintable(expected_pieces[1]).c_str(),
168 MakePrintable(result_pieces[1]).c_str());
169 }
170 if (expected_pieces[2] != result_pieces[2]) {
171 return StringPrintf("msg: nothing expected after final null character '%s' vs '%s'",
172 MakePrintable(expected_pieces[2]).c_str(),
173 MakePrintable(result_pieces[2]).c_str());
174 }
175 return {};
176}
177
178void CompareLogMessages(const std::vector<LogMessage>& expected,
179 const std::vector<LogMessage>& result) {
180 EXPECT_EQ(expected.size(), result.size());
181 size_t end = std::min(expected.size(), result.size());
182 size_t num_errors = 0;
183 for (size_t i = 0; i < end; ++i) {
184 auto errors =
185 CompareLoggerEntries(expected[i].entry, result[i].entry, expected[i].regex_compare);
186 auto msg_error = expected[i].regex_compare
187 ? CompareRegexMessages(expected[i].message, result[i].message)
188 : CompareMessages(expected[i].message, result[i].message);
189 if (!msg_error.empty()) {
190 errors.emplace_back(msg_error);
191 }
192 if (!errors.empty()) {
193 GTEST_LOG_(ERROR) << "Mismatch log message " << i << "\n" << Join(errors, "\n");
194 ++num_errors;
195 }
196 }
197 EXPECT_EQ(0U, num_errors);
198}
199
Tom Cherry43f3f762020-05-14 22:28:09 -0700200class TestWriter : public LogWriter {
201 public:
Tom Cherryb398a7c2020-05-20 12:09:22 -0700202 TestWriter(std::vector<LogMessage>* msgs, bool* released)
Tom Cherry43f3f762020-05-14 22:28:09 -0700203 : LogWriter(0, true, true), msgs_(msgs), released_(released) {}
204 bool Write(const logger_entry& entry, const char* message) override {
Tom Cherryb398a7c2020-05-20 12:09:22 -0700205 msgs_->emplace_back(LogMessage{entry, std::string(message, entry.len), false});
Tom Cherry43f3f762020-05-14 22:28:09 -0700206 return true;
207 }
208
209 void Release() {
210 if (released_) *released_ = true;
211 }
212
213 std::string name() const override { return "test_writer"; }
214
215 private:
Tom Cherryb398a7c2020-05-20 12:09:22 -0700216 std::vector<LogMessage>* msgs_;
Tom Cherry43f3f762020-05-14 22:28:09 -0700217 bool* released_;
218};
219
220class LogBufferTest : public testing::Test {
221 protected:
222 void SetUp() override {
223 log_buffer_.reset(new ChattyLogBuffer(&reader_list_, &tags_, &prune_, &stats_));
224 }
225
Tom Cherryb398a7c2020-05-20 12:09:22 -0700226 void FixupMessages(std::vector<LogMessage>* messages) {
227 for (auto& [entry, message, _] : *messages) {
Tom Cherry43f3f762020-05-14 22:28:09 -0700228 entry.hdr_size = sizeof(logger_entry);
229 entry.len = message.size();
230 }
231 }
232
Tom Cherryb398a7c2020-05-20 12:09:22 -0700233 void LogMessages(const std::vector<LogMessage>& messages) {
234 for (auto& [entry, message, _] : messages) {
Tom Cherry43f3f762020-05-14 22:28:09 -0700235 log_buffer_->Log(static_cast<log_id_t>(entry.lid), log_time(entry.sec, entry.nsec),
236 entry.uid, entry.pid, entry.tid, message.c_str(), message.size());
237 }
238 }
239
Tom Cherry43f3f762020-05-14 22:28:09 -0700240 LogReaderList reader_list_;
241 LogTags tags_;
242 PruneList prune_;
243 LogStatistics stats_{false};
244 std::unique_ptr<LogBuffer> log_buffer_;
245};
246
247TEST_F(LogBufferTest, smoke) {
Tom Cherryb398a7c2020-05-20 12:09:22 -0700248 std::vector<LogMessage> log_messages = {
Tom Cherry43f3f762020-05-14 22:28:09 -0700249 {{
250 .pid = 1,
251 .tid = 1,
252 .sec = 1234,
253 .nsec = 323001,
254 .lid = LOG_ID_MAIN,
255 .uid = 0,
256 },
257 "smoke test"},
258 };
259 FixupMessages(&log_messages);
260 LogMessages(log_messages);
261
Tom Cherryb398a7c2020-05-20 12:09:22 -0700262 std::vector<LogMessage> read_log_messages;
Tom Cherry43f3f762020-05-14 22:28:09 -0700263 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
264 uint64_t flush_result = log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
265 EXPECT_EQ(1ULL, flush_result);
266 CompareLogMessages(log_messages, read_log_messages);
267}
268
269TEST_F(LogBufferTest, smoke_with_reader_thread) {
Tom Cherryb398a7c2020-05-20 12:09:22 -0700270 std::vector<LogMessage> log_messages = {
Tom Cherry43f3f762020-05-14 22:28:09 -0700271 {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0},
272 "first"},
273 {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20002, .lid = LOG_ID_MAIN, .uid = 0},
274 "second"},
275 {{.pid = 100, .tid = 2, .sec = 10000, .nsec = 20003, .lid = LOG_ID_KERNEL, .uid = 0},
276 "third"},
277 {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20004, .lid = LOG_ID_MAIN, .uid = 0},
278 "fourth"},
279 {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20005, .lid = LOG_ID_RADIO, .uid = 0},
280 "fifth"},
281 {{.pid = 2, .tid = 2, .sec = 10000, .nsec = 20006, .lid = LOG_ID_RADIO, .uid = 0},
282 "sixth"},
283 {{.pid = 3, .tid = 2, .sec = 10000, .nsec = 20007, .lid = LOG_ID_RADIO, .uid = 0},
284 "seventh"},
285 {{.pid = 4, .tid = 2, .sec = 10000, .nsec = 20008, .lid = LOG_ID_MAIN, .uid = 0},
286 "eighth"},
287 {{.pid = 5, .tid = 2, .sec = 10000, .nsec = 20009, .lid = LOG_ID_CRASH, .uid = 0},
288 "nineth"},
289 {{.pid = 6, .tid = 2, .sec = 10000, .nsec = 20011, .lid = LOG_ID_MAIN, .uid = 0},
290 "tenth"},
291 };
292 FixupMessages(&log_messages);
293 LogMessages(log_messages);
294
Tom Cherryb398a7c2020-05-20 12:09:22 -0700295 std::vector<LogMessage> read_log_messages;
Tom Cherry43f3f762020-05-14 22:28:09 -0700296 bool released = false;
297
298 {
299 auto lock = std::unique_lock{reader_list_.reader_threads_lock()};
300 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
301 std::unique_ptr<LogReaderThread> log_reader(
302 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
303 0, ~0, 0, {}, 1, {}));
304 reader_list_.reader_threads().emplace_back(std::move(log_reader));
305 }
306
307 while (!released) {
308 usleep(5000);
309 }
310 {
311 auto lock = std::unique_lock{reader_list_.reader_threads_lock()};
312 EXPECT_EQ(0U, reader_list_.reader_threads().size());
313 }
314 CompareLogMessages(log_messages, read_log_messages);
315}
316
317// Generate random messages, set the 'sec' parameter explicit though, to be able to track the
318// expected order of messages.
Tom Cherryb398a7c2020-05-20 12:09:22 -0700319LogMessage GenerateRandomLogMessage(uint32_t sec) {
Tom Cherry43f3f762020-05-14 22:28:09 -0700320 auto rand_uint32 = [](int max) -> uint32_t { return rand() % max; };
321 logger_entry entry = {
322 .hdr_size = sizeof(logger_entry),
323 .pid = rand() % 5000,
324 .tid = rand_uint32(5000),
325 .sec = sec,
326 .nsec = rand_uint32(NS_PER_SEC),
327 .lid = rand_uint32(LOG_ID_STATS),
328 .uid = rand_uint32(100000),
329 };
330
331 // See comment in ChattyLogBuffer::Log() for why this is disallowed.
332 if (entry.nsec % 1000 == 0) {
333 ++entry.nsec;
334 }
335
336 if (entry.lid == LOG_ID_EVENTS) {
337 entry.lid = LOG_ID_KERNEL;
338 }
339
340 std::string message;
341 char priority = ANDROID_LOG_INFO + rand() % 2;
342 message.push_back(priority);
343
344 int tag_length = 2 + rand() % 10;
345 for (int i = 0; i < tag_length; ++i) {
346 message.push_back('a' + rand() % 26);
347 }
348 message.push_back('\0');
349
350 int msg_length = 2 + rand() % 1000;
351 for (int i = 0; i < msg_length; ++i) {
352 message.push_back('a' + rand() % 26);
353 }
354 message.push_back('\0');
355
356 entry.len = message.size();
357
358 return {entry, message};
359}
360
361TEST_F(LogBufferTest, random_messages) {
362 srand(1);
Tom Cherryb398a7c2020-05-20 12:09:22 -0700363 std::vector<LogMessage> log_messages;
Tom Cherry43f3f762020-05-14 22:28:09 -0700364 for (size_t i = 0; i < 1000; ++i) {
365 log_messages.emplace_back(GenerateRandomLogMessage(i));
366 }
367 LogMessages(log_messages);
368
Tom Cherryb398a7c2020-05-20 12:09:22 -0700369 std::vector<LogMessage> read_log_messages;
Tom Cherry43f3f762020-05-14 22:28:09 -0700370 bool released = false;
371
372 {
373 auto lock = std::unique_lock{reader_list_.reader_threads_lock()};
374 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
375 std::unique_ptr<LogReaderThread> log_reader(
376 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
377 0, ~0, 0, {}, 1, {}));
378 reader_list_.reader_threads().emplace_back(std::move(log_reader));
379 }
380
381 while (!released) {
382 usleep(5000);
383 }
384 {
385 auto lock = std::unique_lock{reader_list_.reader_threads_lock()};
386 EXPECT_EQ(0U, reader_list_.reader_threads().size());
387 }
388 CompareLogMessages(log_messages, read_log_messages);
389}
Tom Cherryb398a7c2020-05-20 12:09:22 -0700390
391TEST_F(LogBufferTest, deduplication_simple) {
392 auto make_message = [&](uint32_t sec, const char* tag, const char* msg,
393 bool regex = false) -> LogMessage {
394 logger_entry entry = {
395 .pid = 1, .tid = 1, .sec = sec, .nsec = 1, .lid = LOG_ID_MAIN, .uid = 0};
396 std::string message;
397 message.push_back(ANDROID_LOG_INFO);
398 message.append(tag);
399 message.push_back('\0');
400 message.append(msg);
401 message.push_back('\0');
402 return {entry, message, regex};
403 };
404
405 // clang-format off
406 std::vector<LogMessage> log_messages = {
407 make_message(0, "test_tag", "duplicate"),
408 make_message(1, "test_tag", "duplicate"),
409 make_message(2, "test_tag", "not_same"),
410 make_message(3, "test_tag", "duplicate"),
411 make_message(4, "test_tag", "duplicate"),
412 make_message(5, "test_tag", "not_same"),
413 make_message(6, "test_tag", "duplicate"),
414 make_message(7, "test_tag", "duplicate"),
415 make_message(8, "test_tag", "duplicate"),
416 make_message(9, "test_tag", "not_same"),
417 make_message(10, "test_tag", "duplicate"),
418 make_message(11, "test_tag", "duplicate"),
419 make_message(12, "test_tag", "duplicate"),
420 make_message(13, "test_tag", "duplicate"),
421 make_message(14, "test_tag", "duplicate"),
422 make_message(15, "test_tag", "duplicate"),
423 make_message(16, "test_tag", "not_same"),
424 make_message(100, "test_tag", "duplicate"),
425 make_message(200, "test_tag", "duplicate"),
426 make_message(300, "test_tag", "duplicate"),
427 };
428 // clang-format on
429 FixupMessages(&log_messages);
430 LogMessages(log_messages);
431
432 std::vector<LogMessage> read_log_messages;
433 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
434 log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
435
436 std::vector<LogMessage> expected_log_messages = {
437 make_message(0, "test_tag", "duplicate"),
438 make_message(1, "test_tag", "duplicate"),
439 make_message(2, "test_tag", "not_same"),
440 make_message(3, "test_tag", "duplicate"),
441 make_message(4, "test_tag", "duplicate"),
442 make_message(5, "test_tag", "not_same"),
443 // 3 duplicate logs together print the first, a 1 count chatty message, then the last.
444 make_message(6, "test_tag", "duplicate"),
445 make_message(7, "chatty", "uid=0\\([^\\)]+\\) [^ ]+ expire 1 line", true),
446 make_message(8, "test_tag", "duplicate"),
447 make_message(9, "test_tag", "not_same"),
448 // 6 duplicate logs together print the first, a 4 count chatty message, then the last.
449 make_message(10, "test_tag", "duplicate"),
450 make_message(14, "chatty", "uid=0\\([^\\)]+\\) [^ ]+ expire 4 lines", true),
451 make_message(15, "test_tag", "duplicate"),
452 make_message(16, "test_tag", "not_same"),
453 // duplicate logs > 1 minute apart are not deduplicated.
454 make_message(100, "test_tag", "duplicate"),
455 make_message(200, "test_tag", "duplicate"),
456 make_message(300, "test_tag", "duplicate"),
457 };
458 FixupMessages(&expected_log_messages);
459 CompareLogMessages(expected_log_messages, read_log_messages);
460};
461
462TEST_F(LogBufferTest, deduplication_overflow) {
463 auto make_message = [&](uint32_t sec, const char* tag, const char* msg,
464 bool regex = false) -> LogMessage {
465 logger_entry entry = {
466 .pid = 1, .tid = 1, .sec = sec, .nsec = 1, .lid = LOG_ID_MAIN, .uid = 0};
467 std::string message;
468 message.push_back(ANDROID_LOG_INFO);
469 message.append(tag);
470 message.push_back('\0');
471 message.append(msg);
472 message.push_back('\0');
473 return {entry, message, regex};
474 };
475
476 uint32_t sec = 0;
477 std::vector<LogMessage> log_messages = {
478 make_message(sec++, "test_tag", "normal"),
479 };
480 size_t expired_per_chatty_message = std::numeric_limits<uint16_t>::max();
481 for (size_t i = 0; i < expired_per_chatty_message + 3; ++i) {
482 log_messages.emplace_back(make_message(sec++, "test_tag", "duplicate"));
483 }
484 log_messages.emplace_back(make_message(sec++, "test_tag", "normal"));
485 FixupMessages(&log_messages);
486 LogMessages(log_messages);
487
488 std::vector<LogMessage> read_log_messages;
489 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
490 log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
491
492 std::vector<LogMessage> expected_log_messages = {
493 make_message(0, "test_tag", "normal"),
494 make_message(1, "test_tag", "duplicate"),
495 make_message(expired_per_chatty_message + 1, "chatty",
496 "uid=0\\([^\\)]+\\) [^ ]+ expire 65535 lines", true),
497 make_message(expired_per_chatty_message + 2, "chatty",
498 "uid=0\\([^\\)]+\\) [^ ]+ expire 1 line", true),
499 make_message(expired_per_chatty_message + 3, "test_tag", "duplicate"),
500 make_message(expired_per_chatty_message + 4, "test_tag", "normal"),
501 };
502 FixupMessages(&expected_log_messages);
503 CompareLogMessages(expected_log_messages, read_log_messages);
504}
505
506TEST_F(LogBufferTest, deduplication_liblog) {
507 auto make_message = [&](uint32_t sec, int32_t tag, int32_t count) -> LogMessage {
508 logger_entry entry = {
509 .pid = 1, .tid = 1, .sec = sec, .nsec = 1, .lid = LOG_ID_EVENTS, .uid = 0};
510 android_log_event_int_t liblog_event = {
511 .header.tag = tag, .payload.type = EVENT_TYPE_INT, .payload.data = count};
512 return {entry, std::string(reinterpret_cast<char*>(&liblog_event), sizeof(liblog_event)),
513 false};
514 };
515
516 // LIBLOG_LOG_TAG
517 std::vector<LogMessage> log_messages = {
518 make_message(0, 1234, 1),
519 make_message(1, LIBLOG_LOG_TAG, 3),
520 make_message(2, 1234, 2),
521 make_message(3, LIBLOG_LOG_TAG, 3),
522 make_message(4, LIBLOG_LOG_TAG, 4),
523 make_message(5, 1234, 223),
524 make_message(6, LIBLOG_LOG_TAG, 2),
525 make_message(7, LIBLOG_LOG_TAG, 3),
526 make_message(8, LIBLOG_LOG_TAG, 4),
527 make_message(9, 1234, 227),
528 make_message(10, LIBLOG_LOG_TAG, 1),
529 make_message(11, LIBLOG_LOG_TAG, 3),
530 make_message(12, LIBLOG_LOG_TAG, 2),
531 make_message(13, LIBLOG_LOG_TAG, 3),
532 make_message(14, LIBLOG_LOG_TAG, 5),
533 make_message(15, 1234, 227),
534 make_message(16, LIBLOG_LOG_TAG, 2),
535 make_message(17, LIBLOG_LOG_TAG, std::numeric_limits<int32_t>::max()),
536 make_message(18, LIBLOG_LOG_TAG, 3),
537 make_message(19, LIBLOG_LOG_TAG, 5),
538 make_message(20, 1234, 227),
539 };
540 FixupMessages(&log_messages);
541 LogMessages(log_messages);
542
543 std::vector<LogMessage> read_log_messages;
544 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
545 log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
546
547 std::vector<LogMessage> expected_log_messages = {
548 make_message(0, 1234, 1),
549 make_message(1, LIBLOG_LOG_TAG, 3),
550 make_message(2, 1234, 2),
551 make_message(3, LIBLOG_LOG_TAG, 3),
552 make_message(4, LIBLOG_LOG_TAG, 4),
553 make_message(5, 1234, 223),
554 // More than 2 liblog events (3 here), sum their value into the third message.
555 make_message(6, LIBLOG_LOG_TAG, 2),
556 make_message(8, LIBLOG_LOG_TAG, 7),
557 make_message(9, 1234, 227),
558 // More than 2 liblog events (5 here), sum their value into the third message.
559 make_message(10, LIBLOG_LOG_TAG, 1),
560 make_message(14, LIBLOG_LOG_TAG, 13),
561 make_message(15, 1234, 227),
562 // int32_t max is the max for a chatty message, beyond that we must use new messages.
563 make_message(16, LIBLOG_LOG_TAG, 2),
564 make_message(17, LIBLOG_LOG_TAG, std::numeric_limits<int32_t>::max()),
565 make_message(19, LIBLOG_LOG_TAG, 8),
566 make_message(20, 1234, 227),
567 };
568 FixupMessages(&expected_log_messages);
569 CompareLogMessages(expected_log_messages, read_log_messages);
570};