1*598139dcSAndroid Build Coastguard Worker /* 2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project 3*598139dcSAndroid Build Coastguard Worker * 4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*598139dcSAndroid Build Coastguard Worker * 8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*598139dcSAndroid Build Coastguard Worker * 10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*598139dcSAndroid Build Coastguard Worker * limitations under the License. 15*598139dcSAndroid Build Coastguard Worker */ 16*598139dcSAndroid Build Coastguard Worker 17*598139dcSAndroid Build Coastguard Worker #pragma once 18*598139dcSAndroid Build Coastguard Worker 19*598139dcSAndroid Build Coastguard Worker #include <chrono> 20*598139dcSAndroid Build Coastguard Worker #include <mutex> 21*598139dcSAndroid Build Coastguard Worker #include <string> 22*598139dcSAndroid Build Coastguard Worker #include <vector> 23*598139dcSAndroid Build Coastguard Worker 24*598139dcSAndroid Build Coastguard Worker #include <gtest/gtest.h> 25*598139dcSAndroid Build Coastguard Worker 26*598139dcSAndroid Build Coastguard Worker #include "LogBuffer.h" 27*598139dcSAndroid Build Coastguard Worker #include "LogReaderList.h" 28*598139dcSAndroid Build Coastguard Worker #include "LogStatistics.h" 29*598139dcSAndroid Build Coastguard Worker #include "LogTags.h" 30*598139dcSAndroid Build Coastguard Worker #include "PruneList.h" 31*598139dcSAndroid Build Coastguard Worker #include "SerializedLogBuffer.h" 32*598139dcSAndroid Build Coastguard Worker #include "SimpleLogBuffer.h" 33*598139dcSAndroid Build Coastguard Worker 34*598139dcSAndroid Build Coastguard Worker using namespace std::chrono_literals; 35*598139dcSAndroid Build Coastguard Worker 36*598139dcSAndroid Build Coastguard Worker struct LogMessage { 37*598139dcSAndroid Build Coastguard Worker logger_entry entry; 38*598139dcSAndroid Build Coastguard Worker std::string message; 39*598139dcSAndroid Build Coastguard Worker bool regex_compare = false; // Only set for expected messages, when true 'message' should be 40*598139dcSAndroid Build Coastguard Worker // interpretted as a regex. 41*598139dcSAndroid Build Coastguard Worker }; 42*598139dcSAndroid Build Coastguard Worker 43*598139dcSAndroid Build Coastguard Worker // Compares the ordered list of expected and result, causing a test failure with appropriate 44*598139dcSAndroid Build Coastguard Worker // information on failure. 45*598139dcSAndroid Build Coastguard Worker void CompareLogMessages(const std::vector<LogMessage>& expected, 46*598139dcSAndroid Build Coastguard Worker const std::vector<LogMessage>& result); 47*598139dcSAndroid Build Coastguard Worker // Sets hdr_size and len parameters appropriately. 48*598139dcSAndroid Build Coastguard Worker void FixupMessages(std::vector<LogMessage>* messages); 49*598139dcSAndroid Build Coastguard Worker 50*598139dcSAndroid Build Coastguard Worker class TestWriter : public LogWriter { 51*598139dcSAndroid Build Coastguard Worker public: TestWriter(std::vector<LogMessage> * msgs,std::mutex * mutex,bool * released)52*598139dcSAndroid Build Coastguard Worker TestWriter(std::vector<LogMessage>* msgs, std::mutex* mutex, bool* released) 53*598139dcSAndroid Build Coastguard Worker : LogWriter(0, true), mutex_(mutex ?: &logd_lock), msgs_(msgs), released_(released) {} 54*598139dcSAndroid Build Coastguard Worker Write(const logger_entry & entry,const char * message)55*598139dcSAndroid Build Coastguard Worker bool Write(const logger_entry& entry, const char* message) override { 56*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{*mutex_}; 57*598139dcSAndroid Build Coastguard Worker msgs_->emplace_back(LogMessage{entry, std::string(message, entry.len), false}); 58*598139dcSAndroid Build Coastguard Worker return true; 59*598139dcSAndroid Build Coastguard Worker } 60*598139dcSAndroid Build Coastguard Worker Release()61*598139dcSAndroid Build Coastguard Worker void Release() { 62*598139dcSAndroid Build Coastguard Worker if (released_) *released_ = true; 63*598139dcSAndroid Build Coastguard Worker } 64*598139dcSAndroid Build Coastguard Worker name()65*598139dcSAndroid Build Coastguard Worker std::string name() const override { return "test_writer"; } 66*598139dcSAndroid Build Coastguard Worker 67*598139dcSAndroid Build Coastguard Worker private: 68*598139dcSAndroid Build Coastguard Worker std::mutex* mutex_; 69*598139dcSAndroid Build Coastguard Worker std::vector<LogMessage>* msgs_; 70*598139dcSAndroid Build Coastguard Worker bool* released_; 71*598139dcSAndroid Build Coastguard Worker }; 72*598139dcSAndroid Build Coastguard Worker 73*598139dcSAndroid Build Coastguard Worker class LogBufferTest : public testing::TestWithParam<std::string> { 74*598139dcSAndroid Build Coastguard Worker protected: SetUp()75*598139dcSAndroid Build Coastguard Worker void SetUp() override { 76*598139dcSAndroid Build Coastguard Worker if (GetParam() == "serialized") { 77*598139dcSAndroid Build Coastguard Worker log_buffer_.reset(new SerializedLogBuffer(&reader_list_, &tags_, &stats_)); 78*598139dcSAndroid Build Coastguard Worker } else if (GetParam() == "simple") { 79*598139dcSAndroid Build Coastguard Worker log_buffer_.reset(new SimpleLogBuffer(&reader_list_, &tags_, &stats_)); 80*598139dcSAndroid Build Coastguard Worker } else { 81*598139dcSAndroid Build Coastguard Worker FAIL() << "Unknown buffer type selected for test"; 82*598139dcSAndroid Build Coastguard Worker } 83*598139dcSAndroid Build Coastguard Worker 84*598139dcSAndroid Build Coastguard Worker log_id_for_each(i) { log_buffer_->SetSize(i, 1024 * 1024); } 85*598139dcSAndroid Build Coastguard Worker } 86*598139dcSAndroid Build Coastguard Worker LogMessages(const std::vector<LogMessage> & messages)87*598139dcSAndroid Build Coastguard Worker void LogMessages(const std::vector<LogMessage>& messages) { 88*598139dcSAndroid Build Coastguard Worker for (auto& [entry, message, _] : messages) { 89*598139dcSAndroid Build Coastguard Worker EXPECT_GT(log_buffer_->Log(static_cast<log_id_t>(entry.lid), 90*598139dcSAndroid Build Coastguard Worker log_time(entry.sec, entry.nsec), entry.uid, entry.pid, 91*598139dcSAndroid Build Coastguard Worker entry.tid, message.c_str(), message.size()), 92*598139dcSAndroid Build Coastguard Worker 0); 93*598139dcSAndroid Build Coastguard Worker } 94*598139dcSAndroid Build Coastguard Worker } 95*598139dcSAndroid Build Coastguard Worker 96*598139dcSAndroid Build Coastguard Worker struct FlushMessagesResult { 97*598139dcSAndroid Build Coastguard Worker std::vector<LogMessage> messages; 98*598139dcSAndroid Build Coastguard Worker uint64_t next_sequence; 99*598139dcSAndroid Build Coastguard Worker }; 100*598139dcSAndroid Build Coastguard Worker 101*598139dcSAndroid Build Coastguard Worker FlushMessagesResult FlushMessages(std::mutex* mutex = nullptr) { 102*598139dcSAndroid Build Coastguard Worker std::vector<LogMessage> read_log_messages; 103*598139dcSAndroid Build Coastguard Worker std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, mutex, nullptr)); 104*598139dcSAndroid Build Coastguard Worker 105*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock}; 106*598139dcSAndroid Build Coastguard Worker auto flush_to_state = log_buffer_->CreateFlushToState(1, kLogMaskAll); 107*598139dcSAndroid Build Coastguard Worker EXPECT_TRUE(log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr)); 108*598139dcSAndroid Build Coastguard Worker return {read_log_messages, flush_to_state->start()}; 109*598139dcSAndroid Build Coastguard Worker } 110*598139dcSAndroid Build Coastguard Worker 111*598139dcSAndroid Build Coastguard Worker struct ReaderThreadParams { 112*598139dcSAndroid Build Coastguard Worker bool non_block = true; 113*598139dcSAndroid Build Coastguard Worker unsigned long tail = 0; 114*598139dcSAndroid Build Coastguard Worker LogMask log_mask = kLogMaskAll; 115*598139dcSAndroid Build Coastguard Worker pid_t pid = 0; 116*598139dcSAndroid Build Coastguard Worker log_time start_time = {}; 117*598139dcSAndroid Build Coastguard Worker uint64_t sequence = 1; 118*598139dcSAndroid Build Coastguard Worker std::chrono::steady_clock::time_point deadline = {}; 119*598139dcSAndroid Build Coastguard Worker }; 120*598139dcSAndroid Build Coastguard Worker 121*598139dcSAndroid Build Coastguard Worker class TestReaderThread { 122*598139dcSAndroid Build Coastguard Worker public: TestReaderThread(const ReaderThreadParams & params,LogBufferTest & test)123*598139dcSAndroid Build Coastguard Worker TestReaderThread(const ReaderThreadParams& params, LogBufferTest& test) : test_(test) { 124*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{mutex_}; 125*598139dcSAndroid Build Coastguard Worker std::unique_ptr<LogWriter> test_writer( 126*598139dcSAndroid Build Coastguard Worker new TestWriter(&read_log_messages_, &mutex_, &released_)); 127*598139dcSAndroid Build Coastguard Worker std::unique_ptr<LogReaderThread> log_reader(new LogReaderThread( 128*598139dcSAndroid Build Coastguard Worker test_.log_buffer_.get(), &test_.reader_list_, std::move(test_writer), 129*598139dcSAndroid Build Coastguard Worker params.non_block, params.tail, params.log_mask, params.pid, params.start_time, 130*598139dcSAndroid Build Coastguard Worker params.sequence, params.deadline)); 131*598139dcSAndroid Build Coastguard Worker test_.reader_list_.AddAndRunThread(std::move(log_reader)); 132*598139dcSAndroid Build Coastguard Worker } 133*598139dcSAndroid Build Coastguard Worker WaitUntilReleased()134*598139dcSAndroid Build Coastguard Worker void WaitUntilReleased() { 135*598139dcSAndroid Build Coastguard Worker while (!released_) { 136*598139dcSAndroid Build Coastguard Worker usleep(5000); 137*598139dcSAndroid Build Coastguard Worker } 138*598139dcSAndroid Build Coastguard Worker } 139*598139dcSAndroid Build Coastguard Worker WaitForMessages(size_t n)140*598139dcSAndroid Build Coastguard Worker std::vector<LogMessage> WaitForMessages(size_t n) { 141*598139dcSAndroid Build Coastguard Worker int retry_count = 1s / 5000us; 142*598139dcSAndroid Build Coastguard Worker while (retry_count--) { 143*598139dcSAndroid Build Coastguard Worker usleep(5000); 144*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{mutex_}; 145*598139dcSAndroid Build Coastguard Worker if (read_log_messages_.size() == n) { 146*598139dcSAndroid Build Coastguard Worker return read_log_messages_; 147*598139dcSAndroid Build Coastguard Worker } 148*598139dcSAndroid Build Coastguard Worker } 149*598139dcSAndroid Build Coastguard Worker return {}; 150*598139dcSAndroid Build Coastguard Worker } 151*598139dcSAndroid Build Coastguard Worker read_log_messages()152*598139dcSAndroid Build Coastguard Worker std::vector<LogMessage> read_log_messages() { 153*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{mutex_}; 154*598139dcSAndroid Build Coastguard Worker return read_log_messages_; 155*598139dcSAndroid Build Coastguard Worker } 156*598139dcSAndroid Build Coastguard Worker 157*598139dcSAndroid Build Coastguard Worker private: 158*598139dcSAndroid Build Coastguard Worker LogBufferTest& test_; 159*598139dcSAndroid Build Coastguard Worker std::mutex mutex_; 160*598139dcSAndroid Build Coastguard Worker std::vector<LogMessage> read_log_messages_; 161*598139dcSAndroid Build Coastguard Worker bool released_ = false; 162*598139dcSAndroid Build Coastguard Worker }; 163*598139dcSAndroid Build Coastguard Worker ReadLogMessagesNonBlockingThread(const ReaderThreadParams & params)164*598139dcSAndroid Build Coastguard Worker std::vector<LogMessage> ReadLogMessagesNonBlockingThread(const ReaderThreadParams& params) { 165*598139dcSAndroid Build Coastguard Worker EXPECT_TRUE(params.non_block) 166*598139dcSAndroid Build Coastguard Worker << "params.non_block must be true for ReadLogMessagesNonBlockingThread()"; 167*598139dcSAndroid Build Coastguard Worker 168*598139dcSAndroid Build Coastguard Worker auto reader = TestReaderThread(params, *this); 169*598139dcSAndroid Build Coastguard Worker reader.WaitUntilReleased(); 170*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock}; 171*598139dcSAndroid Build Coastguard Worker EXPECT_EQ(0U, reader_list_.running_reader_threads().size()); 172*598139dcSAndroid Build Coastguard Worker 173*598139dcSAndroid Build Coastguard Worker return reader.read_log_messages(); 174*598139dcSAndroid Build Coastguard Worker } 175*598139dcSAndroid Build Coastguard Worker ReleaseAndJoinReaders()176*598139dcSAndroid Build Coastguard Worker void ReleaseAndJoinReaders() { 177*598139dcSAndroid Build Coastguard Worker { 178*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock}; 179*598139dcSAndroid Build Coastguard Worker for (auto& reader : reader_list_.running_reader_threads()) { 180*598139dcSAndroid Build Coastguard Worker reader->Release(); 181*598139dcSAndroid Build Coastguard Worker } 182*598139dcSAndroid Build Coastguard Worker } 183*598139dcSAndroid Build Coastguard Worker 184*598139dcSAndroid Build Coastguard Worker auto retries = 1s / 5000us; 185*598139dcSAndroid Build Coastguard Worker while (retries--) { 186*598139dcSAndroid Build Coastguard Worker usleep(5000); 187*598139dcSAndroid Build Coastguard Worker auto lock = std::lock_guard{logd_lock}; 188*598139dcSAndroid Build Coastguard Worker if (reader_list_.running_reader_threads().size() == 0) { 189*598139dcSAndroid Build Coastguard Worker return; 190*598139dcSAndroid Build Coastguard Worker } 191*598139dcSAndroid Build Coastguard Worker } 192*598139dcSAndroid Build Coastguard Worker 193*598139dcSAndroid Build Coastguard Worker FAIL() << "ReleaseAndJoinReaders() timed out with reader threads still running"; 194*598139dcSAndroid Build Coastguard Worker } 195*598139dcSAndroid Build Coastguard Worker 196*598139dcSAndroid Build Coastguard Worker LogReaderList reader_list_; 197*598139dcSAndroid Build Coastguard Worker LogTags tags_; 198*598139dcSAndroid Build Coastguard Worker PruneList prune_; 199*598139dcSAndroid Build Coastguard Worker LogStatistics stats_{false, true}; 200*598139dcSAndroid Build Coastguard Worker std::unique_ptr<LogBuffer> log_buffer_; 201*598139dcSAndroid Build Coastguard Worker }; 202