Loading cmds/dumpstate/Android.mk +67 −13 Original line number Original line Diff line number Diff line LOCAL_PATH:= $(call my-dir) LOCAL_PATH:= $(call my-dir) # ================# # Common settings # # ================# # ZipArchive support, the order matters here to get all symbols. COMMON_ZIP_LIBRARIES := libziparchive libz libcrypto_static # TODO: ideally the tests should depend on a shared dumpstate library, but currently libdumpstate # is used to define the device-specific HAL library. Instead, both dumpstate and dumpstate_test # shares a lot of common settings COMMON_LOCAL_CFLAGS := \ -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter COMMON_SRC_FILES := \ utils.cpp COMMON_SHARED_LIBRARIES := \ libbase \ libcutils \ libhardware_legacy \ liblog \ libselinux # ==========# # dumpstate # # ==========# include $(CLEAR_VARS) include $(CLEAR_VARS) ifdef BOARD_WLAN_DEVICE ifdef BOARD_WLAN_DEVICE LOCAL_CFLAGS := -DFWDUMP_$(BOARD_WLAN_DEVICE) LOCAL_CFLAGS := -DFWDUMP_$(BOARD_WLAN_DEVICE) endif endif LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \ dumpstate.cpp \ dumpstate.cpp utils.cpp LOCAL_MODULE := dumpstate LOCAL_MODULE := dumpstate LOCAL_SHARED_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) libbase \ libcutils \ libhardware_legacy \ liblog \ libselinux # ZipArchive support, the order matters here to get all symbols. LOCAL_STATIC_LIBRARIES := $(COMMON_ZIP_LIBRARIES) ZIP_LIBRARIES := libziparchive libz libcrypto_static LOCAL_STATIC_LIBRARIES := $(ZIP_LIBRARIES) LOCAL_HAL_STATIC_LIBRARIES := libdumpstate LOCAL_HAL_STATIC_LIBRARIES := libdumpstate LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter LOCAL_CFLAGS += $(COMMON_LOCAL_CFLAGS) LOCAL_INIT_RC := dumpstate.rc LOCAL_INIT_RC := dumpstate.rc include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE) # ===============# # dumpstate_test # # ===============# include $(CLEAR_VARS) LOCAL_MODULE := dumpstate_test LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS) LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \ tests/dumpstate_test.cpp LOCAL_STATIC_LIBRARIES := $(COMMON_ZIP_LIBRARIES) \ libgmock LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) include $(BUILD_NATIVE_TEST) # =======================# # dumpstate_test_fixture # # =======================# include $(CLEAR_VARS) LOCAL_MODULE := dumpstate_test_fixture LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS) LOCAL_SRC_FILES := \ tests/dumpstate_test_fixture.cpp include $(BUILD_NATIVE_TEST) cmds/dumpstate/dumpstate.cpp +9 −18 Original line number Original line Diff line number Diff line Loading @@ -62,7 +62,6 @@ static const char *dump_traces_path = NULL; static std::string args; static std::string args; // TODO: variables below should be part of dumpstate object // TODO: variables below should be part of dumpstate object static std::string buildType; static time_t now; static time_t now; static std::unique_ptr<ZipWriter> zip_writer; static std::unique_ptr<ZipWriter> zip_writer; static std::set<std::string> mount_points; static std::set<std::string> mount_points; Loading Loading @@ -127,14 +126,6 @@ static const std::string ZIP_ROOT_DIR = "FS"; static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; bool Dumpstate::IsUserBuild() { return "user" == buildType; } bool Dumpstate::IsDryRun() { return dryRun_; } /* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones; /* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones; * otherwise, gets just those modified in the last half an hour. */ * otherwise, gets just those modified in the last half an hour. */ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { Loading @@ -155,7 +146,7 @@ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { } } // for_each_pid() callback to get mount info about a process. // for_each_pid() callback to get mount info about a process. void do_mountinfo(int pid, const char *name) { void do_mountinfo(int pid, const char* name __attribute__((unused))) { char path[PATH_MAX]; char path[PATH_MAX]; // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points Loading Loading @@ -426,7 +417,7 @@ static bool skip_not_stat(const char *path) { return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ } } static bool skip_none(const char *path) { static bool skip_none(const char* path __attribute__((unused))) { return false; return false; } } Loading Loading @@ -704,7 +695,7 @@ void print_header(const std::string& version) { build = android::base::GetProperty("ro.build.display.id", "(unknown)"); build = android::base::GetProperty("ro.build.display.id", "(unknown)"); fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)"); fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)"); buildType = android::base::GetProperty("ro.build.type", "(unknown)"); ds.buildType_ = android::base::GetProperty("ro.build.type", "(unknown)"); radio = android::base::GetProperty("gsm.version.baseband", "(unknown)"); radio = android::base::GetProperty("gsm.version.baseband", "(unknown)"); bootloader = android::base::GetProperty("ro.bootloader", "(unknown)"); bootloader = android::base::GetProperty("ro.bootloader", "(unknown)"); network = android::base::GetProperty("gsm.operator.alpha", "(unknown)"); network = android::base::GetProperty("gsm.operator.alpha", "(unknown)"); Loading @@ -727,7 +718,7 @@ void print_header(const std::string& version) { printf("Command line: %s\n", strtok(cmdline_buf, "\n")); printf("Command line: %s\n", strtok(cmdline_buf, "\n")); printf("Bugreport format version: %s\n", version.c_str()); printf("Bugreport format version: %s\n", version.c_str()); printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(), printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(), ds.dryRun_, args.c_str(), extraOptions.c_str()); ds.IsDryRun(), args.c_str(), extraOptions.c_str()); printf("\n"); printf("\n"); } } Loading Loading @@ -805,7 +796,7 @@ bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) } } /* adds a file to the existing zipped bugreport */ /* adds a file to the existing zipped bugreport */ static int _add_file_from_fd(const char *title, const char *path, int fd) { static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) { return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1; return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1; } } Loading Loading @@ -861,7 +852,8 @@ static void dump_iptables() { RunCommand("IP6TABLE RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"}); RunCommand("IP6TABLE RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"}); } } static void dumpstate(const std::string& screenshot_path, const std::string& version) { static void dumpstate(const std::string& screenshot_path, const std::string& version __attribute__((unused))) { DurationReporter durationReporter("DUMPSTATE"); DurationReporter durationReporter("DUMPSTATE"); unsigned long timeout; unsigned long timeout; Loading Loading @@ -1193,7 +1185,7 @@ static void wake_lock_releaser() { } } } } static void sig_handler(int signo) { static void sig_handler(int signo __attribute__((unused))) { wake_lock_releaser(); wake_lock_releaser(); _exit(EXIT_FAILURE); _exit(EXIT_FAILURE); } } Loading Loading @@ -1319,8 +1311,7 @@ int main(int argc, char *argv[]) { register_sig_handler(); register_sig_handler(); } } ds.dryRun_ = android::base::GetBoolProperty("dumpstate.dry_run", false); if (ds.IsDryRun()) { if (ds.dryRun_) { MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } } Loading cmds/dumpstate/dumpstate.h +8 −3 Original line number Original line Diff line number Diff line Loading @@ -202,6 +202,8 @@ static const int WEIGHT_TOTAL = 6500; * that are spread accross utils.cpp and dumpstate.cpp will be moved to it. * that are spread accross utils.cpp and dumpstate.cpp will be moved to it. */ */ class Dumpstate { class Dumpstate { friend class DumpstateTest; public: public: static Dumpstate& GetInstance(); static Dumpstate& GetInstance(); Loading Loading @@ -274,15 +276,18 @@ class Dumpstate { // When set, defines a socket file-descriptor use to report progress to bugreportz. // When set, defines a socket file-descriptor use to report progress to bugreportz. int controlSocketFd_ = -1; int controlSocketFd_ = -1; // Whether this is a dry run. // Build type (such as 'user' or 'eng'). bool dryRun_; std::string buildType_; // Full path of the directory where the bugreport files will be written; // Full path of the directory where the bugreport files will be written; std::string bugreportDir_; std::string bugreportDir_; private: private: // Whether this is a dry run. bool dryRun_; // Used by GetInstance() only. // Used by GetInstance() only. Dumpstate(); Dumpstate(bool dryRun = false); }; }; // for_each_pid_func = void (*)(int, const char*); // for_each_pid_func = void (*)(int, const char*); Loading cmds/dumpstate/tests/dumpstate_test.cpp 0 → 100644 +143 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 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. */ #include "dumpstate.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <libgen.h> #include <unistd.h> #include <android-base/file.h> using ::testing::EndsWith; using ::testing::IsEmpty; using ::testing::StrEq; using ::testing::StartsWith; using ::testing::Test; using ::testing::internal::CaptureStderr; using ::testing::internal::CaptureStdout; using ::testing::internal::GetCapturedStderr; using ::testing::internal::GetCapturedStdout; // Not used on test cases yet... void dumpstate_board(void) { } class DumpstateTest : public Test { public: void SetUp() { SetDryRun(false); } // Runs a command and capture `stdout` and `stderr`. int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, const CommandOptions& options = CommandOptions::DEFAULT) { CaptureStdout(); CaptureStderr(); int status = ds_.RunCommand(title, fullCommand, options); out = GetCapturedStdout(); err = GetCapturedStderr(); return status; } // `stdout` and `stderr` from the last command ran. std::string out, err; std::string testPath = dirname(android::base::GetExecutablePath().c_str()); std::string simpleBin = testPath + "/../dumpstate_test_fixture/dumpstate_test_fixture"; void SetDryRun(bool dryRun) { ds_.dryRun_ = dryRun; } private: Dumpstate& ds_ = Dumpstate::GetInstance(); }; TEST_F(DumpstateTest, RunCommandNoArgs) { EXPECT_EQ(-1, RunCommand("", {})); } TEST_F(DumpstateTest, RunCommandNoTitle) { EXPECT_EQ(0, RunCommand("", {simpleBin})); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n")); } TEST_F(DumpstateTest, RunCommandWithTitle) { EXPECT_EQ(0, RunCommand("I AM GROOT", {simpleBin})); EXPECT_THAT(err, StrEq("stderr\n")); // We don't know the exact duration, so we check the prefix and suffix EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + simpleBin + ") ------\nstdout\n------")); EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); } TEST_F(DumpstateTest, RunCommandRedirectStderr) { EXPECT_EQ( 0, RunCommand("", {simpleBin}, CommandOptions::WithTimeout(10).RedirectStderr().Build())); EXPECT_THAT(out, IsEmpty()); EXPECT_THAT(err, StrEq("stderr\nstdout\n")); } TEST_F(DumpstateTest, RunCommandWithOneArg) { EXPECT_EQ(0, RunCommand("", {simpleBin, "one"})); EXPECT_THAT(err, IsEmpty()); EXPECT_THAT(out, StrEq("one\n")); } TEST_F(DumpstateTest, RunCommandWithNoArgs) { EXPECT_EQ(0, RunCommand("", {simpleBin, "one", "is", "the", "loniest", "number"})); EXPECT_THAT(err, IsEmpty()); EXPECT_THAT(out, StrEq("one is the loniest number\n")); } TEST_F(DumpstateTest, RunCommandDryRun) { SetDryRun(true); EXPECT_EQ(0, RunCommand("I AM GROOT", {simpleBin})); // We don't know the exact duration, so we check the prefix and suffix EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + simpleBin + ") ------\n\t(skipped on dry run)\n------")); EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); EXPECT_THAT(err, IsEmpty()); } TEST_F(DumpstateTest, RunCommandDryRunNoTitle) { SetDryRun(true); EXPECT_EQ(0, RunCommand("", {simpleBin})); EXPECT_THAT(out, IsEmpty()); EXPECT_THAT(err, IsEmpty()); } TEST_F(DumpstateTest, RunCommandDryRunAlways) { SetDryRun(true); EXPECT_EQ(0, RunCommand("", {simpleBin}, CommandOptions::WithTimeout(10).Always().Build())); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n")); } // TODO: add test for other scenarios: // - AsRoot() // - DropRoot // - WithLoggingMessage() // - command does not exist (invalid path) // - command times out // - command exits with a different value // - command is killed before timed out // - test progress // TODO: test DumpFile() cmds/dumpstate/tests/dumpstate_test_fixture.cpp 0 → 100644 +44 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 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. */ #include <stdio.h> /* * Binary used to on RunCommand tests. * * Usage: * * - It returns 0 unless documented otherwise. * - Without any arguments, prints `stdout\n` on `stdout` and `stderr\n` on `stderr`. * - With arguments, prints all arguments on `stdout` separated by ` `. */ int main(int argc, char* const argv[]) { if (argc > 1) { for (int i = 1; i < argc; i++) { fprintf(stdout, "%s", argv[i]); if (i == argc - 1) { fprintf(stdout, "\n"); } else { fprintf(stdout, " "); } } return 0; } fprintf(stdout, "stdout\n"); fprintf(stderr, "stderr\n"); return 0; } Loading
cmds/dumpstate/Android.mk +67 −13 Original line number Original line Diff line number Diff line LOCAL_PATH:= $(call my-dir) LOCAL_PATH:= $(call my-dir) # ================# # Common settings # # ================# # ZipArchive support, the order matters here to get all symbols. COMMON_ZIP_LIBRARIES := libziparchive libz libcrypto_static # TODO: ideally the tests should depend on a shared dumpstate library, but currently libdumpstate # is used to define the device-specific HAL library. Instead, both dumpstate and dumpstate_test # shares a lot of common settings COMMON_LOCAL_CFLAGS := \ -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter COMMON_SRC_FILES := \ utils.cpp COMMON_SHARED_LIBRARIES := \ libbase \ libcutils \ libhardware_legacy \ liblog \ libselinux # ==========# # dumpstate # # ==========# include $(CLEAR_VARS) include $(CLEAR_VARS) ifdef BOARD_WLAN_DEVICE ifdef BOARD_WLAN_DEVICE LOCAL_CFLAGS := -DFWDUMP_$(BOARD_WLAN_DEVICE) LOCAL_CFLAGS := -DFWDUMP_$(BOARD_WLAN_DEVICE) endif endif LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \ dumpstate.cpp \ dumpstate.cpp utils.cpp LOCAL_MODULE := dumpstate LOCAL_MODULE := dumpstate LOCAL_SHARED_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) libbase \ libcutils \ libhardware_legacy \ liblog \ libselinux # ZipArchive support, the order matters here to get all symbols. LOCAL_STATIC_LIBRARIES := $(COMMON_ZIP_LIBRARIES) ZIP_LIBRARIES := libziparchive libz libcrypto_static LOCAL_STATIC_LIBRARIES := $(ZIP_LIBRARIES) LOCAL_HAL_STATIC_LIBRARIES := libdumpstate LOCAL_HAL_STATIC_LIBRARIES := libdumpstate LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter LOCAL_CFLAGS += $(COMMON_LOCAL_CFLAGS) LOCAL_INIT_RC := dumpstate.rc LOCAL_INIT_RC := dumpstate.rc include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE) # ===============# # dumpstate_test # # ===============# include $(CLEAR_VARS) LOCAL_MODULE := dumpstate_test LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS) LOCAL_SRC_FILES := $(COMMON_SRC_FILES) \ tests/dumpstate_test.cpp LOCAL_STATIC_LIBRARIES := $(COMMON_ZIP_LIBRARIES) \ libgmock LOCAL_SHARED_LIBRARIES := $(COMMON_SHARED_LIBRARIES) include $(BUILD_NATIVE_TEST) # =======================# # dumpstate_test_fixture # # =======================# include $(CLEAR_VARS) LOCAL_MODULE := dumpstate_test_fixture LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS := $(COMMON_LOCAL_CFLAGS) LOCAL_SRC_FILES := \ tests/dumpstate_test_fixture.cpp include $(BUILD_NATIVE_TEST)
cmds/dumpstate/dumpstate.cpp +9 −18 Original line number Original line Diff line number Diff line Loading @@ -62,7 +62,6 @@ static const char *dump_traces_path = NULL; static std::string args; static std::string args; // TODO: variables below should be part of dumpstate object // TODO: variables below should be part of dumpstate object static std::string buildType; static time_t now; static time_t now; static std::unique_ptr<ZipWriter> zip_writer; static std::unique_ptr<ZipWriter> zip_writer; static std::set<std::string> mount_points; static std::set<std::string> mount_points; Loading Loading @@ -127,14 +126,6 @@ static const std::string ZIP_ROOT_DIR = "FS"; static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; bool Dumpstate::IsUserBuild() { return "user" == buildType; } bool Dumpstate::IsDryRun() { return dryRun_; } /* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones; /* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones; * otherwise, gets just those modified in the last half an hour. */ * otherwise, gets just those modified in the last half an hour. */ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { Loading @@ -155,7 +146,7 @@ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { } } // for_each_pid() callback to get mount info about a process. // for_each_pid() callback to get mount info about a process. void do_mountinfo(int pid, const char *name) { void do_mountinfo(int pid, const char* name __attribute__((unused))) { char path[PATH_MAX]; char path[PATH_MAX]; // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points Loading Loading @@ -426,7 +417,7 @@ static bool skip_not_stat(const char *path) { return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ } } static bool skip_none(const char *path) { static bool skip_none(const char* path __attribute__((unused))) { return false; return false; } } Loading Loading @@ -704,7 +695,7 @@ void print_header(const std::string& version) { build = android::base::GetProperty("ro.build.display.id", "(unknown)"); build = android::base::GetProperty("ro.build.display.id", "(unknown)"); fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)"); fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)"); buildType = android::base::GetProperty("ro.build.type", "(unknown)"); ds.buildType_ = android::base::GetProperty("ro.build.type", "(unknown)"); radio = android::base::GetProperty("gsm.version.baseband", "(unknown)"); radio = android::base::GetProperty("gsm.version.baseband", "(unknown)"); bootloader = android::base::GetProperty("ro.bootloader", "(unknown)"); bootloader = android::base::GetProperty("ro.bootloader", "(unknown)"); network = android::base::GetProperty("gsm.operator.alpha", "(unknown)"); network = android::base::GetProperty("gsm.operator.alpha", "(unknown)"); Loading @@ -727,7 +718,7 @@ void print_header(const std::string& version) { printf("Command line: %s\n", strtok(cmdline_buf, "\n")); printf("Command line: %s\n", strtok(cmdline_buf, "\n")); printf("Bugreport format version: %s\n", version.c_str()); printf("Bugreport format version: %s\n", version.c_str()); printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(), printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(), ds.dryRun_, args.c_str(), extraOptions.c_str()); ds.IsDryRun(), args.c_str(), extraOptions.c_str()); printf("\n"); printf("\n"); } } Loading Loading @@ -805,7 +796,7 @@ bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) } } /* adds a file to the existing zipped bugreport */ /* adds a file to the existing zipped bugreport */ static int _add_file_from_fd(const char *title, const char *path, int fd) { static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) { return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1; return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1; } } Loading Loading @@ -861,7 +852,8 @@ static void dump_iptables() { RunCommand("IP6TABLE RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"}); RunCommand("IP6TABLE RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"}); } } static void dumpstate(const std::string& screenshot_path, const std::string& version) { static void dumpstate(const std::string& screenshot_path, const std::string& version __attribute__((unused))) { DurationReporter durationReporter("DUMPSTATE"); DurationReporter durationReporter("DUMPSTATE"); unsigned long timeout; unsigned long timeout; Loading Loading @@ -1193,7 +1185,7 @@ static void wake_lock_releaser() { } } } } static void sig_handler(int signo) { static void sig_handler(int signo __attribute__((unused))) { wake_lock_releaser(); wake_lock_releaser(); _exit(EXIT_FAILURE); _exit(EXIT_FAILURE); } } Loading Loading @@ -1319,8 +1311,7 @@ int main(int argc, char *argv[]) { register_sig_handler(); register_sig_handler(); } } ds.dryRun_ = android::base::GetBoolProperty("dumpstate.dry_run", false); if (ds.IsDryRun()) { if (ds.dryRun_) { MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } } Loading
cmds/dumpstate/dumpstate.h +8 −3 Original line number Original line Diff line number Diff line Loading @@ -202,6 +202,8 @@ static const int WEIGHT_TOTAL = 6500; * that are spread accross utils.cpp and dumpstate.cpp will be moved to it. * that are spread accross utils.cpp and dumpstate.cpp will be moved to it. */ */ class Dumpstate { class Dumpstate { friend class DumpstateTest; public: public: static Dumpstate& GetInstance(); static Dumpstate& GetInstance(); Loading Loading @@ -274,15 +276,18 @@ class Dumpstate { // When set, defines a socket file-descriptor use to report progress to bugreportz. // When set, defines a socket file-descriptor use to report progress to bugreportz. int controlSocketFd_ = -1; int controlSocketFd_ = -1; // Whether this is a dry run. // Build type (such as 'user' or 'eng'). bool dryRun_; std::string buildType_; // Full path of the directory where the bugreport files will be written; // Full path of the directory where the bugreport files will be written; std::string bugreportDir_; std::string bugreportDir_; private: private: // Whether this is a dry run. bool dryRun_; // Used by GetInstance() only. // Used by GetInstance() only. Dumpstate(); Dumpstate(bool dryRun = false); }; }; // for_each_pid_func = void (*)(int, const char*); // for_each_pid_func = void (*)(int, const char*); Loading
cmds/dumpstate/tests/dumpstate_test.cpp 0 → 100644 +143 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 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. */ #include "dumpstate.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <libgen.h> #include <unistd.h> #include <android-base/file.h> using ::testing::EndsWith; using ::testing::IsEmpty; using ::testing::StrEq; using ::testing::StartsWith; using ::testing::Test; using ::testing::internal::CaptureStderr; using ::testing::internal::CaptureStdout; using ::testing::internal::GetCapturedStderr; using ::testing::internal::GetCapturedStdout; // Not used on test cases yet... void dumpstate_board(void) { } class DumpstateTest : public Test { public: void SetUp() { SetDryRun(false); } // Runs a command and capture `stdout` and `stderr`. int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, const CommandOptions& options = CommandOptions::DEFAULT) { CaptureStdout(); CaptureStderr(); int status = ds_.RunCommand(title, fullCommand, options); out = GetCapturedStdout(); err = GetCapturedStderr(); return status; } // `stdout` and `stderr` from the last command ran. std::string out, err; std::string testPath = dirname(android::base::GetExecutablePath().c_str()); std::string simpleBin = testPath + "/../dumpstate_test_fixture/dumpstate_test_fixture"; void SetDryRun(bool dryRun) { ds_.dryRun_ = dryRun; } private: Dumpstate& ds_ = Dumpstate::GetInstance(); }; TEST_F(DumpstateTest, RunCommandNoArgs) { EXPECT_EQ(-1, RunCommand("", {})); } TEST_F(DumpstateTest, RunCommandNoTitle) { EXPECT_EQ(0, RunCommand("", {simpleBin})); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n")); } TEST_F(DumpstateTest, RunCommandWithTitle) { EXPECT_EQ(0, RunCommand("I AM GROOT", {simpleBin})); EXPECT_THAT(err, StrEq("stderr\n")); // We don't know the exact duration, so we check the prefix and suffix EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + simpleBin + ") ------\nstdout\n------")); EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); } TEST_F(DumpstateTest, RunCommandRedirectStderr) { EXPECT_EQ( 0, RunCommand("", {simpleBin}, CommandOptions::WithTimeout(10).RedirectStderr().Build())); EXPECT_THAT(out, IsEmpty()); EXPECT_THAT(err, StrEq("stderr\nstdout\n")); } TEST_F(DumpstateTest, RunCommandWithOneArg) { EXPECT_EQ(0, RunCommand("", {simpleBin, "one"})); EXPECT_THAT(err, IsEmpty()); EXPECT_THAT(out, StrEq("one\n")); } TEST_F(DumpstateTest, RunCommandWithNoArgs) { EXPECT_EQ(0, RunCommand("", {simpleBin, "one", "is", "the", "loniest", "number"})); EXPECT_THAT(err, IsEmpty()); EXPECT_THAT(out, StrEq("one is the loniest number\n")); } TEST_F(DumpstateTest, RunCommandDryRun) { SetDryRun(true); EXPECT_EQ(0, RunCommand("I AM GROOT", {simpleBin})); // We don't know the exact duration, so we check the prefix and suffix EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + simpleBin + ") ------\n\t(skipped on dry run)\n------")); EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); EXPECT_THAT(err, IsEmpty()); } TEST_F(DumpstateTest, RunCommandDryRunNoTitle) { SetDryRun(true); EXPECT_EQ(0, RunCommand("", {simpleBin})); EXPECT_THAT(out, IsEmpty()); EXPECT_THAT(err, IsEmpty()); } TEST_F(DumpstateTest, RunCommandDryRunAlways) { SetDryRun(true); EXPECT_EQ(0, RunCommand("", {simpleBin}, CommandOptions::WithTimeout(10).Always().Build())); EXPECT_THAT(out, StrEq("stdout\n")); EXPECT_THAT(err, StrEq("stderr\n")); } // TODO: add test for other scenarios: // - AsRoot() // - DropRoot // - WithLoggingMessage() // - command does not exist (invalid path) // - command times out // - command exits with a different value // - command is killed before timed out // - test progress // TODO: test DumpFile()
cmds/dumpstate/tests/dumpstate_test_fixture.cpp 0 → 100644 +44 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 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. */ #include <stdio.h> /* * Binary used to on RunCommand tests. * * Usage: * * - It returns 0 unless documented otherwise. * - Without any arguments, prints `stdout\n` on `stdout` and `stderr\n` on `stderr`. * - With arguments, prints all arguments on `stdout` separated by ` `. */ int main(int argc, char* const argv[]) { if (argc > 1) { for (int i = 1; i < argc; i++) { fprintf(stdout, "%s", argv[i]); if (i == argc - 1) { fprintf(stdout, "\n"); } else { fprintf(stdout, " "); } } return 0; } fprintf(stdout, "stdout\n"); fprintf(stderr, "stderr\n"); return 0; }