• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Section.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/test_utils.h>
21 #include <android/os/IncidentReportArgs.h>
22 #include <android/util/protobuf.h>
23 #include <frameworks/base/libs/incident/proto/android/os/header.pb.h>
24 #include <gmock/gmock.h>
25 #include <gtest/gtest.h>
26 #include <string.h>
27 
28 using namespace android;
29 using namespace android::base;
30 using namespace android::binder;
31 using namespace android::os;
32 using namespace android::os::incidentd;
33 using namespace android::util;
34 using ::testing::StrEq;
35 using ::testing::Test;
36 using ::testing::internal::CaptureStdout;
37 using ::testing::internal::GetCapturedStdout;
38 
39 const int TIMEOUT_PARSER = -1;
40 const int NOOP_PARSER = 0;
41 const int REVERSE_PARSER = 1;
42 
43 const int QUICK_TIMEOUT_MS = 100;
44 
45 const std::string VARINT_FIELD_1 = "\x08\x96\x01";  // 150
46 const std::string STRING_FIELD_2 = "\x12\vandroidwins";
47 const std::string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff";  // -1
48 
49 // NOTICE: this test requires /system/bin/incident_helper is installed.
50 class SectionTest : public Test {
51 public:
SetUp()52     virtual void SetUp() override { ASSERT_NE(tf.fd, -1); }
53 
printDebugString(std::string s)54     void printDebugString(std::string s) {
55         fprintf(stderr, "size: %zu\n", s.length());
56         for (size_t i = 0; i < s.length(); i++) {
57             char c = s[i];
58             fprintf(stderr, "\\x%x", c);
59         }
60         fprintf(stderr, "\n");
61     }
62 
63 protected:
64     TemporaryFile tf;
65     ReportRequestSet requests;
66 
67     const std::string kTestPath = GetExecutableDirectory();
68     const std::string kTestDataPath = kTestPath + "/testdata/";
69 };
70 
71 class SimpleListener : public IIncidentReportStatusListener {
72 public:
SimpleListener()73     SimpleListener(){};
~SimpleListener()74     virtual ~SimpleListener(){};
75 
onReportStarted()76     virtual Status onReportStarted() { return Status::ok(); };
onReportSectionStatus(int,int)77     virtual Status onReportSectionStatus(int /*section*/, int /*status*/) { return Status::ok(); };
onReportFinished()78     virtual Status onReportFinished() { return Status::ok(); };
onReportFailed()79     virtual Status onReportFailed() { return Status::ok(); };
80 
81 protected:
onAsBinder()82     virtual IBinder* onAsBinder() override { return nullptr; };
83 };
84 
TEST_F(SectionTest,HeaderSection)85 TEST_F(SectionTest, HeaderSection) {
86     HeaderSection hs;
87 
88     IncidentReportArgs args1, args2;
89     args1.addSection(1);
90     args1.addSection(2);
91     args2.setAll(true);
92 
93     IncidentHeaderProto head1, head2;
94     head1.set_reason("axe");
95     head2.set_reason("pup");
96 
97     args1.addHeader(head1);
98     args1.addHeader(head2);
99     args2.addHeader(head2);
100 
101     requests.add(new ReportRequest(args1, new SimpleListener(), -1));
102     requests.add(new ReportRequest(args2, new SimpleListener(), tf.fd));
103     requests.setMainFd(STDOUT_FILENO);
104 
105     std::string content;
106     CaptureStdout();
107     ASSERT_EQ(NO_ERROR, hs.Execute(&requests));
108     EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x5"
109                                            "\x12\x3"
110                                            "axe\n\x05\x12\x03pup"));
111 
112     EXPECT_TRUE(ReadFileToString(tf.path, &content));
113     EXPECT_THAT(content, StrEq("\n\x05\x12\x03pup"));
114 }
115 
TEST_F(SectionTest,MetadataSection)116 TEST_F(SectionTest, MetadataSection) {
117     MetadataSection ms;
118     const std::string testFile = kTestDataPath + "metadata.txt";
119     std::string expect;
120     ASSERT_TRUE(ReadFileToString(testFile, &expect));
121 
122     requests.setMainFd(STDOUT_FILENO);
123     requests.setMainDest(android::os::DEST_LOCAL);
124     requests.sectionStats(1)->set_success(true);
125 
126     CaptureStdout();
127     ASSERT_EQ(NO_ERROR, ms.Execute(&requests));
128     // Notice message_lite.h ParseFromString doesn't work so we just match the bytes directly.
129     EXPECT_THAT(GetCapturedStdout(), StrEq(expect));
130 }
131 
TEST_F(SectionTest,FileSection)132 TEST_F(SectionTest, FileSection) {
133     FileSection fs(REVERSE_PARSER, tf.path);
134 
135     ASSERT_TRUE(WriteStringToFile("iamtestdata", tf.path));
136 
137     requests.setMainFd(STDOUT_FILENO);
138 
139     CaptureStdout();
140     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
141     // The input string is reversed in incident helper
142     // The length is 11, in 128Varint it is "0000 1011" -> \v
143     EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\vatadtsetmai"));
144 }
145 
TEST_F(SectionTest,FileSectionNotExist)146 TEST_F(SectionTest, FileSectionNotExist) {
147     FileSection fs1(NOOP_PARSER, "notexist", false, QUICK_TIMEOUT_MS);
148     ASSERT_EQ(NAME_NOT_FOUND, fs1.Execute(&requests));
149 
150     FileSection fs2(NOOP_PARSER, "notexist", true, QUICK_TIMEOUT_MS);
151     ASSERT_EQ(NO_ERROR, fs2.Execute(&requests));
152 }
153 
TEST_F(SectionTest,FileSectionTimeout)154 TEST_F(SectionTest, FileSectionTimeout) {
155     FileSection fs(TIMEOUT_PARSER, tf.path, false, QUICK_TIMEOUT_MS);
156     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
157     ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
158 }
159 
TEST_F(SectionTest,GZipSection)160 TEST_F(SectionTest, GZipSection) {
161     const std::string testFile = kTestDataPath + "kmsg.txt";
162     const std::string testGzFile = testFile + ".gz";
163     GZipSection gs(NOOP_PARSER, "/tmp/nonexist", testFile.c_str(), NULL);
164 
165     requests.setMainFd(tf.fd);
166     requests.setMainDest(android::os::DEST_LOCAL);
167 
168     ASSERT_EQ(NO_ERROR, gs.Execute(&requests));
169     std::string expected, gzFile, actual;
170     ASSERT_TRUE(ReadFileToString(testGzFile, &gzFile));
171     ASSERT_TRUE(ReadFileToString(tf.path, &actual));
172     // generates the expected protobuf result.
173     size_t fileLen = testFile.size();
174     size_t totalLen = 1 + get_varint_size(fileLen) + fileLen + 3 + gzFile.size();
175     uint8_t header[20];
176     header[0] = '\x2';  // header 0 << 3 + 2
177     uint8_t* ptr = write_raw_varint(header + 1, totalLen);
178     *ptr = '\n';  // header 1 << 3 + 2
179     ptr = write_raw_varint(++ptr, fileLen);
180     expected.assign((const char*)header, ptr - header);
181     expected += testFile + "\x12\x9F\x6" + gzFile;
182     EXPECT_THAT(actual, StrEq(expected));
183 }
184 
TEST_F(SectionTest,GZipSectionNoFileFound)185 TEST_F(SectionTest, GZipSectionNoFileFound) {
186     GZipSection gs(NOOP_PARSER, "/tmp/nonexist1", "/tmp/nonexist2", NULL);
187     requests.setMainFd(STDOUT_FILENO);
188     ASSERT_EQ(NO_ERROR, gs.Execute(&requests));
189 }
190 
TEST_F(SectionTest,CommandSectionConstructor)191 TEST_F(SectionTest, CommandSectionConstructor) {
192     CommandSection cs1(1, "echo", "\"this is a test\"", "ooo", NULL);
193     CommandSection cs2(2, "single_command", NULL);
194     CommandSection cs3(1, 3123, "echo", "\"this is a test\"", "ooo", NULL);
195     CommandSection cs4(2, 43214, "single_command", NULL);
196 
197     EXPECT_THAT(cs1.name.string(), StrEq("cmd echo \"this is a test\" ooo"));
198     EXPECT_THAT(cs2.name.string(), StrEq("cmd single_command"));
199     EXPECT_EQ(3123, cs3.timeoutMs);
200     EXPECT_EQ(43214, cs4.timeoutMs);
201     EXPECT_THAT(cs3.name.string(), StrEq("cmd echo \"this is a test\" ooo"));
202     EXPECT_THAT(cs4.name.string(), StrEq("cmd single_command"));
203 }
204 
TEST_F(SectionTest,CommandSectionEcho)205 TEST_F(SectionTest, CommandSectionEcho) {
206     CommandSection cs(REVERSE_PARSER, "/system/bin/echo", "about", NULL);
207     requests.setMainFd(STDOUT_FILENO);
208     CaptureStdout();
209     ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
210     EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\x06\ntuoba"));
211 }
212 
TEST_F(SectionTest,CommandSectionCommandTimeout)213 TEST_F(SectionTest, CommandSectionCommandTimeout) {
214     CommandSection cs(NOOP_PARSER, QUICK_TIMEOUT_MS, "/system/bin/yes", NULL);
215     ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
216     ASSERT_TRUE(requests.sectionStats(NOOP_PARSER)->timed_out());
217 }
218 
TEST_F(SectionTest,CommandSectionIncidentHelperTimeout)219 TEST_F(SectionTest, CommandSectionIncidentHelperTimeout) {
220     CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "/system/bin/echo", "about", NULL);
221     requests.setMainFd(STDOUT_FILENO);
222     ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
223     ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
224 }
225 
TEST_F(SectionTest,CommandSectionBadCommand)226 TEST_F(SectionTest, CommandSectionBadCommand) {
227     CommandSection cs(NOOP_PARSER, "echoo", "about", NULL);
228     ASSERT_EQ(NAME_NOT_FOUND, cs.Execute(&requests));
229 }
230 
TEST_F(SectionTest,CommandSectionBadCommandAndTimeout)231 TEST_F(SectionTest, CommandSectionBadCommandAndTimeout) {
232     CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "nonexistcommand", "-opt", NULL);
233     // timeout will return first
234     ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
235     ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
236 }
237 
TEST_F(SectionTest,LogSectionBinary)238 TEST_F(SectionTest, LogSectionBinary) {
239     LogSection ls(1, LOG_ID_EVENTS);
240     requests.setMainFd(STDOUT_FILENO);
241     CaptureStdout();
242     ASSERT_EQ(NO_ERROR, ls.Execute(&requests));
243     std::string results = GetCapturedStdout();
244     EXPECT_FALSE(results.empty());
245 }
246 
TEST_F(SectionTest,LogSectionSystem)247 TEST_F(SectionTest, LogSectionSystem) {
248     LogSection ls(1, LOG_ID_SYSTEM);
249     requests.setMainFd(STDOUT_FILENO);
250     CaptureStdout();
251     ASSERT_EQ(NO_ERROR, ls.Execute(&requests));
252     std::string results = GetCapturedStdout();
253     EXPECT_FALSE(results.empty());
254 }
255 
TEST_F(SectionTest,TestFilterPiiTaggedFields)256 TEST_F(SectionTest, TestFilterPiiTaggedFields) {
257     FileSection fs(NOOP_PARSER, tf.path);
258 
259     ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
260 
261     requests.setMainFd(STDOUT_FILENO);
262 
263     CaptureStdout();
264     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
265     EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
266 }
267 
TEST_F(SectionTest,TestBadFdRequest)268 TEST_F(SectionTest, TestBadFdRequest) {
269     FileSection fs(NOOP_PARSER, tf.path);
270     ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
271 
272     IncidentReportArgs args;
273     args.setAll(true);
274     args.setDest(0);
275     sp<ReportRequest> badFdRequest = new ReportRequest(args, new SimpleListener(), 1234567);
276     requests.add(badFdRequest);
277     requests.setMainFd(STDOUT_FILENO);
278 
279     CaptureStdout();
280     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
281     EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
282     EXPECT_EQ(badFdRequest->err, -EBADF);
283 }
284 
TEST_F(SectionTest,TestBadRequests)285 TEST_F(SectionTest, TestBadRequests) {
286     FileSection fs(NOOP_PARSER, tf.path);
287     ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
288 
289     IncidentReportArgs args;
290     args.setAll(true);
291     args.setDest(0);
292     requests.add(new ReportRequest(args, new SimpleListener(), -1));
293     EXPECT_EQ(fs.Execute(&requests), -EBADF);
294 }
295 
TEST_F(SectionTest,TestMultipleRequests)296 TEST_F(SectionTest, TestMultipleRequests) {
297     TemporaryFile output1, output2, output3;
298     FileSection fs(NOOP_PARSER, tf.path);
299 
300     ASSERT_TRUE(output1.fd != -1);
301     ASSERT_TRUE(output2.fd != -1);
302     ASSERT_TRUE(output3.fd != -1);
303     ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
304 
305     IncidentReportArgs args1, args2, args3;
306     args1.setAll(true);
307     args1.setDest(android::os::DEST_LOCAL);
308     args2.setAll(true);
309     args2.setDest(android::os::DEST_EXPLICIT);
310     sp<SimpleListener> l = new SimpleListener();
311     requests.add(new ReportRequest(args1, l, output1.fd));
312     requests.add(new ReportRequest(args2, l, output2.fd));
313     requests.add(new ReportRequest(args3, l, output3.fd));
314     requests.setMainFd(STDOUT_FILENO);
315 
316     CaptureStdout();
317     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
318     EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
319 
320     std::string content, expect;
321     expect = VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3;
322     char c = (char)expect.size();
323     EXPECT_TRUE(ReadFileToString(output1.path, &content));
324     EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
325 
326     expect = STRING_FIELD_2 + FIX64_FIELD_3;
327     c = (char)expect.size();
328     EXPECT_TRUE(ReadFileToString(output2.path, &content));
329     EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
330 
331     // because args3 doesn't set section, so it should receive nothing
332     EXPECT_TRUE(ReadFileToString(output3.path, &content));
333     EXPECT_THAT(content, StrEq(""));
334 }
335 
TEST_F(SectionTest,TestMultipleRequestsBySpec)336 TEST_F(SectionTest, TestMultipleRequestsBySpec) {
337     TemporaryFile output1, output2, output3;
338     FileSection fs(NOOP_PARSER, tf.path);
339 
340     ASSERT_TRUE(output1.fd != -1);
341     ASSERT_TRUE(output2.fd != -1);
342     ASSERT_TRUE(output3.fd != -1);
343 
344     ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
345 
346     IncidentReportArgs args1, args2, args3;
347     args1.setAll(true);
348     args1.setDest(android::os::DEST_EXPLICIT);
349     args2.setAll(true);
350     args2.setDest(android::os::DEST_EXPLICIT);
351     args3.setAll(true);
352     sp<SimpleListener> l = new SimpleListener();
353     requests.add(new ReportRequest(args1, l, output1.fd));
354     requests.add(new ReportRequest(args2, l, output2.fd));
355     requests.add(new ReportRequest(args3, l, output3.fd));
356     requests.setMainFd(STDOUT_FILENO);
357 
358     CaptureStdout();
359     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
360     EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
361 
362     std::string content, expect;
363     expect = STRING_FIELD_2 + FIX64_FIELD_3;
364     char c = (char)expect.size();
365 
366     // output1 and output2 are the same
367     EXPECT_TRUE(ReadFileToString(output1.path, &content));
368     EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
369     EXPECT_TRUE(ReadFileToString(output2.path, &content));
370     EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
371 
372     // output3 has only auto field
373     c = (char)STRING_FIELD_2.size();
374     EXPECT_TRUE(ReadFileToString(output3.path, &content));
375     EXPECT_THAT(content, StrEq(string("\x02") + c + STRING_FIELD_2));
376 }
377