blob: a77474199d27f090bee3a2e03275402d7b04d9c6 [file] [log] [blame]
Yi Jinadd11e92017-07-30 16:10:07 -07001// 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
15#define LOG_TAG "incidentd"
16
17#include "Reporter.h"
18
19#include <android/os/BnIncidentReportStatusListener.h>
20
21#include <android-base/file.h>
22#include <android-base/test_utils.h>
23#include <dirent.h>
24#include <gmock/gmock.h>
25#include <gtest/gtest.h>
26#include <string.h>
27
28
29using namespace android;
30using namespace android::base;
31using namespace android::binder;
32using namespace std;
33using ::testing::StrEq;
34using ::testing::Test;
35using ::testing::internal::CaptureStdout;
36using ::testing::internal::GetCapturedStdout;
37
38class TestListener : public IIncidentReportStatusListener
39{
40public:
41 int startInvoked;
42 int finishInvoked;
43 int failedInvoked;
44 map<int, int> startSections;
45 map<int, int> finishSections;
46
47 TestListener() : startInvoked(0), finishInvoked(0), failedInvoked(0) {};
48 virtual ~TestListener() {};
49
50 virtual Status onReportStarted() {
51 startInvoked++;
52 return Status::ok();
53 };
54 virtual Status onReportSectionStatus(int section, int status) {
55 switch (status) {
56 case IIncidentReportStatusListener::STATUS_STARTING:
57 if (startSections.count(section) == 0)
58 startSections[section] = 0;
59 startSections[section] = startSections[section] + 1;
60 break;
61 case IIncidentReportStatusListener::STATUS_FINISHED:
62 if (finishSections.count(section) == 0)
63 finishSections[section] = 0;
64 finishSections[section] = finishSections[section] + 1;
65 break;
66 }
67 return Status::ok();
68 };
69 virtual Status onReportFinished() {
70 finishInvoked++;
71 return Status::ok();
72 };
73 virtual Status onReportFailed() {
74 failedInvoked++;
75 return Status::ok();
76 };
77
78protected:
79 IBinder* onAsBinder() override { return nullptr; };
80
81};
82
83class ReporterTest : public Test {
84public:
85 virtual void SetUp() {
86 reporter = new Reporter(td.path);
87 l = new TestListener();
88 }
89
90 vector<string> InspectFiles() {
91 DIR* dir;
92 struct dirent* entry;
93 vector<string> results;
94
95 string dirbase = string(td.path) + "/";
96 dir = opendir(td.path);
97
98 while ((entry = readdir(dir)) != NULL) {
99 if (entry->d_name[0] == '.') {
100 continue;
101 }
102 string filename = dirbase + entry->d_name;
103 string content;
104 ReadFileToString(filename, &content);
105 results.push_back(content);
106 }
107 return results;
108 }
109
110protected:
111 TemporaryDir td;
112 ReportRequestSet requests;
113 sp<Reporter> reporter;
114 sp<TestListener> l;
115};
116
117TEST_F(ReporterTest, IncidentReportArgs) {
118 IncidentReportArgs args1, args2;
119 args1.addSection(1);
120 args2.addSection(3);
121
122 args1.merge(args2);
123 ASSERT_TRUE(args1.containsSection(1));
124 ASSERT_FALSE(args1.containsSection(2));
125 ASSERT_TRUE(args1.containsSection(3));
126}
127
128TEST_F(ReporterTest, ReportRequestSetEmpty) {
129 requests.setMainFd(STDOUT_FILENO);
130
131 CaptureStdout();
132 requests.write((uint8_t *) "abcdef", 6);
133 EXPECT_THAT(GetCapturedStdout(), StrEq("abcdef"));
134}
135
136TEST_F(ReporterTest, WriteToStreamFdAndMainFd) {
137 TemporaryFile tf;
138 IncidentReportArgs args;
139 sp<ReportRequest> r = new ReportRequest(args, l, tf.fd);
140
141 requests.add(r);
142 requests.setMainFd(STDOUT_FILENO);
143
144 const char* data = "abcdef";
145
146 CaptureStdout();
147 requests.write((uint8_t *) data, 6);
148 EXPECT_THAT(GetCapturedStdout(), StrEq(data));
149
150 string content;
151 ASSERT_TRUE(ReadFileToString(tf.path, &content));
152 EXPECT_THAT(content, StrEq(data));
153}
154
155TEST_F(ReporterTest, RunReportEmpty) {
156 ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport());
157 EXPECT_EQ(l->startInvoked, 0);
158 EXPECT_EQ(l->finishInvoked, 0);
159 EXPECT_TRUE(l->startSections.empty());
160 EXPECT_TRUE(l->finishSections.empty());
161 EXPECT_EQ(l->failedInvoked, 0);
162}
163
164TEST_F(ReporterTest, RunReportWithHeaders) {
165 IncidentReportArgs args1, args2;
166 args1.addSection(1);
167 args2.addSection(2);
168 std::vector<int8_t> header {'a', 'b', 'c', 'd', 'e'};
169 args2.addHeader(header);
170 sp<ReportRequest> r1 = new ReportRequest(args1, l, STDOUT_FILENO);
171 sp<ReportRequest> r2 = new ReportRequest(args2, l, STDOUT_FILENO);
172
173 reporter->batch.add(r1);
174 reporter->batch.add(r2);
175
176 CaptureStdout();
177 ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport());
178 EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x5" "abcde"));
179 EXPECT_EQ(l->startInvoked, 2);
180 EXPECT_EQ(l->finishInvoked, 2);
181 EXPECT_TRUE(l->startSections.empty());
182 EXPECT_TRUE(l->finishSections.empty());
183 EXPECT_EQ(l->failedInvoked, 0);
184}
185
186TEST_F(ReporterTest, RunReportToGivenDirectory) {
187 IncidentReportArgs args;
188 args.addHeader({'1', '2', '3'});
189 args.addHeader({'a', 'b', 'c', 'd'});
190 sp<ReportRequest> r = new ReportRequest(args, l, -1);
191 reporter->batch.add(r);
192
193 ASSERT_EQ(Reporter::REPORT_FINISHED, reporter->runReport());
194 vector<string> results = InspectFiles();
195 ASSERT_EQ((int)results.size(), 1);
196 EXPECT_EQ(results[0], "\n\x3" "123\n\x4" "abcd");
197}