2017-06-22 19:23:11 -07:00
|
|
|
// Copyright (C) 2017 The Android Open Source Project
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#define LOG_TAG "incidentd"
|
|
|
|
|
|
|
|
#include "Section.h"
|
|
|
|
|
|
|
|
#include <android-base/file.h>
|
|
|
|
#include <android-base/test_utils.h>
|
|
|
|
#include <gmock/gmock.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2017-08-25 18:11:58 -07:00
|
|
|
const int TIMEOUT_PARSER = -1;
|
|
|
|
const int NOOP_PARSER = 0;
|
|
|
|
const int REVERSE_PARSER = 1;
|
|
|
|
|
2017-07-21 12:12:59 -07:00
|
|
|
const int QUICK_TIMEOUT_MS = 100;
|
|
|
|
|
2017-08-25 18:11:58 -07:00
|
|
|
const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
|
|
|
|
const string STRING_FIELD_2 = "\x12\vwhatthefuck";
|
|
|
|
const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
|
|
|
|
|
2017-06-22 19:23:11 -07:00
|
|
|
using namespace android::base;
|
2017-09-05 13:44:22 -07:00
|
|
|
using namespace android::binder;
|
2017-06-22 19:23:11 -07:00
|
|
|
using namespace std;
|
|
|
|
using ::testing::StrEq;
|
|
|
|
using ::testing::internal::CaptureStdout;
|
|
|
|
using ::testing::internal::GetCapturedStdout;
|
|
|
|
|
2017-09-06 17:09:11 -07:00
|
|
|
// NOTICE: this test requires /system/bin/incident_helper is installed.
|
|
|
|
|
2017-09-05 13:44:22 -07:00
|
|
|
class SimpleListener : public IIncidentReportStatusListener
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SimpleListener() {};
|
|
|
|
virtual ~SimpleListener() {};
|
|
|
|
|
|
|
|
virtual Status onReportStarted() { return Status::ok(); };
|
|
|
|
virtual Status onReportSectionStatus(int /*section*/, int /*status*/) { return Status::ok(); };
|
|
|
|
virtual Status onReportFinished() { return Status::ok(); };
|
|
|
|
virtual Status onReportFailed() { return Status::ok(); };
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual IBinder* onAsBinder() override { return nullptr; };
|
|
|
|
};
|
|
|
|
|
2017-09-06 17:09:11 -07:00
|
|
|
TEST(SectionTest, HeaderSection) {
|
|
|
|
TemporaryFile output2;
|
|
|
|
HeaderSection hs;
|
|
|
|
ReportRequestSet requests;
|
|
|
|
|
|
|
|
IncidentReportArgs args1, args2;
|
|
|
|
args1.addSection(1);
|
|
|
|
args1.addSection(2);
|
|
|
|
args2.setAll(true);
|
|
|
|
|
2017-11-14 17:58:19 -08:00
|
|
|
vector<uint8_t> head1;
|
2017-09-06 17:09:11 -07:00
|
|
|
head1.push_back('a');
|
|
|
|
head1.push_back('x');
|
|
|
|
head1.push_back('e');
|
|
|
|
|
2017-11-14 17:58:19 -08:00
|
|
|
vector<uint8_t> head2;
|
2017-09-06 17:09:11 -07:00
|
|
|
head2.push_back('p');
|
|
|
|
head2.push_back('u');
|
|
|
|
head2.push_back('p');
|
|
|
|
|
|
|
|
args1.addHeader(head1);
|
|
|
|
args1.addHeader(head2);
|
|
|
|
args2.addHeader(head2);
|
|
|
|
|
|
|
|
requests.add(new ReportRequest(args1, new SimpleListener(), -1));
|
|
|
|
requests.add(new ReportRequest(args2, new SimpleListener(), output2.fd));
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
|
|
|
|
string content;
|
|
|
|
CaptureStdout();
|
|
|
|
ASSERT_EQ(NO_ERROR, hs.Execute(&requests));
|
|
|
|
EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x3" "axe\n\x03pup"));
|
|
|
|
|
|
|
|
EXPECT_TRUE(ReadFileToString(output2.path, &content));
|
|
|
|
EXPECT_THAT(content, StrEq("\n\x03pup"));
|
|
|
|
}
|
|
|
|
|
2017-06-22 19:23:11 -07:00
|
|
|
TEST(SectionTest, FileSection) {
|
|
|
|
TemporaryFile tf;
|
2017-08-25 18:11:58 -07:00
|
|
|
FileSection fs(REVERSE_PARSER, tf.path);
|
2017-06-22 19:23:11 -07:00
|
|
|
ReportRequestSet requests;
|
|
|
|
|
|
|
|
ASSERT_TRUE(tf.fd != -1);
|
2017-11-09 21:45:29 -08:00
|
|
|
ASSERT_TRUE(WriteStringToFile("iamtestdata", tf.path));
|
2017-06-22 19:23:11 -07:00
|
|
|
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
|
|
|
|
CaptureStdout();
|
|
|
|
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
|
|
|
|
// The input string is reversed in incident helper
|
|
|
|
// The length is 11, in 128Varint it is "0000 1011" -> \v
|
2017-08-25 18:11:58 -07:00
|
|
|
EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\vatadtsetmai"));
|
2017-06-22 19:23:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, FileSectionTimeout) {
|
|
|
|
TemporaryFile tf;
|
|
|
|
// id -1 is timeout parser
|
2017-08-25 18:11:58 -07:00
|
|
|
FileSection fs(TIMEOUT_PARSER, tf.path, QUICK_TIMEOUT_MS);
|
2017-06-22 19:23:11 -07:00
|
|
|
ReportRequestSet requests;
|
|
|
|
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
|
2017-07-21 12:12:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, CommandSectionConstructor) {
|
|
|
|
CommandSection cs1(1, "echo", "\"this is a test\"", "ooo", NULL);
|
|
|
|
CommandSection cs2(2, "single_command", NULL);
|
|
|
|
CommandSection cs3(1, 3123, "echo", "\"this is a test\"", "ooo", NULL);
|
|
|
|
CommandSection cs4(2, 43214, "single_command", NULL);
|
|
|
|
|
|
|
|
EXPECT_THAT(cs1.name.string(), StrEq("echo \"this is a test\" ooo"));
|
|
|
|
EXPECT_THAT(cs2.name.string(), StrEq("single_command"));
|
|
|
|
EXPECT_EQ(3123, cs3.timeoutMs);
|
|
|
|
EXPECT_EQ(43214, cs4.timeoutMs);
|
|
|
|
EXPECT_THAT(cs3.name.string(), StrEq("echo \"this is a test\" ooo"));
|
|
|
|
EXPECT_THAT(cs4.name.string(), StrEq("single_command"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, CommandSectionEcho) {
|
2017-08-25 18:11:58 -07:00
|
|
|
CommandSection cs(REVERSE_PARSER, "/system/bin/echo", "about", NULL);
|
2017-07-21 12:12:59 -07:00
|
|
|
ReportRequestSet requests;
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
CaptureStdout();
|
|
|
|
ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
|
2017-08-25 18:11:58 -07:00
|
|
|
EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\x06\ntuoba"));
|
2017-07-21 12:12:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, CommandSectionCommandTimeout) {
|
2017-08-25 18:11:58 -07:00
|
|
|
CommandSection cs(NOOP_PARSER, QUICK_TIMEOUT_MS, "/system/bin/yes", NULL);
|
2017-07-21 12:12:59 -07:00
|
|
|
ReportRequestSet requests;
|
|
|
|
ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, CommandSectionIncidentHelperTimeout) {
|
2017-08-25 18:11:58 -07:00
|
|
|
CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "/system/bin/echo", "about", NULL);
|
2017-07-21 12:12:59 -07:00
|
|
|
ReportRequestSet requests;
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, CommandSectionBadCommand) {
|
2017-08-25 18:11:58 -07:00
|
|
|
CommandSection cs(NOOP_PARSER, "echo", "about", NULL);
|
2017-07-21 12:12:59 -07:00
|
|
|
ReportRequestSet requests;
|
|
|
|
ASSERT_EQ(NAME_NOT_FOUND, cs.Execute(&requests));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, CommandSectionBadCommandAndTimeout) {
|
2017-08-25 18:11:58 -07:00
|
|
|
CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "nonexistcommand", "-opt", NULL);
|
2017-07-21 12:12:59 -07:00
|
|
|
ReportRequestSet requests;
|
|
|
|
// timeout will return first
|
|
|
|
ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
|
2017-08-25 18:11:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, TestFilterPiiTaggedFields) {
|
|
|
|
TemporaryFile tf;
|
|
|
|
FileSection fs(NOOP_PARSER, tf.path);
|
|
|
|
ReportRequestSet requests;
|
|
|
|
|
|
|
|
ASSERT_TRUE(tf.fd != -1);
|
2017-11-09 21:45:29 -08:00
|
|
|
ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
|
2017-08-25 18:11:58 -07:00
|
|
|
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
|
|
|
|
CaptureStdout();
|
|
|
|
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
|
|
|
|
EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
|
2017-09-05 13:44:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, TestBadFdRequest) {
|
|
|
|
TemporaryFile input;
|
|
|
|
FileSection fs(NOOP_PARSER, input.path);
|
|
|
|
ReportRequestSet requests;
|
2017-11-09 21:45:29 -08:00
|
|
|
ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, input.path));
|
2017-09-05 13:44:22 -07:00
|
|
|
|
|
|
|
IncidentReportArgs args;
|
|
|
|
args.setAll(true);
|
|
|
|
args.setDest(0);
|
|
|
|
sp<ReportRequest> badFdRequest = new ReportRequest(args, new SimpleListener(), 1234567);
|
|
|
|
requests.add(badFdRequest);
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
|
|
|
|
CaptureStdout();
|
|
|
|
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
|
|
|
|
EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
|
|
|
|
EXPECT_EQ(badFdRequest->err, -EBADF);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, TestBadRequests) {
|
|
|
|
TemporaryFile input;
|
|
|
|
FileSection fs(NOOP_PARSER, input.path);
|
|
|
|
ReportRequestSet requests;
|
2017-11-09 21:45:29 -08:00
|
|
|
ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, input.path));
|
2017-09-05 13:44:22 -07:00
|
|
|
|
|
|
|
IncidentReportArgs args;
|
|
|
|
args.setAll(true);
|
|
|
|
args.setDest(0);
|
|
|
|
requests.add(new ReportRequest(args, new SimpleListener(), -1));
|
|
|
|
EXPECT_EQ(fs.Execute(&requests), -EBADF);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, TestMultipleRequests) {
|
|
|
|
TemporaryFile input, output1, output2, output3;
|
|
|
|
FileSection fs(NOOP_PARSER, input.path);
|
|
|
|
ReportRequestSet requests;
|
|
|
|
|
|
|
|
ASSERT_TRUE(input.fd != -1);
|
|
|
|
ASSERT_TRUE(output1.fd != -1);
|
|
|
|
ASSERT_TRUE(output2.fd != -1);
|
|
|
|
ASSERT_TRUE(output3.fd != -1);
|
2017-11-09 21:45:29 -08:00
|
|
|
ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, input.path));
|
2017-09-05 13:44:22 -07:00
|
|
|
|
|
|
|
IncidentReportArgs args1, args2, args3;
|
|
|
|
args1.setAll(true);
|
|
|
|
args1.setDest(0); // LOCAL
|
|
|
|
args2.setAll(true); // default to explicit
|
|
|
|
sp<SimpleListener> l = new SimpleListener();
|
|
|
|
requests.add(new ReportRequest(args1, l, output1.fd));
|
|
|
|
requests.add(new ReportRequest(args2, l, output2.fd));
|
|
|
|
requests.add(new ReportRequest(args3, l, output3.fd));
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
|
|
|
|
CaptureStdout();
|
|
|
|
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
|
|
|
|
EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
|
|
|
|
|
|
|
|
string content, expect;
|
|
|
|
expect = VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3;
|
|
|
|
char c = (char) expect.size();
|
|
|
|
EXPECT_TRUE(ReadFileToString(output1.path, &content));
|
|
|
|
EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
|
|
|
|
|
|
|
|
expect = STRING_FIELD_2 + FIX64_FIELD_3;
|
|
|
|
c = (char) expect.size();
|
|
|
|
EXPECT_TRUE(ReadFileToString(output2.path, &content));
|
|
|
|
EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
|
|
|
|
|
|
|
|
// because args3 doesn't set section, so it should receive nothing
|
|
|
|
EXPECT_TRUE(ReadFileToString(output3.path, &content));
|
|
|
|
EXPECT_THAT(content, StrEq(""));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(SectionTest, TestMultipleRequestsBySpec) {
|
|
|
|
TemporaryFile input, output1, output2, output3;
|
|
|
|
FileSection fs(NOOP_PARSER, input.path);
|
|
|
|
ReportRequestSet requests;
|
|
|
|
|
|
|
|
ASSERT_TRUE(input.fd != -1);
|
|
|
|
ASSERT_TRUE(output1.fd != -1);
|
|
|
|
ASSERT_TRUE(output2.fd != -1);
|
|
|
|
ASSERT_TRUE(output3.fd != -1);
|
|
|
|
|
2017-11-09 21:45:29 -08:00
|
|
|
ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, input.path));
|
2017-09-05 13:44:22 -07:00
|
|
|
|
|
|
|
IncidentReportArgs args1, args2, args3, args4;
|
|
|
|
args1.setAll(true);
|
|
|
|
args2.setAll(true);
|
|
|
|
args4.setAll(true);
|
|
|
|
sp<SimpleListener> l = new SimpleListener();
|
|
|
|
requests.add(new ReportRequest(args1, l, output1.fd));
|
|
|
|
requests.add(new ReportRequest(args2, l, output2.fd));
|
|
|
|
requests.add(new ReportRequest(args3, l, output3.fd));
|
|
|
|
requests.setMainFd(STDOUT_FILENO);
|
|
|
|
|
|
|
|
CaptureStdout();
|
|
|
|
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
|
|
|
|
EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
|
|
|
|
|
|
|
|
string content, expect;
|
|
|
|
expect = STRING_FIELD_2 + FIX64_FIELD_3;
|
|
|
|
char c = (char) expect.size();
|
|
|
|
|
|
|
|
// output1 and output2 are the same
|
|
|
|
EXPECT_TRUE(ReadFileToString(output1.path, &content));
|
|
|
|
EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
|
|
|
|
EXPECT_TRUE(ReadFileToString(output2.path, &content));
|
|
|
|
EXPECT_THAT(content, StrEq(string("\x02") + c + expect));
|
|
|
|
|
|
|
|
// because args3 doesn't set section, so it should receive nothing
|
|
|
|
EXPECT_TRUE(ReadFileToString(output3.path, &content));
|
|
|
|
EXPECT_THAT(content, StrEq(""));
|
2017-06-22 19:23:11 -07:00
|
|
|
}
|