Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 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. |
Yi Jin | 4e84310 | 2018-02-14 15:36:18 -0800 | [diff] [blame] | 14 | #define DEBUG false |
Yi Jin | b592e3b | 2018-02-01 15:17:04 -0800 | [diff] [blame] | 15 | #include "Log.h" |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 16 | |
| 17 | #include "Reporter.h" |
| 18 | |
| 19 | #include <android/os/BnIncidentReportStatusListener.h> |
Yi Jin | 437aa6e | 2018-01-10 11:34:26 -0800 | [diff] [blame] | 20 | #include <frameworks/base/libs/incident/proto/android/os/header.pb.h> |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 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 | |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 29 | using namespace android; |
| 30 | using namespace android::base; |
| 31 | using namespace android::binder; |
Yi Jin | 437aa6e | 2018-01-10 11:34:26 -0800 | [diff] [blame] | 32 | using namespace android::os; |
Yi Jin | 6cacbcb | 2018-03-30 14:04:52 -0700 | [diff] [blame] | 33 | using namespace android::os::incidentd; |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 34 | using namespace std; |
| 35 | using ::testing::StrEq; |
| 36 | using ::testing::Test; |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 37 | |
Yi Jin | b592e3b | 2018-02-01 15:17:04 -0800 | [diff] [blame] | 38 | class TestListener : public IIncidentReportStatusListener { |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 39 | public: |
| 40 | int startInvoked; |
| 41 | int finishInvoked; |
| 42 | int failedInvoked; |
| 43 | map<int, int> startSections; |
| 44 | map<int, int> finishSections; |
| 45 | |
Yi Jin | b592e3b | 2018-02-01 15:17:04 -0800 | [diff] [blame] | 46 | TestListener() : startInvoked(0), finishInvoked(0), failedInvoked(0){}; |
| 47 | virtual ~TestListener(){}; |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 48 | |
| 49 | virtual Status onReportStarted() { |
| 50 | startInvoked++; |
| 51 | return Status::ok(); |
| 52 | }; |
| 53 | virtual Status onReportSectionStatus(int section, int status) { |
| 54 | switch (status) { |
Yi Jin | b592e3b | 2018-02-01 15:17:04 -0800 | [diff] [blame] | 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; |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 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: |
Yi Jin | 0f04716 | 2017-09-05 13:44:22 -0700 | [diff] [blame] | 76 | virtual IBinder* onAsBinder() override { return nullptr; }; |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 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; |
Yi Jin | 4e84310 | 2018-02-14 15:36:18 -0800 | [diff] [blame] | 111 | size_t size; |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 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); |
Yi Jin | 99c248f | 2017-08-25 18:11:58 -0700 | [diff] [blame] | 127 | ASSERT_EQ(requests.mainFd(), STDOUT_FILENO); |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 128 | } |
| 129 | |
| 130 | TEST_F(ReporterTest, RunReportEmpty) { |
Yi Jin | 4e84310 | 2018-02-14 15:36:18 -0800 | [diff] [blame] | 131 | ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 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) { |
Yi Jin | e083330 | 2017-10-23 15:42:44 -0700 | [diff] [blame] | 140 | TemporaryFile tf; |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 141 | IncidentReportArgs args1, args2; |
| 142 | args1.addSection(1); |
| 143 | args2.addSection(2); |
Yi Jin | 437aa6e | 2018-01-10 11:34:26 -0800 | [diff] [blame] | 144 | IncidentHeaderProto header; |
| 145 | header.set_alert_id(12); |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 146 | args2.addHeader(header); |
Yi Jin | e083330 | 2017-10-23 15:42:44 -0700 | [diff] [blame] | 147 | sp<ReportRequest> r1 = new ReportRequest(args1, l, tf.fd); |
| 148 | sp<ReportRequest> r2 = new ReportRequest(args2, l, tf.fd); |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 149 | |
| 150 | reporter->batch.add(r1); |
| 151 | reporter->batch.add(r2); |
| 152 | |
Yi Jin | 4e84310 | 2018-02-14 15:36:18 -0800 | [diff] [blame] | 153 | ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); |
Yi Jin | e083330 | 2017-10-23 15:42:44 -0700 | [diff] [blame] | 154 | |
| 155 | string result; |
| 156 | ReadFileToString(tf.path, &result); |
Yi Jin | b592e3b | 2018-02-01 15:17:04 -0800 | [diff] [blame] | 157 | EXPECT_THAT(result, StrEq("\n\x2" |
| 158 | "\b\f")); |
Yi Jin | e083330 | 2017-10-23 15:42:44 -0700 | [diff] [blame] | 159 | |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 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; |
Yi Jin | 437aa6e | 2018-01-10 11:34:26 -0800 | [diff] [blame] | 169 | IncidentHeaderProto header1, header2; |
| 170 | header1.set_alert_id(12); |
| 171 | header2.set_reason("abcd"); |
| 172 | args.addHeader(header1); |
| 173 | args.addHeader(header2); |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 174 | sp<ReportRequest> r = new ReportRequest(args, l, -1); |
| 175 | reporter->batch.add(r); |
| 176 | |
Yi Jin | 4e84310 | 2018-02-14 15:36:18 -0800 | [diff] [blame] | 177 | ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 178 | vector<string> results = InspectFiles(); |
| 179 | ASSERT_EQ((int)results.size(), 1); |
Yi Jin | b592e3b | 2018-02-01 15:17:04 -0800 | [diff] [blame] | 180 | EXPECT_EQ(results[0], |
| 181 | "\n\x2" |
| 182 | "\b\f\n\x6" |
| 183 | "\x12\x4" |
| 184 | "abcd"); |
Yi Jin | add11e9 | 2017-07-30 16:10:07 -0700 | [diff] [blame] | 185 | } |
Yi Jin | 329130b | 2018-02-09 16:47:47 -0800 | [diff] [blame] | 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 | |
Yi Jin | 4e84310 | 2018-02-14 15:36:18 -0800 | [diff] [blame] | 194 | ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport(&size)); |
Yi Jin | 86dce41 | 2018-03-07 11:36:57 -0800 | [diff] [blame] | 195 | IncidentMetadata metadata = reporter->batch.metadata(); |
Yi Jin | 329130b | 2018-02-09 16:47:47 -0800 | [diff] [blame] | 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 | } |