summaryrefslogtreecommitdiff
path: root/cmds/incidentd/tests/Section_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/incidentd/tests/Section_test.cpp')
-rw-r--r--cmds/incidentd/tests/Section_test.cpp339
1 files changed, 339 insertions, 0 deletions
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
new file mode 100644
index 000000000000..1528224447af
--- /dev/null
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -0,0 +1,339 @@
+// 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 DEBUG false
+#include "Log.h"
+
+#include "Section.h"
+
+#include <android-base/file.h>
+#include <android-base/test_utils.h>
+#include <android/os/IncidentReportArgs.h>
+#include <frameworks/base/libs/incident/proto/android/os/header.pb.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <string.h>
+
+const int TIMEOUT_PARSER = -1;
+const int NOOP_PARSER = 0;
+const int REVERSE_PARSER = 1;
+
+const int QUICK_TIMEOUT_MS = 100;
+
+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
+
+using namespace android::base;
+using namespace android::binder;
+using namespace android::os;
+using namespace std;
+using ::testing::StrEq;
+using ::testing::Test;
+using ::testing::internal::CaptureStdout;
+using ::testing::internal::GetCapturedStdout;
+
+// NOTICE: this test requires /system/bin/incident_helper is installed.
+class SectionTest : public Test {
+public:
+ virtual void SetUp() override { ASSERT_NE(tf.fd, -1); }
+
+protected:
+ TemporaryFile tf;
+ ReportRequestSet requests;
+
+ const std::string kTestPath = GetExecutableDirectory();
+ const std::string kTestDataPath = kTestPath + "/testdata/";
+};
+
+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; };
+};
+
+TEST_F(SectionTest, HeaderSection) {
+ HeaderSection hs;
+
+ IncidentReportArgs args1, args2;
+ args1.addSection(1);
+ args1.addSection(2);
+ args2.setAll(true);
+
+ IncidentHeaderProto head1, head2;
+ head1.set_reason("axe");
+ head2.set_reason("pup");
+
+ args1.addHeader(head1);
+ args1.addHeader(head2);
+ args2.addHeader(head2);
+
+ requests.add(new ReportRequest(args1, new SimpleListener(), -1));
+ requests.add(new ReportRequest(args2, new SimpleListener(), tf.fd));
+ requests.setMainFd(STDOUT_FILENO);
+
+ string content;
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, hs.Execute(&requests));
+ EXPECT_THAT(GetCapturedStdout(), StrEq("\n\x5"
+ "\x12\x3"
+ "axe\n\x05\x12\x03pup"));
+
+ EXPECT_TRUE(ReadFileToString(tf.path, &content));
+ EXPECT_THAT(content, StrEq("\n\x05\x12\x03pup"));
+}
+
+TEST_F(SectionTest, MetadataSection) {
+ MetadataSection ms;
+
+ requests.setMainFd(STDOUT_FILENO);
+ requests.sectionStats(1)->set_success(true);
+
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, ms.Execute(&requests));
+ EXPECT_THAT(GetCapturedStdout(), StrEq("\x12\b(\x1"
+ "2\x4\b\x1\x10\x1"));
+}
+
+TEST_F(SectionTest, FileSection) {
+ FileSection fs(REVERSE_PARSER, tf.path);
+
+ ASSERT_TRUE(WriteStringToFile("iamtestdata", tf.path));
+
+ 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
+ EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\vatadtsetmai"));
+}
+
+TEST_F(SectionTest, FileSectionTimeout) {
+ FileSection fs(TIMEOUT_PARSER, tf.path, QUICK_TIMEOUT_MS);
+ ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
+}
+
+TEST_F(SectionTest, GZipSection) {
+ const std::string testFile = kTestDataPath + "kmsg.txt";
+ const std::string testGzFile = testFile + ".gz";
+ GZipSection gs(NOOP_PARSER, "/tmp/nonexist", testFile.c_str(), NULL);
+
+ requests.setMainFd(tf.fd);
+ requests.setMainDest(android::os::DEST_LOCAL);
+
+ ASSERT_EQ(NO_ERROR, gs.Execute(&requests));
+ std::string expect, gzFile, actual;
+ ASSERT_TRUE(ReadFileToString(testGzFile, &gzFile));
+ ASSERT_TRUE(ReadFileToString(tf.path, &actual));
+ expect = "\x2\xC6\x6\n\"" + testFile + "\x12\x9F\x6" + gzFile;
+ EXPECT_THAT(actual, StrEq(expect));
+}
+
+TEST_F(SectionTest, GZipSectionNoFileFound) {
+ GZipSection gs(NOOP_PARSER, "/tmp/nonexist1", "/tmp/nonexist2", NULL);
+ requests.setMainFd(STDOUT_FILENO);
+ ASSERT_EQ(-1, gs.Execute(&requests));
+}
+
+TEST_F(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"));
+ 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"));
+ EXPECT_THAT(cs4.name.string(), StrEq("single_command"));
+}
+
+TEST_F(SectionTest, CommandSectionEcho) {
+ CommandSection cs(REVERSE_PARSER, "/system/bin/echo", "about", NULL);
+ requests.setMainFd(STDOUT_FILENO);
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
+ EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\x06\ntuoba"));
+}
+
+TEST_F(SectionTest, CommandSectionCommandTimeout) {
+ CommandSection cs(NOOP_PARSER, QUICK_TIMEOUT_MS, "/system/bin/yes", NULL);
+ ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
+}
+
+TEST_F(SectionTest, CommandSectionIncidentHelperTimeout) {
+ CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "/system/bin/echo", "about", NULL);
+ requests.setMainFd(STDOUT_FILENO);
+ ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
+}
+
+TEST_F(SectionTest, CommandSectionBadCommand) {
+ CommandSection cs(NOOP_PARSER, "echoo", "about", NULL);
+ ASSERT_EQ(NAME_NOT_FOUND, cs.Execute(&requests));
+}
+
+TEST_F(SectionTest, CommandSectionBadCommandAndTimeout) {
+ CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "nonexistcommand", "-opt", NULL);
+ // timeout will return first
+ ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
+}
+
+TEST_F(SectionTest, LogSectionBinary) {
+ LogSection ls(1, LOG_ID_EVENTS);
+ requests.setMainFd(STDOUT_FILENO);
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, ls.Execute(&requests));
+ string results = GetCapturedStdout();
+ EXPECT_FALSE(results.empty());
+}
+
+TEST_F(SectionTest, LogSectionSystem) {
+ LogSection ls(1, LOG_ID_SYSTEM);
+ requests.setMainFd(STDOUT_FILENO);
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, ls.Execute(&requests));
+ string results = GetCapturedStdout();
+ EXPECT_FALSE(results.empty());
+}
+
+TEST_F(SectionTest, TestFilterPiiTaggedFields) {
+ FileSection fs(NOOP_PARSER, tf.path);
+
+ ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
+
+ requests.setMainFd(STDOUT_FILENO);
+
+ CaptureStdout();
+ ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
+ EXPECT_THAT(GetCapturedStdout(), StrEq("\x02\r" + STRING_FIELD_2));
+}
+
+TEST_F(SectionTest, TestBadFdRequest) {
+ FileSection fs(NOOP_PARSER, tf.path);
+ ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
+
+ 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_F(SectionTest, TestBadRequests) {
+ FileSection fs(NOOP_PARSER, tf.path);
+ ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
+
+ IncidentReportArgs args;
+ args.setAll(true);
+ args.setDest(0);
+ requests.add(new ReportRequest(args, new SimpleListener(), -1));
+ EXPECT_EQ(fs.Execute(&requests), -EBADF);
+}
+
+TEST_F(SectionTest, TestMultipleRequests) {
+ TemporaryFile output1, output2, output3;
+ FileSection fs(NOOP_PARSER, tf.path);
+
+ ASSERT_TRUE(output1.fd != -1);
+ ASSERT_TRUE(output2.fd != -1);
+ ASSERT_TRUE(output3.fd != -1);
+ ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
+
+ IncidentReportArgs args1, args2, args3;
+ args1.setAll(true);
+ args1.setDest(android::os::DEST_LOCAL);
+ args2.setAll(true);
+ args2.setDest(android::os::DEST_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_F(SectionTest, TestMultipleRequestsBySpec) {
+ TemporaryFile output1, output2, output3;
+ FileSection fs(NOOP_PARSER, tf.path);
+
+ ASSERT_TRUE(output1.fd != -1);
+ ASSERT_TRUE(output2.fd != -1);
+ ASSERT_TRUE(output3.fd != -1);
+
+ ASSERT_TRUE(WriteStringToFile(VARINT_FIELD_1 + STRING_FIELD_2 + FIX64_FIELD_3, tf.path));
+
+ IncidentReportArgs args1, args2, args3;
+ args1.setAll(true);
+ args1.setDest(android::os::DEST_EXPLICIT);
+ args2.setAll(true);
+ args2.setDest(android::os::DEST_EXPLICIT);
+ args3.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));
+
+ // output3 has only auto field
+ c = (char)STRING_FIELD_2.size();
+ EXPECT_TRUE(ReadFileToString(output3.path, &content));
+ EXPECT_THAT(content, StrEq(string("\x02") + c + STRING_FIELD_2));
+}