blob: 3b3c79545f990d4f929e77d4a9a0f6def3bdb9e2 [file] [log] [blame]
Tom Cherryfbe79422020-05-14 22:28:09 -07001/*
Tom Cherry6bc6f492020-05-21 12:13:20 -07002 * Copyright (C) 2020 The Android Open Source Project
Tom Cherryfbe79422020-05-14 22:28:09 -07003 *
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
Tom Cherry6bc6f492020-05-21 12:13:20 -070017#include "LogBufferTest.h"
Tom Cherryfbe79422020-05-14 22:28:09 -070018
19#include <unistd.h>
20
Tom Cherry0f7ec302020-11-13 10:52:35 -080021#include <chrono>
Tom Cherry9f3eb612020-05-20 12:09:22 -070022#include <limits>
Tom Cherryfbe79422020-05-14 22:28:09 -070023#include <memory>
Tom Cherry9f3eb612020-05-20 12:09:22 -070024#include <regex>
Tom Cherryfbe79422020-05-14 22:28:09 -070025#include <vector>
26
27#include <android-base/stringprintf.h>
28#include <android-base/strings.h>
Tom Cherryfbe79422020-05-14 22:28:09 -070029
Tom Cherry7a557f42020-06-11 14:06:58 -070030#include "LogBuffer.h"
Tom Cherryfbe79422020-05-14 22:28:09 -070031#include "LogReaderThread.h"
Tom Cherryfbe79422020-05-14 22:28:09 -070032#include "LogWriter.h"
33
34using android::base::Join;
Tom Cherry9f3eb612020-05-20 12:09:22 -070035using android::base::Split;
Tom Cherryfbe79422020-05-14 22:28:09 -070036using android::base::StringPrintf;
Tom Cherry0f7ec302020-11-13 10:52:35 -080037using namespace std::chrono_literals;
Tom Cherryfbe79422020-05-14 22:28:09 -070038
Tom Cherryfbe79422020-05-14 22:28:09 -070039char* android::uidToName(uid_t) {
40 return nullptr;
41}
42
Tom Cherry6bc6f492020-05-21 12:13:20 -070043static std::vector<std::string> CompareLoggerEntries(const logger_entry& expected,
44 const logger_entry& result, bool ignore_len) {
Tom Cherry9f3eb612020-05-20 12:09:22 -070045 std::vector<std::string> errors;
46 if (!ignore_len && expected.len != result.len) {
47 errors.emplace_back(
48 StringPrintf("len: expected %" PRIu16 " vs %" PRIu16, expected.len, result.len));
49 }
50 if (expected.hdr_size != result.hdr_size) {
51 errors.emplace_back(StringPrintf("hdr_size: %" PRIu16 " vs %" PRIu16, expected.hdr_size,
52 result.hdr_size));
53 }
54 if (expected.pid != result.pid) {
55 errors.emplace_back(
56 StringPrintf("pid: expected %" PRIi32 " vs %" PRIi32, expected.pid, result.pid));
57 }
58 if (expected.tid != result.tid) {
59 errors.emplace_back(
60 StringPrintf("tid: expected %" PRIu32 " vs %" PRIu32, expected.tid, result.tid));
61 }
62 if (expected.sec != result.sec) {
63 errors.emplace_back(
64 StringPrintf("sec: expected %" PRIu32 " vs %" PRIu32, expected.sec, result.sec));
65 }
66 if (expected.nsec != result.nsec) {
67 errors.emplace_back(
68 StringPrintf("nsec: expected %" PRIu32 " vs %" PRIu32, expected.nsec, result.nsec));
69 }
70 if (expected.lid != result.lid) {
71 errors.emplace_back(
72 StringPrintf("lid: expected %" PRIu32 " vs %" PRIu32, expected.lid, result.lid));
73 }
74 if (expected.uid != result.uid) {
75 errors.emplace_back(
76 StringPrintf("uid: expected %" PRIu32 " vs %" PRIu32, expected.uid, result.uid));
77 }
78 return errors;
79}
80
Tom Cherry6bc6f492020-05-21 12:13:20 -070081static std::string MakePrintable(std::string in) {
Tom Cherry9f3eb612020-05-20 12:09:22 -070082 if (in.size() > 80) {
83 in = in.substr(0, 80) + "...";
84 }
85 std::string result;
86 for (const char c : in) {
87 if (isprint(c)) {
88 result.push_back(c);
89 } else {
90 result.append(StringPrintf("\\%02x", static_cast<int>(c) & 0xFF));
91 }
92 }
93 return result;
94}
95
Tom Cherry6bc6f492020-05-21 12:13:20 -070096static std::string CompareMessages(const std::string& expected, const std::string& result) {
Tom Cherry9f3eb612020-05-20 12:09:22 -070097 if (expected == result) {
98 return {};
99 }
100 size_t diff_index = 0;
101 for (; diff_index < std::min(expected.size(), result.size()); ++diff_index) {
102 if (expected[diff_index] != result[diff_index]) {
103 break;
104 }
105 }
106
Tom Cherryca4b25d2020-05-28 20:02:42 -0700107 if (diff_index < 80) {
Tom Cherry9f3eb612020-05-20 12:09:22 -0700108 auto expected_short = MakePrintable(expected);
109 auto result_short = MakePrintable(result);
110 return StringPrintf("msg: expected '%s' vs '%s'", expected_short.c_str(),
111 result_short.c_str());
112 }
113
114 auto expected_short = MakePrintable(expected.substr(diff_index));
115 auto result_short = MakePrintable(result.substr(diff_index));
116 return StringPrintf("msg: index %zu: expected '%s' vs '%s'", diff_index, expected_short.c_str(),
117 result_short.c_str());
118}
119
Tom Cherry6bc6f492020-05-21 12:13:20 -0700120static std::string CompareRegexMessages(const std::string& expected, const std::string& result) {
Tom Cherry9f3eb612020-05-20 12:09:22 -0700121 auto expected_pieces = Split(expected, std::string("\0", 1));
122 auto result_pieces = Split(result, std::string("\0", 1));
123
124 if (expected_pieces.size() != 3 || result_pieces.size() != 3) {
125 return StringPrintf(
126 "msg: should have 3 null delimited strings found %d in expected, %d in result: "
127 "'%s' vs '%s'",
128 static_cast<int>(expected_pieces.size()), static_cast<int>(result_pieces.size()),
129 MakePrintable(expected).c_str(), MakePrintable(result).c_str());
130 }
131 if (expected_pieces[0] != result_pieces[0]) {
132 return StringPrintf("msg: tag/priority mismatch expected '%s' vs '%s'",
133 MakePrintable(expected_pieces[0]).c_str(),
134 MakePrintable(result_pieces[0]).c_str());
135 }
136 std::regex expected_tag_regex(expected_pieces[1]);
137 if (!std::regex_search(result_pieces[1], expected_tag_regex)) {
138 return StringPrintf("msg: message regex mismatch expected '%s' vs '%s'",
139 MakePrintable(expected_pieces[1]).c_str(),
140 MakePrintable(result_pieces[1]).c_str());
141 }
142 if (expected_pieces[2] != result_pieces[2]) {
143 return StringPrintf("msg: nothing expected after final null character '%s' vs '%s'",
144 MakePrintable(expected_pieces[2]).c_str(),
145 MakePrintable(result_pieces[2]).c_str());
146 }
147 return {};
148}
149
150void CompareLogMessages(const std::vector<LogMessage>& expected,
151 const std::vector<LogMessage>& result) {
152 EXPECT_EQ(expected.size(), result.size());
153 size_t end = std::min(expected.size(), result.size());
154 size_t num_errors = 0;
155 for (size_t i = 0; i < end; ++i) {
156 auto errors =
157 CompareLoggerEntries(expected[i].entry, result[i].entry, expected[i].regex_compare);
158 auto msg_error = expected[i].regex_compare
159 ? CompareRegexMessages(expected[i].message, result[i].message)
160 : CompareMessages(expected[i].message, result[i].message);
161 if (!msg_error.empty()) {
162 errors.emplace_back(msg_error);
163 }
164 if (!errors.empty()) {
165 GTEST_LOG_(ERROR) << "Mismatch log message " << i << "\n" << Join(errors, "\n");
166 ++num_errors;
167 }
168 }
169 EXPECT_EQ(0U, num_errors);
170}
171
Tom Cherry6bc6f492020-05-21 12:13:20 -0700172void FixupMessages(std::vector<LogMessage>* messages) {
173 for (auto& [entry, message, _] : *messages) {
174 entry.hdr_size = sizeof(logger_entry);
175 entry.len = message.size();
Tom Cherryfbe79422020-05-14 22:28:09 -0700176 }
Tom Cherry6bc6f492020-05-21 12:13:20 -0700177}
Tom Cherryfbe79422020-05-14 22:28:09 -0700178
Tom Cherry6bc6f492020-05-21 12:13:20 -0700179TEST_P(LogBufferTest, smoke) {
Tom Cherry9f3eb612020-05-20 12:09:22 -0700180 std::vector<LogMessage> log_messages = {
Tom Cherryfbe79422020-05-14 22:28:09 -0700181 {{
182 .pid = 1,
183 .tid = 1,
184 .sec = 1234,
185 .nsec = 323001,
186 .lid = LOG_ID_MAIN,
187 .uid = 0,
188 },
189 "smoke test"},
190 };
191 FixupMessages(&log_messages);
192 LogMessages(log_messages);
193
Tom Cherry9f3eb612020-05-20 12:09:22 -0700194 std::vector<LogMessage> read_log_messages;
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700195 {
196 auto lock = std::lock_guard{logd_lock};
197 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
198 std::unique_ptr<FlushToState> flush_to_state =
199 log_buffer_->CreateFlushToState(1, kLogMaskAll);
200 EXPECT_TRUE(log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr));
201 EXPECT_EQ(2ULL, flush_to_state->start());
202 }
Tom Cherryfbe79422020-05-14 22:28:09 -0700203 CompareLogMessages(log_messages, read_log_messages);
204}
205
Tom Cherry6bc6f492020-05-21 12:13:20 -0700206TEST_P(LogBufferTest, smoke_with_reader_thread) {
Tom Cherry9f3eb612020-05-20 12:09:22 -0700207 std::vector<LogMessage> log_messages = {
Tom Cherryfbe79422020-05-14 22:28:09 -0700208 {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0},
209 "first"},
210 {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20002, .lid = LOG_ID_MAIN, .uid = 0},
211 "second"},
212 {{.pid = 100, .tid = 2, .sec = 10000, .nsec = 20003, .lid = LOG_ID_KERNEL, .uid = 0},
213 "third"},
214 {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20004, .lid = LOG_ID_MAIN, .uid = 0},
215 "fourth"},
216 {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20005, .lid = LOG_ID_RADIO, .uid = 0},
217 "fifth"},
218 {{.pid = 2, .tid = 2, .sec = 10000, .nsec = 20006, .lid = LOG_ID_RADIO, .uid = 0},
219 "sixth"},
220 {{.pid = 3, .tid = 2, .sec = 10000, .nsec = 20007, .lid = LOG_ID_RADIO, .uid = 0},
221 "seventh"},
222 {{.pid = 4, .tid = 2, .sec = 10000, .nsec = 20008, .lid = LOG_ID_MAIN, .uid = 0},
223 "eighth"},
224 {{.pid = 5, .tid = 2, .sec = 10000, .nsec = 20009, .lid = LOG_ID_CRASH, .uid = 0},
225 "nineth"},
226 {{.pid = 6, .tid = 2, .sec = 10000, .nsec = 20011, .lid = LOG_ID_MAIN, .uid = 0},
227 "tenth"},
228 };
229 FixupMessages(&log_messages);
230 LogMessages(log_messages);
231
Tom Cherry9f3eb612020-05-20 12:09:22 -0700232 std::vector<LogMessage> read_log_messages;
Tom Cherryfbe79422020-05-14 22:28:09 -0700233 bool released = false;
234
235 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700236 auto lock = std::lock_guard{logd_lock};
Tom Cherryfbe79422020-05-14 22:28:09 -0700237 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
238 std::unique_ptr<LogReaderThread> log_reader(
239 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
Tom Cherry7a557f42020-06-11 14:06:58 -0700240 0, kLogMaskAll, 0, {}, 1, {}));
Tom Cherryfbe79422020-05-14 22:28:09 -0700241 reader_list_.reader_threads().emplace_back(std::move(log_reader));
242 }
243
244 while (!released) {
245 usleep(5000);
246 }
247 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700248 auto lock = std::lock_guard{logd_lock};
Tom Cherryfbe79422020-05-14 22:28:09 -0700249 EXPECT_EQ(0U, reader_list_.reader_threads().size());
250 }
251 CompareLogMessages(log_messages, read_log_messages);
252}
253
254// Generate random messages, set the 'sec' parameter explicit though, to be able to track the
255// expected order of messages.
Tom Cherry9f3eb612020-05-20 12:09:22 -0700256LogMessage GenerateRandomLogMessage(uint32_t sec) {
Tom Cherryfbe79422020-05-14 22:28:09 -0700257 auto rand_uint32 = [](int max) -> uint32_t { return rand() % max; };
258 logger_entry entry = {
259 .hdr_size = sizeof(logger_entry),
260 .pid = rand() % 5000,
261 .tid = rand_uint32(5000),
262 .sec = sec,
263 .nsec = rand_uint32(NS_PER_SEC),
264 .lid = rand_uint32(LOG_ID_STATS),
265 .uid = rand_uint32(100000),
266 };
267
268 // See comment in ChattyLogBuffer::Log() for why this is disallowed.
269 if (entry.nsec % 1000 == 0) {
270 ++entry.nsec;
271 }
272
273 if (entry.lid == LOG_ID_EVENTS) {
274 entry.lid = LOG_ID_KERNEL;
275 }
276
277 std::string message;
278 char priority = ANDROID_LOG_INFO + rand() % 2;
279 message.push_back(priority);
280
281 int tag_length = 2 + rand() % 10;
282 for (int i = 0; i < tag_length; ++i) {
283 message.push_back('a' + rand() % 26);
284 }
285 message.push_back('\0');
286
287 int msg_length = 2 + rand() % 1000;
288 for (int i = 0; i < msg_length; ++i) {
289 message.push_back('a' + rand() % 26);
290 }
291 message.push_back('\0');
292
293 entry.len = message.size();
294
295 return {entry, message};
296}
297
Tom Cherry6bc6f492020-05-21 12:13:20 -0700298TEST_P(LogBufferTest, random_messages) {
Tom Cherryfbe79422020-05-14 22:28:09 -0700299 srand(1);
Tom Cherry9f3eb612020-05-20 12:09:22 -0700300 std::vector<LogMessage> log_messages;
Tom Cherryfbe79422020-05-14 22:28:09 -0700301 for (size_t i = 0; i < 1000; ++i) {
302 log_messages.emplace_back(GenerateRandomLogMessage(i));
303 }
304 LogMessages(log_messages);
305
Tom Cherry9f3eb612020-05-20 12:09:22 -0700306 std::vector<LogMessage> read_log_messages;
Tom Cherryfbe79422020-05-14 22:28:09 -0700307 bool released = false;
308
309 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700310 auto lock = std::lock_guard{logd_lock};
Tom Cherryfbe79422020-05-14 22:28:09 -0700311 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
312 std::unique_ptr<LogReaderThread> log_reader(
313 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
Tom Cherry7a557f42020-06-11 14:06:58 -0700314 0, kLogMaskAll, 0, {}, 1, {}));
Tom Cherryfbe79422020-05-14 22:28:09 -0700315 reader_list_.reader_threads().emplace_back(std::move(log_reader));
316 }
317
318 while (!released) {
319 usleep(5000);
320 }
321 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700322 auto lock = std::lock_guard{logd_lock};
Tom Cherryfbe79422020-05-14 22:28:09 -0700323 EXPECT_EQ(0U, reader_list_.reader_threads().size());
324 }
325 CompareLogMessages(log_messages, read_log_messages);
326}
Tom Cherry9f3eb612020-05-20 12:09:22 -0700327
Tom Cherry33ce9422020-06-01 13:43:50 -0700328TEST_P(LogBufferTest, read_last_sequence) {
329 std::vector<LogMessage> log_messages = {
330 {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0},
331 "first"},
332 {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20002, .lid = LOG_ID_MAIN, .uid = 0},
333 "second"},
334 {{.pid = 100, .tid = 2, .sec = 10000, .nsec = 20003, .lid = LOG_ID_MAIN, .uid = 0},
335 "third"},
336 };
337 FixupMessages(&log_messages);
338 LogMessages(log_messages);
339
340 std::vector<LogMessage> read_log_messages;
341 bool released = false;
342
343 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700344 auto lock = std::lock_guard{logd_lock};
Tom Cherry33ce9422020-06-01 13:43:50 -0700345 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
346 std::unique_ptr<LogReaderThread> log_reader(
347 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
Tom Cherry7a557f42020-06-11 14:06:58 -0700348 0, kLogMaskAll, 0, {}, 3, {}));
Tom Cherry33ce9422020-06-01 13:43:50 -0700349 reader_list_.reader_threads().emplace_back(std::move(log_reader));
350 }
351
352 while (!released) {
353 usleep(5000);
354 }
355 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700356 auto lock = std::lock_guard{logd_lock};
Tom Cherry33ce9422020-06-01 13:43:50 -0700357 EXPECT_EQ(0U, reader_list_.reader_threads().size());
358 }
359 std::vector<LogMessage> expected_log_messages = {log_messages.back()};
360 CompareLogMessages(expected_log_messages, read_log_messages);
361}
362
Tom Cherry7a557f42020-06-11 14:06:58 -0700363TEST_P(LogBufferTest, clear_logs) {
364 // Log 3 initial logs.
365 std::vector<LogMessage> log_messages = {
366 {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0},
367 "first"},
368 {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20002, .lid = LOG_ID_MAIN, .uid = 0},
369 "second"},
370 {{.pid = 100, .tid = 2, .sec = 10000, .nsec = 20003, .lid = LOG_ID_MAIN, .uid = 0},
371 "third"},
372 };
373 FixupMessages(&log_messages);
374 LogMessages(log_messages);
375
376 std::vector<LogMessage> read_log_messages;
377 bool released = false;
378
379 // Connect a blocking reader.
380 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700381 auto lock = std::lock_guard{logd_lock};
Tom Cherry7a557f42020-06-11 14:06:58 -0700382 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
383 std::unique_ptr<LogReaderThread> log_reader(
384 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), false,
385 0, kLogMaskAll, 0, {}, 1, {}));
386 reader_list_.reader_threads().emplace_back(std::move(log_reader));
387 }
388
389 // Wait up to 250ms for the reader to read the first 3 logs.
390 constexpr int kMaxRetryCount = 50;
391 int count = 0;
392 for (; count < kMaxRetryCount; ++count) {
393 usleep(5000);
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700394 auto lock = std::lock_guard{logd_lock};
Tom Cherry7a557f42020-06-11 14:06:58 -0700395 if (reader_list_.reader_threads().back()->start() == 4) {
396 break;
397 }
398 }
399 ASSERT_LT(count, kMaxRetryCount);
400
401 // Clear the log buffer.
402 log_buffer_->Clear(LOG_ID_MAIN, 0);
403
404 // Log 3 more logs.
405 std::vector<LogMessage> after_clear_messages = {
406 {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0},
407 "4th"},
408 {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20002, .lid = LOG_ID_MAIN, .uid = 0},
409 "5th"},
410 {{.pid = 100, .tid = 2, .sec = 10000, .nsec = 20003, .lid = LOG_ID_MAIN, .uid = 0},
411 "6th"},
412 };
413 FixupMessages(&after_clear_messages);
414 LogMessages(after_clear_messages);
415
416 // Wait up to 250ms for the reader to read the 3 additional logs.
417 for (count = 0; count < kMaxRetryCount; ++count) {
418 usleep(5000);
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700419 auto lock = std::lock_guard{logd_lock};
Tom Cherry7a557f42020-06-11 14:06:58 -0700420 if (reader_list_.reader_threads().back()->start() == 7) {
421 break;
422 }
423 }
424 ASSERT_LT(count, kMaxRetryCount);
425
426 // Release the reader, wait for it to get the signal then check that it has been deleted.
427 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700428 auto lock = std::lock_guard{logd_lock};
429 reader_list_.reader_threads().back()->Release();
Tom Cherry7a557f42020-06-11 14:06:58 -0700430 }
431 while (!released) {
432 usleep(5000);
433 }
434 {
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700435 auto lock = std::lock_guard{logd_lock};
Tom Cherry7a557f42020-06-11 14:06:58 -0700436 EXPECT_EQ(0U, reader_list_.reader_threads().size());
437 }
438
439 // Check that we have read all 6 messages.
440 std::vector<LogMessage> expected_log_messages = log_messages;
441 expected_log_messages.insert(expected_log_messages.end(), after_clear_messages.begin(),
442 after_clear_messages.end());
443 CompareLogMessages(expected_log_messages, read_log_messages);
444
445 // Finally, call FlushTo and ensure that only the 3 logs after the clear remain in the buffer.
446 std::vector<LogMessage> read_log_messages_after_clear;
Tom Cherryc5c9eba2020-10-06 10:22:35 -0700447 {
448 auto lock = std::lock_guard{logd_lock};
449 std::unique_ptr<LogWriter> test_writer(
450 new TestWriter(&read_log_messages_after_clear, nullptr));
451 std::unique_ptr<FlushToState> flush_to_state =
452 log_buffer_->CreateFlushToState(1, kLogMaskAll);
453 EXPECT_TRUE(log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr));
454 EXPECT_EQ(7ULL, flush_to_state->start());
455 }
Tom Cherry7a557f42020-06-11 14:06:58 -0700456 CompareLogMessages(after_clear_messages, read_log_messages_after_clear);
457}
458
Tom Cherry0f7ec302020-11-13 10:52:35 -0800459TEST_P(LogBufferTest, tail100_nonblocking_1000total) {
460 LogMessage message = {
461 {.pid = 1, .tid = 2, .sec = 0, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0}, "message"};
462 std::vector<LogMessage> log_messages;
463 for (int i = 0; i < 1000; ++i) {
464 log_messages.push_back(message);
465 log_messages.back().entry.sec = i;
466 log_messages.back().entry.pid = i; // Chatty dedupes these messages if they're identical.
467 }
468 FixupMessages(&log_messages);
469 LogMessages(log_messages);
470
471 std::vector<LogMessage> read_log_messages;
472 bool released = false;
473
474 constexpr int kTailCount = 100;
475 {
476 auto lock = std::lock_guard{logd_lock};
477 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
478 std::unique_ptr<LogReaderThread> log_reader(
479 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
480 kTailCount, kLogMaskAll, 0, {}, 1, {}));
481 reader_list_.reader_threads().emplace_back(std::move(log_reader));
482 }
483
484 while (!released) {
485 usleep(5000);
486 }
487 {
488 auto lock = std::lock_guard{logd_lock};
489 EXPECT_EQ(0U, reader_list_.reader_threads().size());
490 }
491 std::vector<LogMessage> expected_log_messages{log_messages.end() - kTailCount,
492 log_messages.end()};
493 CompareLogMessages(expected_log_messages, read_log_messages);
494}
495
496TEST_P(LogBufferTest, tail100_blocking_1000total_then1000more) {
497 LogMessage message = {
498 {.pid = 1, .tid = 2, .sec = 0, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0}, "message"};
499 std::vector<LogMessage> log_messages;
500 for (int i = 0; i < 1000; ++i) {
501 log_messages.push_back(message);
502 log_messages.back().entry.sec = i;
503 log_messages.back().entry.pid = i; // Chatty dedupes these messages if they're identical.
504 }
505 FixupMessages(&log_messages);
506 LogMessages(log_messages);
507
508 std::vector<LogMessage> read_log_messages;
509 bool released = false;
510
511 constexpr int kTailCount = 100;
512 {
513 auto lock = std::lock_guard{logd_lock};
514 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
515 std::unique_ptr<LogReaderThread> log_reader(
516 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), false,
517 kTailCount, kLogMaskAll, 0, {}, 1, {}));
518 reader_list_.reader_threads().emplace_back(std::move(log_reader));
519 }
520
521 std::vector<LogMessage> expected_log_messages{log_messages.end() - kTailCount,
522 log_messages.end()};
523
524 // Wait for the reader to have read the messages.
525 int retry_count = 1s / 5000us;
526 while (retry_count--) {
527 usleep(5000);
528 auto lock = std::lock_guard{logd_lock};
529 if (read_log_messages.size() == expected_log_messages.size()) {
530 CompareLogMessages(expected_log_messages, read_log_messages);
531 break;
532 }
533 }
534 ASSERT_GT(retry_count, 0);
535
536 // Log more messages
537 for (auto& message : log_messages) {
538 message.entry.sec += 10000;
539 }
540 FixupMessages(&log_messages);
541 LogMessages(log_messages);
542 expected_log_messages.insert(expected_log_messages.end(), log_messages.begin(),
543 log_messages.end());
544
545 // Wait for the reader to have read the new messages.
546 retry_count = 1s / 5000us;
547 while (retry_count--) {
548 usleep(5000);
549 auto lock = std::lock_guard{logd_lock};
550 if (read_log_messages.size() == expected_log_messages.size()) {
551 CompareLogMessages(expected_log_messages, read_log_messages);
552 break;
553 }
554 }
555 ASSERT_GT(retry_count, 0);
556
557 // Release the reader.
558 {
559 auto lock = std::lock_guard{logd_lock};
560 reader_list_.reader_threads().back()->Release();
561 }
562
563 // Confirm that it has exited.
564 while (!released) {
565 usleep(5000);
566 }
567 {
568 auto lock = std::lock_guard{logd_lock};
569 EXPECT_EQ(0U, reader_list_.reader_threads().size());
570 }
571
572 // Final check that no extraneous logs were logged.
573 CompareLogMessages(expected_log_messages, read_log_messages);
574}
575
576TEST_P(LogBufferTest, tail100_nonblocking_50total) {
577 LogMessage message = {
578 {.pid = 1, .tid = 2, .sec = 0, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0}, "message"};
579 std::vector<LogMessage> log_messages;
580 for (int i = 0; i < 50; ++i) {
581 log_messages.push_back(message);
582 log_messages.back().entry.sec = i;
583 log_messages.back().entry.pid = i; // Chatty dedupes these messages if they're identical.
584 }
585 FixupMessages(&log_messages);
586 LogMessages(log_messages);
587
588 std::vector<LogMessage> read_log_messages;
589 bool released = false;
590
591 constexpr int kTailCount = 100;
592 {
593 auto lock = std::lock_guard{logd_lock};
594 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
595 std::unique_ptr<LogReaderThread> log_reader(
596 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
597 kTailCount, kLogMaskAll, 0, {}, 1, {}));
598 reader_list_.reader_threads().emplace_back(std::move(log_reader));
599 }
600
601 while (!released) {
602 usleep(5000);
603 }
604 {
605 auto lock = std::lock_guard{logd_lock};
606 EXPECT_EQ(0U, reader_list_.reader_threads().size());
607 }
608 CompareLogMessages(log_messages, read_log_messages);
609}
610
611TEST_P(LogBufferTest, tail100_blocking_50total_then1000more) {
612 LogMessage message = {
613 {.pid = 1, .tid = 2, .sec = 0, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0}, "message"};
614 std::vector<LogMessage> log_messages;
615 for (int i = 0; i < 50; ++i) {
616 log_messages.push_back(message);
617 log_messages.back().entry.sec = i;
618 log_messages.back().entry.pid = i; // Chatty dedupes these messages if they're identical.
619 }
620 FixupMessages(&log_messages);
621 LogMessages(log_messages);
622
623 std::vector<LogMessage> read_log_messages;
624 bool released = false;
625
626 constexpr int kTailCount = 100;
627 {
628 auto lock = std::lock_guard{logd_lock};
629 std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
630 std::unique_ptr<LogReaderThread> log_reader(
631 new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), false,
632 kTailCount, kLogMaskAll, 0, {}, 1, {}));
633 reader_list_.reader_threads().emplace_back(std::move(log_reader));
634 }
635
636 std::vector<LogMessage> expected_log_messages = log_messages;
637
638 // Wait for the reader to have read the messages.
639 int retry_count = 1s / 5000us;
640 while (retry_count--) {
641 usleep(5000);
642 auto lock = std::lock_guard{logd_lock};
643 if (read_log_messages.size() == expected_log_messages.size()) {
644 CompareLogMessages(expected_log_messages, read_log_messages);
645 break;
646 }
647 }
648 ASSERT_GT(retry_count, 0);
649
650 // Log more messages
651 for (auto& message : log_messages) {
652 message.entry.sec += 10000;
653 }
654 FixupMessages(&log_messages);
655 LogMessages(log_messages);
656 expected_log_messages.insert(expected_log_messages.end(), log_messages.begin(),
657 log_messages.end());
658
659 // Wait for the reader to have read the new messages.
660 retry_count = 1s / 5000us;
661 while (retry_count--) {
662 usleep(5000);
663 auto lock = std::lock_guard{logd_lock};
664 if (read_log_messages.size() == expected_log_messages.size()) {
665 CompareLogMessages(expected_log_messages, read_log_messages);
666 break;
667 }
668 }
669 ASSERT_GT(retry_count, 0);
670
671 // Release the reader.
672 {
673 auto lock = std::lock_guard{logd_lock};
674 reader_list_.reader_threads().back()->Release();
675 }
676
677 // Confirm that it has exited.
678 while (!released) {
679 usleep(5000);
680 }
681 {
682 auto lock = std::lock_guard{logd_lock};
683 EXPECT_EQ(0U, reader_list_.reader_threads().size());
684 }
685
686 // Final check that no extraneous logs were logged.
687 CompareLogMessages(expected_log_messages, read_log_messages);
688}
689
Tom Cherryfb150dd2020-05-13 09:28:37 -0700690INSTANTIATE_TEST_CASE_P(LogBufferTests, LogBufferTest,
691 testing::Values("chatty", "serialized", "simple"));