PageRenderTime 78ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/cmds/incidentd/tests/Section_test.cpp

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