1 // Copyright (C) 2017 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 #define DEBUG false 15 #include "Log.h" 16 17 #include "Reporter.h" 18 19 #include <android/os/BnIncidentReportStatusListener.h> 20 #include <frameworks/base/libs/incident/proto/android/os/header.pb.h> 21 22 #include <android-base/file.h> 23 #include <android-base/test_utils.h> 24 #include <dirent.h> 25 #include <gmock/gmock.h> 26 #include <gtest/gtest.h> 27 #include <string.h> 28 29 using namespace android; 30 using namespace android::base; 31 using namespace android::binder; 32 using namespace android::os; 33 using namespace android::os::incidentd; 34 using namespace std; 35 using ::testing::StrEq; 36 using ::testing::Test; 37 38 class TestListener : public IIncidentReportStatusListener { 39 public: 40 int startInvoked; 41 int finishInvoked; 42 int failedInvoked; 43 map<int, int> startSections; 44 map<int, int> finishSections; 45 46 TestListener() : startInvoked(0), finishInvoked(0), failedInvoked(0){}; 47 virtual ~TestListener(){}; 48 49 virtual Status onReportStarted() { 50 startInvoked++; 51 return Status::ok(); 52 }; 53 virtual Status onReportSectionStatus(int section, int status) { 54 switch (status) { 55 case IIncidentReportStatusListener::STATUS_STARTING: 56 if (startSections.count(section) == 0) startSections[section] = 0; 57 startSections[section] = startSections[section] + 1; 58 break; 59 case IIncidentReportStatusListener::STATUS_FINISHED: 60 if (finishSections.count(section) == 0) finishSections[section] = 0; 61 finishSections[section] = finishSections[section] + 1; 62 break; 63 } 64 return Status::ok(); 65 }; 66 virtual Status onReportFinished() { 67 finishInvoked++; 68 return Status::ok(); 69 }; 70 virtual Status onReportFailed() { 71 failedInvoked++; 72 return Status::ok(); 73 }; 74 75 protected: 76 virtual IBinder* onAsBinder() override { return nullptr; }; 77 }; 78 79 class ReporterTest : public Test { 80 public: 81 virtual void SetUp() { 82 reporter = new Reporter(td.path); 83 l = new TestListener(); 84 } 85 86 vector<string> InspectFiles() { 87 DIR* dir; 88 struct dirent* entry; 89 vector<string> results; 90 91 string dirbase = string(td.path) + "/"; 92 dir = opendir(td.path); 93 94 while ((entry = readdir(dir)) != NULL) { 95 if (entry->d_name[0] == '.') { 96 continue; 97 } 98 string filename = dirbase + entry->d_name; 99 string content; 100 ReadFileToString(filename, &content); 101 results.push_back(content); 102 } 103 return results; 104 } 105 106 protected: 107 TemporaryDir td; 108 ReportRequestSet requests; 109 sp<Reporter> reporter; 110 sp<TestListener> l; 111 size_t size; 112 }; 113 114 TEST_F(ReporterTest, IncidentReportArgs) { 115 IncidentReportArgs args1, args2; 116 args1.addSection(1); 117 args2.addSection(3); 118 119 args1.merge(args2); 120 ASSERT_TRUE(args1.containsSection(1)); 121 ASSERT_FALSE(args1.containsSection(2)); 122 ASSERT_TRUE(args1.containsSection(3)); 123 } 124 125 TEST_F(ReporterTest, ReportRequestSetEmpty) { 126 requests.setMainFd(STDOUT_FILENO); 127 ASSERT_EQ(requests.mainFd(), STDOUT_FILENO); 128 } 129 130 TEST_F(ReporterTest, RunReportEmpty) { 131 ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); 132 EXPECT_EQ(l->startInvoked, 0); 133 EXPECT_EQ(l->finishInvoked, 0); 134 EXPECT_TRUE(l->startSections.empty()); 135 EXPECT_TRUE(l->finishSections.empty()); 136 EXPECT_EQ(l->failedInvoked, 0); 137 } 138 139 TEST_F(ReporterTest, RunReportWithHeaders) { 140 TemporaryFile tf; 141 IncidentReportArgs args1, args2; 142 args1.addSection(1); 143 args2.addSection(2); 144 IncidentHeaderProto header; 145 header.set_alert_id(12); 146 args2.addHeader(header); 147 sp<ReportRequest> r1 = new ReportRequest(args1, l, tf.fd); 148 sp<ReportRequest> r2 = new ReportRequest(args2, l, tf.fd); 149 150 reporter->batch.add(r1); 151 reporter->batch.add(r2); 152 153 ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); 154 155 string result; 156 ReadFileToString(tf.path, &result); 157 EXPECT_THAT(result, StrEq("\n\x2" 158 "\b\f")); 159 160 EXPECT_EQ(l->startInvoked, 2); 161 EXPECT_EQ(l->finishInvoked, 2); 162 EXPECT_TRUE(l->startSections.empty()); 163 EXPECT_TRUE(l->finishSections.empty()); 164 EXPECT_EQ(l->failedInvoked, 0); 165 } 166 167 TEST_F(ReporterTest, RunReportToGivenDirectory) { 168 IncidentReportArgs args; 169 IncidentHeaderProto header1, header2; 170 header1.set_alert_id(12); 171 header2.set_reason("abcd"); 172 args.addHeader(header1); 173 args.addHeader(header2); 174 sp<ReportRequest> r = new ReportRequest(args, l, -1); 175 reporter->batch.add(r); 176 177 ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); 178 vector<string> results = InspectFiles(); 179 ASSERT_EQ((int)results.size(), 1); 180 EXPECT_EQ(results[0], 181 "\n\x2" 182 "\b\f\n\x6" 183 "\x12\x4" 184 "abcd"); 185 } 186 187 TEST_F(ReporterTest, ReportMetadata) { 188 IncidentReportArgs args; 189 args.addSection(1); 190 args.setDest(android::os::DEST_EXPLICIT); 191 sp<ReportRequest> r = new ReportRequest(args, l, -1); 192 reporter->batch.add(r); 193 194 ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); 195 IncidentMetadata metadata = reporter->batch.metadata(); 196 EXPECT_EQ(IncidentMetadata_Destination_EXPLICIT, metadata.dest()); 197 EXPECT_EQ(1, metadata.request_size()); 198 EXPECT_TRUE(metadata.use_dropbox()); 199 EXPECT_EQ(0, metadata.sections_size()); 200 }