blob: c57535a6c10df4127ca9df2bb163050bf492dc77 [file] [log] [blame]
Felipe Leme4c2d6632016-09-28 14:32:00 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Felipe Leme75876a22016-10-27 16:31:27 -070017#define LOG_TAG "dumpstate"
18#include <cutils/log.h>
19
Felipe Lemef0292972016-11-22 13:57:05 -080020#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070021#include "DumpstateService.h"
22#include "android/os/BnDumpstate.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070023#include "dumpstate.h"
24
25#include <gmock/gmock.h>
26#include <gtest/gtest.h>
27
Felipe Leme46b85da2016-11-21 17:40:45 -080028#include <fcntl.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070029#include <libgen.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070030#include <signal.h>
31#include <sys/types.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070032#include <unistd.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070033#include <thread>
Felipe Leme4c2d6632016-09-28 14:32:00 -070034
35#include <android-base/file.h>
Felipe Lemed80e6b62016-10-03 13:08:14 -070036#include <android-base/properties.h>
37#include <android-base/stringprintf.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070038#include <android-base/strings.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070039
Felipe Leme47e9be22016-12-21 15:37:07 -080040namespace android {
41namespace os {
42namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070043
Felipe Leme4c2d6632016-09-28 14:32:00 -070044using ::testing::EndsWith;
Felipe Leme46b85da2016-11-21 17:40:45 -080045using ::testing::HasSubstr;
Felipe Leme009ecbb2016-11-07 10:18:44 -080046using ::testing::IsNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070047using ::testing::IsEmpty;
Felipe Leme009ecbb2016-11-07 10:18:44 -080048using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070049using ::testing::StrEq;
50using ::testing::StartsWith;
51using ::testing::Test;
52using ::testing::internal::CaptureStderr;
53using ::testing::internal::CaptureStdout;
54using ::testing::internal::GetCapturedStderr;
55using ::testing::internal::GetCapturedStdout;
56
Nandana Dutt3f8c7172018-09-25 12:01:54 +010057#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
58
Felipe Leme75876a22016-10-27 16:31:27 -070059class DumpstateListenerMock : public IDumpstateListener {
60 public:
61 MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
62 MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
Vishnu Nair20cf5032018-01-05 13:15:49 -080063 MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
64 int32_t size, int32_t durationMs));
Felipe Leme75876a22016-10-27 16:31:27 -070065
66 protected:
67 MOCK_METHOD0(onAsBinder, IBinder*());
68};
69
Felipe Leme46b85da2016-11-21 17:40:45 -080070static int calls_;
71
Felipe Leme7447d7c2016-11-03 18:12:22 -070072// Base class for all tests in this file
73class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080074 public:
75 virtual void SetUp() override {
76 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080077 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080078 }
79
Felipe Lemef0292972016-11-22 13:57:05 -080080 void SetDryRun(bool dry_run) const {
81 PropertiesHelper::dry_run_ = dry_run;
82 }
83
84 void SetBuildType(const std::string& build_type) const {
85 PropertiesHelper::build_type_ = build_type;
86 }
87
88 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -080089 return calls_ == 1;
90 }
91
Felipe Lemef0292972016-11-22 13:57:05 -080092 void DropRoot() const {
93 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -080094 uid_t uid = getuid();
95 ASSERT_EQ(2000, (int)uid);
96 }
97
Felipe Leme7447d7c2016-11-03 18:12:22 -070098 protected:
99 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
100 const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
Felipe Leme7fb8dee2017-08-25 10:15:01 -0700101 const std::string kTestDataPath = kFixturesPath + "tests/testdata/";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700102 const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
103 const std::string kEchoCommand = "/system/bin/echo";
104
105 /*
106 * Copies a text file fixture to a temporary file, returning it's path.
107 *
108 * Useful in cases where the test case changes the content of the tile.
109 */
110 std::string CopyTextFileFixture(const std::string& relative_name) {
111 std::string from = kTestDataPath + relative_name;
112 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
113 // around for poking when the test fails.
114 std::string to = kTestDataPath + relative_name + ".tmp";
115 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
116 android::base::RemoveFileIfExists(to);
117 CopyTextFile(from, to);
118 return to.c_str();
119 }
120
Felipe Leme46b85da2016-11-21 17:40:45 -0800121 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700122 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800123 void ReadFileToString(const std::string& path, std::string* content) {
124 ASSERT_TRUE(android::base::ReadFileToString(path, content))
125 << "could not read contents from " << path;
126 }
127 void WriteStringToFile(const std::string& content, const std::string& path) {
128 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
129 << "could not write contents to " << path;
130 }
131
132 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700133 void CopyTextFile(const std::string& from, const std::string& to) {
134 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800135 ReadFileToString(from, &content);
136 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700137 }
138};
139
140class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700141 public:
142 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800143 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700144 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700145 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700146 ds.progress_.reset(new Progress());
Felipe Leme9a523ae2016-10-20 15:10:33 -0700147 ds.update_progress_ = false;
Felipe Leme009ecbb2016-11-07 10:18:44 -0800148 ds.update_progress_threshold_ = 0;
Nandana Dutt3f8c7172018-09-25 12:01:54 +0100149 ds.options_ = Dumpstate::DumpOptions();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700150 }
151
152 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700153 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700154 const CommandOptions& options = CommandOptions::DEFAULT) {
155 CaptureStdout();
156 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700157 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700158 out = GetCapturedStdout();
159 err = GetCapturedStderr();
160 return status;
161 }
162
Felipe Lemecef02982016-10-03 17:22:22 -0700163 // Dumps a file and capture `stdout` and `stderr`.
164 int DumpFile(const std::string& title, const std::string& path) {
165 CaptureStdout();
166 CaptureStderr();
167 int status = ds.DumpFile(title, path);
168 out = GetCapturedStdout();
169 err = GetCapturedStderr();
170 return status;
171 }
172
Felipe Leme009ecbb2016-11-07 10:18:44 -0800173 void SetProgress(long progress, long initial_max, long threshold = 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700174 ds.update_progress_ = true;
Felipe Leme009ecbb2016-11-07 10:18:44 -0800175 ds.update_progress_threshold_ = threshold;
176 ds.last_updated_progress_ = 0;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700177 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
178 }
179
Felipe Leme7447d7c2016-11-03 18:12:22 -0700180 std::string GetProgressMessage(const std::string& listener_name, int progress, int max,
Felipe Leme009ecbb2016-11-07 10:18:44 -0800181 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700182 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
183 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700184
Felipe Leme7447d7c2016-11-03 18:12:22 -0700185 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700186
Felipe Leme009ecbb2016-11-07 10:18:44 -0800187 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700188 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800189 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700190 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700191 }
192
Felipe Leme009ecbb2016-11-07 10:18:44 -0800193 if (update_progress) {
194 message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
195 listener_name.c_str(), progress, max);
196 }
197
198 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700199 }
200
Felipe Leme4c2d6632016-09-28 14:32:00 -0700201 // `stdout` and `stderr` from the last command ran.
202 std::string out, err;
203
Felipe Lemefd8affa2016-09-30 17:38:57 -0700204 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700205};
206
Nandana Dutt3f8c7172018-09-25 12:01:54 +0100207TEST_F(DumpstateTest, ParseCommandlineOptionsNone) {
208 // clang-format off
209 char* argv[] = {
210 const_cast<char*>("dumpstate")
211 };
212 // clang-format on
213
214 int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
215 EXPECT_EQ(-1, ret);
216 EXPECT_FALSE(ds.options_.do_add_date);
217 EXPECT_FALSE(ds.options_.do_zip_file);
218 EXPECT_EQ("", ds.options_.use_outfile);
219 EXPECT_FALSE(ds.options_.use_socket);
220 EXPECT_FALSE(ds.options_.use_control_socket);
221 EXPECT_FALSE(ds.options_.show_header_only);
222 EXPECT_TRUE(ds.options_.do_vibrate);
223 EXPECT_FALSE(ds.options_.do_fb);
224 EXPECT_FALSE(ds.update_progress_);
225 EXPECT_FALSE(ds.options_.is_remote_mode);
226 EXPECT_FALSE(ds.options_.do_broadcast);
227}
228
229TEST_F(DumpstateTest, ParseCommandlineOptionsPartial1) {
230 // clang-format off
231 char* argv[] = {
232 const_cast<char*>("dumpstate"),
233 const_cast<char*>("-d"),
234 const_cast<char*>("-z"),
235 const_cast<char*>("-o abc"),
236 const_cast<char*>("-s"),
237 const_cast<char*>("-S"),
238
239 };
240 // clang-format on
241 int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
242 EXPECT_EQ(-1, ret);
243 EXPECT_TRUE(ds.options_.do_add_date);
244 EXPECT_TRUE(ds.options_.do_zip_file);
245 // TODO: Maybe we should trim the filename
246 EXPECT_EQ(" abc", std::string(ds.options_.use_outfile));
247 EXPECT_TRUE(ds.options_.use_socket);
248 EXPECT_TRUE(ds.options_.use_control_socket);
249
250 // Other options retain default values
251 EXPECT_FALSE(ds.options_.show_header_only);
252 EXPECT_TRUE(ds.options_.do_vibrate);
253 EXPECT_FALSE(ds.options_.do_fb);
254 EXPECT_FALSE(ds.update_progress_);
255 EXPECT_FALSE(ds.options_.is_remote_mode);
256 EXPECT_FALSE(ds.options_.do_broadcast);
257}
258
259TEST_F(DumpstateTest, ParseCommandlineOptionsPartial2) {
260 // clang-format off
261 char* argv[] = {
262 const_cast<char*>("dumpstate"),
263 const_cast<char*>("-v"),
264 const_cast<char*>("-q"),
265 const_cast<char*>("-p"),
266 const_cast<char*>("-P"),
267 const_cast<char*>("-R"),
268 const_cast<char*>("-B"),
269 };
270 // clang-format on
271 int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
272 EXPECT_EQ(-1, ret);
273 EXPECT_TRUE(ds.options_.show_header_only);
274 EXPECT_FALSE(ds.options_.do_vibrate);
275 EXPECT_TRUE(ds.options_.do_fb);
276 EXPECT_TRUE(ds.update_progress_);
277 EXPECT_TRUE(ds.options_.is_remote_mode);
278 EXPECT_TRUE(ds.options_.do_broadcast);
279
280 // Other options retain default values
281 EXPECT_FALSE(ds.options_.do_add_date);
282 EXPECT_FALSE(ds.options_.do_zip_file);
283 EXPECT_EQ("", ds.options_.use_outfile);
284 EXPECT_FALSE(ds.options_.use_socket);
285 EXPECT_FALSE(ds.options_.use_control_socket);
286}
287
288TEST_F(DumpstateTest, ParseCommandlineOptionsHelp) {
289 // clang-format off
290 char* argv[] = {
291 const_cast<char*>("dumpstate"),
292 const_cast<char*>("-h")
293 };
294 // clang-format on
295 int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
296
297 // -h is for help. Caller exit with code = 0 after printing usage, so expect return = 0.
298 EXPECT_EQ(0, ret);
299}
300
301TEST_F(DumpstateTest, ParseCommandlineOptionsUnknown) {
302 // clang-format off
303 char* argv[] = {
304 const_cast<char*>("dumpstate"),
305 const_cast<char*>("-u") // unknown flag
306 };
307 // clang-format on
308 int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
309
310 // -u is unknown. Caller exit with code = 1 to show execution failure, after printing usage,
311 // so expect return = 1.
312 EXPECT_EQ(1, ret);
313}
314
315TEST_F(DumpstateTest, ValidateOptionsNeedOutfile1) {
316 ds.options_.do_zip_file = true;
317 EXPECT_FALSE(ds.ValidateOptions());
318 ds.options_.use_outfile = "a/b/c";
319 EXPECT_TRUE(ds.ValidateOptions());
320}
321
322TEST_F(DumpstateTest, ValidateOptionsNeedOutfile2) {
323 ds.options_.do_broadcast = true;
324 EXPECT_FALSE(ds.ValidateOptions());
325 ds.options_.use_outfile = "a/b/c";
326 EXPECT_TRUE(ds.ValidateOptions());
327}
328
329TEST_F(DumpstateTest, ValidateOptionsNeedZipfile) {
330 ds.options_.use_control_socket = true;
331 EXPECT_FALSE(ds.ValidateOptions());
332
333 ds.options_.do_zip_file = true;
334 ds.options_.use_outfile = "a/b/c"; // do_zip_file needs outfile
335 EXPECT_TRUE(ds.ValidateOptions());
336}
337
338TEST_F(DumpstateTest, ValidateOptionsUpdateProgressNeedsBroadcast) {
339 ds.update_progress_ = true;
340 ds.options_.use_outfile = "a/b/c"; // update_progress_ needs outfile
341 EXPECT_FALSE(ds.ValidateOptions());
342
343 ds.options_.do_broadcast = true;
344 EXPECT_TRUE(ds.ValidateOptions());
345}
346
347TEST_F(DumpstateTest, ValidateOptionsRemoteMode) {
348 ds.options_.is_remote_mode = true;
349 EXPECT_FALSE(ds.ValidateOptions());
350
351 ds.options_.do_broadcast = true;
352 ds.options_.do_zip_file = true;
353 ds.options_.do_add_date = true;
354 ds.options_.use_outfile = "a/b/c"; // do_broadcast needs outfile
355 EXPECT_TRUE(ds.ValidateOptions());
356}
357
Felipe Leme4c2d6632016-09-28 14:32:00 -0700358TEST_F(DumpstateTest, RunCommandNoArgs) {
359 EXPECT_EQ(-1, RunCommand("", {}));
360}
361
362TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700363 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700364 EXPECT_THAT(out, StrEq("stdout\n"));
365 EXPECT_THAT(err, StrEq("stderr\n"));
366}
367
368TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700369 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700370 EXPECT_THAT(err, StrEq("stderr\n"));
371 // We don't know the exact duration, so we check the prefix and suffix
Felipe Lemefd8affa2016-09-30 17:38:57 -0700372 EXPECT_THAT(out,
Felipe Leme7447d7c2016-11-03 18:12:22 -0700373 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700374 EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
375}
376
Felipe Lemefd8affa2016-09-30 17:38:57 -0700377TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700378 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700379 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700380 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
381 EXPECT_THAT(out, StrEq("stdout\n"));
382 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
383}
384
385TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700386 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700387 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700388 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700389 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700390}
391
392TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700393 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700394 EXPECT_THAT(err, IsEmpty());
395 EXPECT_THAT(out, StrEq("one\n"));
396}
397
Felipe Lemefd8affa2016-09-30 17:38:57 -0700398TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700399 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700400 EXPECT_THAT(err, IsEmpty());
401 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
402}
403
404TEST_F(DumpstateTest, RunCommandDryRun) {
405 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700406 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700407 // We don't know the exact duration, so we check the prefix and suffix
Felipe Leme7447d7c2016-11-03 18:12:22 -0700408 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Felipe Leme4c2d6632016-09-28 14:32:00 -0700409 ") ------\n\t(skipped on dry run)\n------"));
410 EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
411 EXPECT_THAT(err, IsEmpty());
412}
413
414TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
415 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700416 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700417 EXPECT_THAT(out, IsEmpty());
418 EXPECT_THAT(err, IsEmpty());
419}
420
421TEST_F(DumpstateTest, RunCommandDryRunAlways) {
422 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700423 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700424 EXPECT_THAT(out, StrEq("stdout\n"));
425 EXPECT_THAT(err, StrEq("stderr\n"));
426}
427
Felipe Lemefd8affa2016-09-30 17:38:57 -0700428TEST_F(DumpstateTest, RunCommandNotFound) {
429 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
430 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
431 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
432}
433
434TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700435 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
436 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700437 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700438 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700439 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700440}
441
442TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700443 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700444 // We don't know the exit code, so check just the prefix.
445 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700446 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700447 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700448 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700449}
450
451TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700452 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700453 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700454 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700455 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700456 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700457 " --sleep 2' timed out after 1"));
458}
459
460TEST_F(DumpstateTest, RunCommandIsKilled) {
461 CaptureStdout();
462 CaptureStderr();
463
464 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700465 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700466 CommandOptions::WithTimeout(100).Always().Build()));
467 });
468
469 // Capture pid and pre-sleep output.
470 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
471 std::string err = GetCapturedStderr();
472 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
473
474 std::string out = GetCapturedStdout();
475 std::vector<std::string> lines = android::base::Split(out, "\n");
476 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
477
478 int pid = atoi(lines[0].c_str());
479 EXPECT_THAT(lines[1], StrEq("stdout line1"));
480 EXPECT_THAT(lines[2], IsEmpty()); // \n
481
482 // Then kill the process.
483 CaptureStdout();
484 CaptureStderr();
485 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
486 t.join();
487
488 // Finally, check output after murder.
489 out = GetCapturedStdout();
490 err = GetCapturedStderr();
491
Felipe Leme7447d7c2016-11-03 18:12:22 -0700492 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700493 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700494 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700495 " --pid --sleep 20' failed: killed by signal 15\n"));
496}
497
Felipe Leme75876a22016-10-27 16:31:27 -0700498TEST_F(DumpstateTest, RunCommandProgress) {
499 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
500 ds.listener_ = listener;
501 ds.listener_name_ = "FoxMulder";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700502 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700503
504 EXPECT_CALL(*listener, onProgressUpdated(20));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700505 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Felipe Leme75876a22016-10-27 16:31:27 -0700506 std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
507 EXPECT_THAT(out, StrEq("stdout\n"));
508 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
509
510 EXPECT_CALL(*listener, onProgressUpdated(30));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700511 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
Felipe Leme75876a22016-10-27 16:31:27 -0700512 progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
513 EXPECT_THAT(out, StrEq("stdout\n"));
514 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
515
516 // Run a command that will increase maximum timeout.
517 EXPECT_CALL(*listener, onProgressUpdated(31));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700518 EXPECT_CALL(*listener, onMaxProgressUpdated(37));
519 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
520 progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase
Felipe Leme75876a22016-10-27 16:31:27 -0700521 EXPECT_THAT(out, StrEq("stdout\n"));
522 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
523
524 // Make sure command ran while in dry_run is counted.
525 SetDryRun(true);
526 EXPECT_CALL(*listener, onProgressUpdated(35));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700527 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
528 progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
Felipe Leme75876a22016-10-27 16:31:27 -0700529 EXPECT_THAT(out, IsEmpty());
530 EXPECT_THAT(err, StrEq(progress_message));
531
532 ds.listener_.clear();
533}
534
Felipe Leme009ecbb2016-11-07 10:18:44 -0800535TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
536 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
537 ds.listener_ = listener;
538 ds.listener_name_ = "FoxMulder";
539 SetProgress(0, 8, 5); // 8 max, 5 threshold
540
541 // First update should always be sent.
542 EXPECT_CALL(*listener, onProgressUpdated(1));
543 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
544 std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
545 EXPECT_THAT(out, StrEq("stdout\n"));
546 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
547
548 // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
549 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
550 EXPECT_THAT(out, StrEq("stdout\n"));
551 EXPECT_THAT(err, StrEq("stderr\n"));
552
553 // Third update should be sent because it reaches threshold (6 - 1 = 5).
554 EXPECT_CALL(*listener, onProgressUpdated(6));
555 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
556 progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
557 EXPECT_THAT(out, StrEq("stdout\n"));
558 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
559
560 // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
561 // But max update should be sent.
562 EXPECT_CALL(*listener, onMaxProgressUpdated(10)); // 9 * 120% = 10.8 = 10
563 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
564 progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
565 EXPECT_THAT(out, StrEq("stdout\n"));
566 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
567
568 ds.listener_.clear();
569}
570
Felipe Lemed80e6b62016-10-03 13:08:14 -0700571TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800572 if (!IsStandalone()) {
573 // TODO: temporarily disabled because it might cause other tests to fail after dropping
574 // to Shell - need to refactor tests to avoid this problem)
575 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
576 return;
577 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700578 // First check root case - only available when running with 'adb root'.
579 uid_t uid = getuid();
580 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700581 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700582 EXPECT_THAT(out, StrEq("0\nstdout\n"));
583 EXPECT_THAT(err, StrEq("stderr\n"));
584 return;
585 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700586 // Then run dropping root.
587 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700588 CommandOptions::WithTimeout(1).DropRoot().Build()));
589 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700590 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700591}
592
593TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800594 if (!IsStandalone()) {
595 // TODO: temporarily disabled because it might cause other tests to fail after dropping
596 // to Shell - need to refactor tests to avoid this problem)
597 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
598 return;
599 }
Felipe Lemef0292972016-11-22 13:57:05 -0800600 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700601 // Emulates user build if necessarily.
602 SetBuildType("user");
603 }
604
605 DropRoot();
606
Felipe Leme7447d7c2016-11-03 18:12:22 -0700607 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700608
609 // We don't know the exact path of su, so we just check for the 'root ...' commands
610 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700611 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700612 EXPECT_THAT(err, IsEmpty());
613}
614
Felipe Leme46b85da2016-11-21 17:40:45 -0800615TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
616 if (!IsStandalone()) {
617 // TODO: temporarily disabled because it might cause other tests to fail after dropping
618 // to Shell - need to refactor tests to avoid this problem)
619 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
620 return;
621 }
Felipe Lemef0292972016-11-22 13:57:05 -0800622 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800623 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
624 return;
625 }
626
627 DropRoot();
628
629 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
630 CommandOptions::WithTimeout(1).AsRoot().Build()));
631
632 EXPECT_THAT(out, StrEq("0\nstdout\n"));
633 EXPECT_THAT(err, StrEq("stderr\n"));
634}
635
Yifan Hong48e83a12017-10-03 14:10:07 -0700636TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
637 if (!IsStandalone()) {
638 // TODO: temporarily disabled because it might cause other tests to fail after dropping
639 // to Shell - need to refactor tests to avoid this problem)
640 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
641 return;
642 }
643 if (!PropertiesHelper::IsUserBuild()) {
644 // Emulates user build if necessarily.
645 SetBuildType("user");
646 }
647
648 DropRoot();
649
650 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
651 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
652
653 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
654 EXPECT_THAT(err, StrEq("stderr\n"));
655}
656
657TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
658 if (!IsStandalone()) {
659 // TODO: temporarily disabled because it might cause other tests to fail after dropping
660 // to Shell - need to refactor tests to avoid this problem)
661 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
662 return;
663 }
664 if (PropertiesHelper::IsUserBuild()) {
665 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
666 return;
667 }
668
669 DropRoot();
670
671 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
672 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
673
674 EXPECT_THAT(out, StrEq("0\nstdout\n"));
675 EXPECT_THAT(err, StrEq("stderr\n"));
676}
677
Felipe Lemecef02982016-10-03 17:22:22 -0700678TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
679 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
680 EXPECT_THAT(out,
681 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
682 EXPECT_THAT(err, IsEmpty());
683}
684
685TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
686 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
687 EXPECT_THAT(err, IsEmpty());
688 // We don't know the exact duration, so we check the prefix and suffix
689 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
690 "such file or directory\n"));
691 EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n"));
692}
693
694TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700695 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700696 EXPECT_THAT(err, IsEmpty());
697 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
698}
699
700TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700701 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700702 EXPECT_THAT(err, IsEmpty());
703 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
704}
705
706TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700707 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700708 EXPECT_THAT(err, IsEmpty());
709 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
710}
711
712TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700713 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700714 EXPECT_THAT(err, IsEmpty());
715 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
716}
717
718TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
719 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700720 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700721 EXPECT_THAT(err, IsEmpty());
722 EXPECT_THAT(out, IsEmpty());
723}
724
725TEST_F(DumpstateTest, DumpFileOnDryRun) {
726 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700727 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700728 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -0800729 EXPECT_THAT(
730 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
731 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n------"));
Felipe Lemecef02982016-10-03 17:22:22 -0700732 EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700733}
734
Felipe Leme75876a22016-10-27 16:31:27 -0700735TEST_F(DumpstateTest, DumpFileUpdateProgress) {
736 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
737 ds.listener_ = listener;
738 ds.listener_name_ = "FoxMulder";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700739 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700740
741 EXPECT_CALL(*listener, onProgressUpdated(5));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700742 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -0700743
744 std::string progress_message =
745 GetProgressMessage(ds.listener_name_, 5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
746 EXPECT_THAT(err, StrEq(progress_message));
747 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
748
749 ds.listener_.clear();
750}
751
Felipe Leme7447d7c2016-11-03 18:12:22 -0700752class DumpstateServiceTest : public DumpstateBaseTest {
Felipe Leme75876a22016-10-27 16:31:27 -0700753 public:
754 DumpstateService dss;
755};
756
757TEST_F(DumpstateServiceTest, SetListenerNoName) {
758 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800759 sp<IDumpstateToken> token;
Vishnu Nair20cf5032018-01-05 13:15:49 -0800760 EXPECT_TRUE(dss.setListener("", listener, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800761 ASSERT_THAT(token, IsNull());
Felipe Leme75876a22016-10-27 16:31:27 -0700762}
763
764TEST_F(DumpstateServiceTest, SetListenerNoPointer) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800765 sp<IDumpstateToken> token;
Vishnu Nair20cf5032018-01-05 13:15:49 -0800766 EXPECT_TRUE(
767 dss.setListener("whatever", nullptr, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800768 ASSERT_THAT(token, IsNull());
Felipe Leme75876a22016-10-27 16:31:27 -0700769}
770
771TEST_F(DumpstateServiceTest, SetListenerTwice) {
772 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800773 sp<IDumpstateToken> token;
Vishnu Nair20cf5032018-01-05 13:15:49 -0800774 EXPECT_TRUE(
775 dss.setListener("whatever", listener, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800776 ASSERT_THAT(token, NotNull());
Felipe Leme75876a22016-10-27 16:31:27 -0700777 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
Vishnu Nair20cf5032018-01-05 13:15:49 -0800778 EXPECT_FALSE(Dumpstate::GetInstance().report_section_);
Felipe Leme75876a22016-10-27 16:31:27 -0700779
Felipe Leme009ecbb2016-11-07 10:18:44 -0800780 token.clear();
Vishnu Nair20cf5032018-01-05 13:15:49 -0800781 EXPECT_TRUE(
782 dss.setListener("whatsoever", listener, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800783 ASSERT_THAT(token, IsNull());
784 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
Vishnu Nair20cf5032018-01-05 13:15:49 -0800785 EXPECT_FALSE(Dumpstate::GetInstance().report_section_);
786}
787
788TEST_F(DumpstateServiceTest, SetListenerWithSectionDetails) {
789 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
790 sp<IDumpstateToken> token;
791 Dumpstate::GetInstance().listener_ = nullptr;
792 EXPECT_TRUE(
793 dss.setListener("whatever", listener, /* getSectionDetails = */ true, &token).isOk());
794 ASSERT_THAT(token, NotNull());
795 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
796 EXPECT_TRUE(Dumpstate::GetInstance().report_section_);
Felipe Leme75876a22016-10-27 16:31:27 -0700797}
Felipe Leme7447d7c2016-11-03 18:12:22 -0700798
799class ProgressTest : public DumpstateBaseTest {
800 public:
801 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
802 return Progress(max, growth_factor, path);
803 }
804
805 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
806 std::string expected_content =
807 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
808 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800809 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700810 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
811 }
812};
813
814TEST_F(ProgressTest, SimpleTest) {
815 Progress progress;
816 EXPECT_EQ(0, progress.Get());
817 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
818 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
819
820 bool max_increased = progress.Inc(1);
821 EXPECT_EQ(1, progress.Get());
822 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
823 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
824 EXPECT_FALSE(max_increased);
825
826 // Ignore negative increase.
827 max_increased = progress.Inc(-1);
828 EXPECT_EQ(1, progress.Get());
829 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
830 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
831 EXPECT_FALSE(max_increased);
832}
833
834TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
835 Progress progress = GetInstance(10, 1.2); // 20% growth factor
836 EXPECT_EQ(0, progress.Get());
837 EXPECT_EQ(10, progress.GetInitialMax());
838 EXPECT_EQ(10, progress.GetMax());
839
840 // No increase
841 bool max_increased = progress.Inc(10);
842 EXPECT_EQ(10, progress.Get());
843 EXPECT_EQ(10, progress.GetMax());
844 EXPECT_FALSE(max_increased);
845
846 // Increase, with new value < max*20%
847 max_increased = progress.Inc(1);
848 EXPECT_EQ(11, progress.Get());
849 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
850 EXPECT_TRUE(max_increased);
851}
852
853TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
854 Progress progress = GetInstance(10, 1.2); // 20% growth factor
855 EXPECT_EQ(0, progress.Get());
856 EXPECT_EQ(10, progress.GetInitialMax());
857 EXPECT_EQ(10, progress.GetMax());
858
859 // No increase
860 bool max_increased = progress.Inc(10);
861 EXPECT_EQ(10, progress.Get());
862 EXPECT_EQ(10, progress.GetMax());
863 EXPECT_FALSE(max_increased);
864
865 // Increase, with new value > max*20%
866 max_increased = progress.Inc(5);
867 EXPECT_EQ(15, progress.Get());
868 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
869 EXPECT_TRUE(max_increased);
870}
871
872TEST_F(ProgressTest, InvalidPath) {
873 Progress progress("/devil/null");
874 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
875}
876
877TEST_F(ProgressTest, EmptyFile) {
878 Progress progress(CopyTextFileFixture("empty-file.txt"));
879 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
880}
881
882TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
883 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
884 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
885}
886
887TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
888 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
889 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
890}
891
892TEST_F(ProgressTest, InvalidLineBothNAN) {
893 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
894 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
895}
896
897TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
898 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
899 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
900}
901
902TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
903 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
904 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
905}
906
907TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
908 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
909 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
910}
911
912TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
913 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
914 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
915}
916
917// Tests stats are properly saved when the file does not exists.
918TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800919 if (!IsStandalone()) {
920 // TODO: temporarily disabled because it's failing when running as suite
921 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
922 return;
923 }
924
Felipe Leme7447d7c2016-11-03 18:12:22 -0700925 std::string path = kTestDataPath + "FirstTime.txt";
926 android::base::RemoveFileIfExists(path);
927
928 Progress run1(path);
929 EXPECT_EQ(0, run1.Get());
930 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
931 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
932
933 bool max_increased = run1.Inc(20);
934 EXPECT_EQ(20, run1.Get());
935 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
936 EXPECT_FALSE(max_increased);
937
938 run1.Save();
939 AssertStats(path, 1, 20);
940}
941
942// Tests what happens when the persistent settings contains the average duration of 1 run.
943// Data on file is 1 run and 109 average.
944TEST_F(ProgressTest, SecondTime) {
945 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
946
947 Progress run1 = GetInstance(-42, 1.2, path);
948 EXPECT_EQ(0, run1.Get());
949 EXPECT_EQ(10, run1.GetInitialMax());
950 EXPECT_EQ(10, run1.GetMax());
951
952 bool max_increased = run1.Inc(20);
953 EXPECT_EQ(20, run1.Get());
954 EXPECT_EQ(24, run1.GetMax());
955 EXPECT_TRUE(max_increased);
956
957 // Average now is 2 runs and (10 + 20)/ 2 = 15
958 run1.Save();
959 AssertStats(path, 2, 15);
960
961 Progress run2 = GetInstance(-42, 1.2, path);
962 EXPECT_EQ(0, run2.Get());
963 EXPECT_EQ(15, run2.GetInitialMax());
964 EXPECT_EQ(15, run2.GetMax());
965
966 max_increased = run2.Inc(25);
967 EXPECT_EQ(25, run2.Get());
968 EXPECT_EQ(30, run2.GetMax());
969 EXPECT_TRUE(max_increased);
970
971 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
972 run2.Save();
973 AssertStats(path, 3, 18);
974
975 Progress run3 = GetInstance(-42, 1.2, path);
976 EXPECT_EQ(0, run3.Get());
977 EXPECT_EQ(18, run3.GetInitialMax());
978 EXPECT_EQ(18, run3.GetMax());
979
980 // Make sure average decreases as well
981 max_increased = run3.Inc(5);
982 EXPECT_EQ(5, run3.Get());
983 EXPECT_EQ(18, run3.GetMax());
984 EXPECT_FALSE(max_increased);
985
986 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
987 run3.Save();
988 AssertStats(path, 4, 14);
989}
990
991// Tests what happens when the persistent settings contains the average duration of 2 runs.
992// Data on file is 2 runs and 15 average.
993TEST_F(ProgressTest, ThirdTime) {
994 std::string path = CopyTextFileFixture("stats-two-runs.txt");
995 AssertStats(path, 2, 15); // Sanity check
996
997 Progress run1 = GetInstance(-42, 1.2, path);
998 EXPECT_EQ(0, run1.Get());
999 EXPECT_EQ(15, run1.GetInitialMax());
1000 EXPECT_EQ(15, run1.GetMax());
1001
1002 bool max_increased = run1.Inc(20);
1003 EXPECT_EQ(20, run1.Get());
1004 EXPECT_EQ(24, run1.GetMax());
1005 EXPECT_TRUE(max_increased);
1006
1007 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1008 run1.Save();
1009 AssertStats(path, 3, 16);
1010}
1011
Felipe Leme46b85da2016-11-21 17:40:45 -08001012class DumpstateUtilTest : public DumpstateBaseTest {
1013 public:
1014 void SetUp() {
1015 DumpstateBaseTest::SetUp();
1016 SetDryRun(false);
1017 }
1018
Felipe Leme46b85da2016-11-21 17:40:45 -08001019 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001020 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001021 }
1022
1023 void CreateFd(const std::string& name) {
1024 path_ = kTestDataPath + name;
1025 MYLOGD("Creating fd for file %s\n", path_.c_str());
1026
1027 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1028 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1029 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1030 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1031 }
1032
1033 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001034 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001035 const CommandOptions& options = CommandOptions::DEFAULT) {
1036 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001037 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001038 close(fd);
1039
1040 CaptureFdOut();
1041 err = GetCapturedStderr();
1042 return status;
1043 }
1044
1045 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001046 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001047 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001048 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001049 close(fd);
1050
1051 CaptureFdOut();
1052 err = GetCapturedStderr();
1053 return status;
1054 }
1055
Ecco Park61ffcf72016-10-27 15:46:26 -07001056 // Find out the pid of the process_name
1057 int FindPidOfProcess(const std::string& process_name) {
1058 CaptureStderr();
1059 int status = GetPidByName(process_name);
1060 err = GetCapturedStderr();
1061 return status;
1062 }
1063
Felipe Leme46b85da2016-11-21 17:40:45 -08001064 int fd;
1065
1066 // 'fd` output and `stderr` from the last command ran.
1067 std::string out, err;
1068
1069 private:
1070 std::string path_;
1071};
1072
1073TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001074 CreateFd("RunCommandNoArgs.txt");
1075 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001076}
1077
Felipe Lemef0292972016-11-22 13:57:05 -08001078TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001079 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001080 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001081 EXPECT_THAT(out, StrEq("stdout\n"));
1082 EXPECT_THAT(err, StrEq("stderr\n"));
1083}
1084
Felipe Lemef0292972016-11-22 13:57:05 -08001085TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1086 CreateFd("RunCommandWithNoArgs.txt");
1087 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1088 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1089 EXPECT_THAT(err, StrEq("stderr\n"));
1090}
1091
Felipe Leme46b85da2016-11-21 17:40:45 -08001092TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1093 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001094 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001095 EXPECT_THAT(err, IsEmpty());
1096 EXPECT_THAT(out, StrEq("one\n"));
1097}
1098
1099TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1100 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001101 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001102 EXPECT_THAT(err, IsEmpty());
1103 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1104}
1105
1106TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1107 CreateFd("RunCommandWithLoggingMessage.txt");
1108 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001109 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001110 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1111 EXPECT_THAT(out, StrEq("stdout\n"));
1112 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1113}
1114
1115TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1116 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001117 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1118 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001119 EXPECT_THAT(out, IsEmpty());
1120 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1121}
1122
1123TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1124 CreateFd("RunCommandDryRun.txt");
1125 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001126 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1127 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1128 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1129 kSimpleCommand.c_str())));
1130 EXPECT_THAT(err, IsEmpty());
1131}
1132
1133TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1134 CreateFd("RunCommandDryRun.txt");
1135 SetDryRun(true);
1136 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001137 EXPECT_THAT(
1138 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1139 EXPECT_THAT(err, IsEmpty());
1140}
1141
1142TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1143 CreateFd("RunCommandDryRunAlways.txt");
1144 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001145 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001146 EXPECT_THAT(out, StrEq("stdout\n"));
1147 EXPECT_THAT(err, StrEq("stderr\n"));
1148}
1149
1150TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1151 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001152 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001153 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1154 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1155}
1156
1157TEST_F(DumpstateUtilTest, RunCommandFails) {
1158 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001159 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001160 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1161 " --exit 42' failed: exit code 42\n"));
1162 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1163 " --exit 42' failed: exit code 42\n"));
1164}
1165
1166TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1167 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001168 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001169 // We don't know the exit code, so check just the prefix.
1170 EXPECT_THAT(
1171 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1172 EXPECT_THAT(
1173 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1174}
1175
Vishnu Nair6921f802017-11-22 09:17:23 -08001176TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001177 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001178 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1179 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001180 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1181 " --sleep 2' timed out after 1"));
1182 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1183 " --sleep 2' timed out after 1"));
1184}
1185
Vishnu Nair6921f802017-11-22 09:17:23 -08001186TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1187 CreateFd("RunCommandTimesout.txt");
1188 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1189 CommandOptions::WithTimeoutInMs(1000).Build()));
1190 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1191 " --sleep 2' timed out after 1"));
1192 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1193 " --sleep 2' timed out after 1"));
1194}
1195
1196
Felipe Leme46b85da2016-11-21 17:40:45 -08001197TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1198 CreateFd("RunCommandIsKilled.txt");
1199 CaptureStderr();
1200
1201 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001202 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001203 CommandOptions::WithTimeout(100).Always().Build()));
1204 });
1205
1206 // Capture pid and pre-sleep output.
1207 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1208 std::string err = GetCapturedStderr();
1209 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1210
1211 CaptureFdOut();
1212 std::vector<std::string> lines = android::base::Split(out, "\n");
1213 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1214
1215 int pid = atoi(lines[0].c_str());
1216 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1217 EXPECT_THAT(lines[2], IsEmpty()); // \n
1218
1219 // Then kill the process.
1220 CaptureFdOut();
1221 CaptureStderr();
1222 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1223 t.join();
1224
1225 // Finally, check output after murder.
1226 CaptureFdOut();
1227 err = GetCapturedStderr();
1228
1229 // out starts with the pid, which is an unknown
1230 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1231 " --pid --sleep 20' failed: killed by signal 15\n"));
1232 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1233 " --pid --sleep 20' failed: killed by signal 15\n"));
1234}
1235
1236TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1237 if (!IsStandalone()) {
1238 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1239 // to Shell - need to refactor tests to avoid this problem)
1240 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1241 return;
1242 }
1243 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001244 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001245 // Emulates user build if necessarily.
1246 SetBuildType("user");
1247 }
1248
1249 DropRoot();
1250
Felipe Lemef0292972016-11-22 13:57:05 -08001251 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001252
1253 // We don't know the exact path of su, so we just check for the 'root ...' commands
1254 EXPECT_THAT(out, StartsWith("Skipping"));
1255 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1256 EXPECT_THAT(err, IsEmpty());
1257}
1258
1259TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1260 if (!IsStandalone()) {
1261 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1262 // to Shell - need to refactor tests to avoid this problem)
1263 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1264 return;
1265 }
1266 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001267 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001268 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1269 return;
1270 }
1271
1272 DropRoot();
1273
Felipe Lemef0292972016-11-22 13:57:05 -08001274 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1275 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001276
1277 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1278 EXPECT_THAT(err, StrEq("stderr\n"));
1279}
Felipe Leme46b85da2016-11-21 17:40:45 -08001280
Yifan Hong48e83a12017-10-03 14:10:07 -07001281
1282TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1283 if (!IsStandalone()) {
1284 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1285 // to Shell - need to refactor tests to avoid this problem)
1286 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1287 return;
1288 }
1289 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1290 if (!PropertiesHelper::IsUserBuild()) {
1291 // Emulates user build if necessarily.
1292 SetBuildType("user");
1293 }
1294
1295 DropRoot();
1296
1297 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1298 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1299
1300 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1301 EXPECT_THAT(err, StrEq("stderr\n"));
1302}
1303
1304TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1305 if (!IsStandalone()) {
1306 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1307 // to Shell - need to refactor tests to avoid this problem)
1308 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1309 return;
1310 }
1311 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1312 if (PropertiesHelper::IsUserBuild()) {
1313 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1314 return;
1315 }
1316
1317 DropRoot();
1318
1319 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1320 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1321
1322 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1323 EXPECT_THAT(err, StrEq("stderr\n"));
1324}
1325
Felipe Leme46b85da2016-11-21 17:40:45 -08001326TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1327 if (!IsStandalone()) {
1328 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1329 // to Shell - need to refactor tests to avoid this problem)
1330 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1331 return;
1332 }
1333 CreateFd("RunCommandDropRoot.txt");
1334 // First check root case - only available when running with 'adb root'.
1335 uid_t uid = getuid();
1336 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001337 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001338 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1339 EXPECT_THAT(err, StrEq("stderr\n"));
1340 return;
1341 }
1342 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001343 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001344 CommandOptions::WithTimeout(1).DropRoot().Build()));
1345 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1346 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1347}
1348
Felipe Lemef0292972016-11-22 13:57:05 -08001349TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001350 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001351 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001352 EXPECT_THAT(out,
1353 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1354 EXPECT_THAT(err, IsEmpty());
1355}
1356
Felipe Lemef0292972016-11-22 13:57:05 -08001357TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1358 CreateFd("DumpFileNotFound.txt");
1359 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1360 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1361 "file or directory\n"));
1362 EXPECT_THAT(err, IsEmpty());
1363}
1364
Felipe Leme46b85da2016-11-21 17:40:45 -08001365TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1366 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001367 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001368 EXPECT_THAT(err, IsEmpty());
1369 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1370}
1371
1372TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1373 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001374 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001375 EXPECT_THAT(err, IsEmpty());
1376 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1377}
1378
1379TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1380 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001381 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001382 EXPECT_THAT(err, IsEmpty());
1383 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1384}
1385
1386TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1387 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001388 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001389 EXPECT_THAT(err, IsEmpty());
1390 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1391}
1392
Felipe Lemef0292972016-11-22 13:57:05 -08001393TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1394 CreateFd("DumpFileOnDryRun.txt");
1395 SetDryRun(true);
1396 std::string path = kTestDataPath + "single-line.txt";
1397 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1398 EXPECT_THAT(err, IsEmpty());
1399 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1400}
1401
Felipe Leme46b85da2016-11-21 17:40:45 -08001402TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1403 CreateFd("DumpFileOnDryRun.txt");
1404 SetDryRun(true);
1405 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001406 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001407 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001408 EXPECT_THAT(
1409 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1410 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001411}
Ecco Park61ffcf72016-10-27 15:46:26 -07001412
1413TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
1414 // init process always has pid 1.
1415 EXPECT_EQ(1, FindPidOfProcess("init"));
1416 EXPECT_THAT(err, IsEmpty());
1417}
1418
1419TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
1420 // find the process with abnormal name.
1421 EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
1422 EXPECT_THAT(err, StrEq("can't find the pid\n"));
1423}
Felipe Leme47e9be22016-12-21 15:37:07 -08001424
1425} // namespace dumpstate
1426} // namespace os
1427} // namespace android