diff options
author | Yabin Cui <yabinc@google.com> | 2020-07-07 15:56:34 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2020-07-08 15:02:56 -0700 |
commit | acbdb2456da4837a143d096a8a0563ba1dfc0507 (patch) | |
tree | 9e07abefafc96e76fb9b065264fb67cb78c0d9ad | |
parent | 4f6808ce8d0a10cb4c8588ddd7ed275001da3154 (diff) | |
download | extras-acbdb2456da4837a143d096a8a0563ba1dfc0507.tar.gz |
simpleperf: add function to preprocess options.
Add Command::PreprocessOptions() to extracts options from the
argument list. It splits options into different types. Instead of
replying on the order in the argument list, it allows a command
choosing the order to process each option.
Also put whole command.h in simpleperf namespace.
Bug: 160701181
Test: run simpleperf_unit_test.
Change-Id: I9b20e21a94797c322c1371cbe1704b3e2ce1be28
-rw-r--r-- | simpleperf/cmd_api.cpp | 6 | ||||
-rw-r--r-- | simpleperf/cmd_api_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_debug_unwind.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_debug_unwind_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_dumprecord.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_dumprecord_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_help.cpp | 6 | ||||
-rw-r--r-- | simpleperf/cmd_inject.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_kmem.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_kmem_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_list.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_list_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_report.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_report_sample.cpp | 5 | ||||
-rw-r--r-- | simpleperf/cmd_report_sample_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_report_test.cpp | 2 | ||||
-rw-r--r-- | simpleperf/cmd_stat.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_trace_sched.cpp | 5 | ||||
-rw-r--r-- | simpleperf/cmd_trace_sched_test.cpp | 1 | ||||
-rw-r--r-- | simpleperf/command.cpp | 92 | ||||
-rw-r--r-- | simpleperf/command.h | 100 | ||||
-rw-r--r-- | simpleperf/command_test.cpp | 111 | ||||
-rw-r--r-- | simpleperf/gtest_main.cpp | 2 | ||||
-rw-r--r-- | simpleperf/main.cpp | 2 |
25 files changed, 370 insertions, 6 deletions
diff --git a/simpleperf/cmd_api.cpp b/simpleperf/cmd_api.cpp index 7f933736..7235a250 100644 --- a/simpleperf/cmd_api.cpp +++ b/simpleperf/cmd_api.cpp @@ -34,6 +34,8 @@ #include "utils.h" #include "workload.h" +using namespace simpleperf; + namespace { const std::string SIMPLEPERF_DATA_DIR = "simpleperf_data"; @@ -215,9 +217,13 @@ bool CollectCommand::RemoveRecordingData() { } } // namespace +namespace simpleperf { + void RegisterAPICommands() { RegisterCommand("api-prepare", []{ return std::unique_ptr<Command>(new PrepareCommand()); }); RegisterCommand("api-collect", []{ return std::unique_ptr<Command>(new CollectCommand()); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_api_test.cpp b/simpleperf/cmd_api_test.cpp index 4157bdef..716b383b 100644 --- a/simpleperf/cmd_api_test.cpp +++ b/simpleperf/cmd_api_test.cpp @@ -24,6 +24,8 @@ #include "test_util.h" #include "utils.h" +using namespace simpleperf; + #if defined(__ANDROID__) static bool WaitUntilAppExit(const std::string& package_name) { diff --git a/simpleperf/cmd_debug_unwind.cpp b/simpleperf/cmd_debug_unwind.cpp index b5df2da3..72f1ddbb 100644 --- a/simpleperf/cmd_debug_unwind.cpp +++ b/simpleperf/cmd_debug_unwind.cpp @@ -405,7 +405,11 @@ void DebugUnwindCommand::PrintStat() { printf("Please use debug_unwind_reporter.py to get a report in details.\n"); } +namespace simpleperf { + void RegisterDebugUnwindCommand() { RegisterCommand("debug-unwind", []{ return std::unique_ptr<Command>(new DebugUnwindCommand()); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_debug_unwind_test.cpp b/simpleperf/cmd_debug_unwind_test.cpp index 20a441ec..8b65d424 100644 --- a/simpleperf/cmd_debug_unwind_test.cpp +++ b/simpleperf/cmd_debug_unwind_test.cpp @@ -29,6 +29,8 @@ #include "record_file.h" #include "test_util.h" +using namespace simpleperf; + static std::unique_ptr<Command> DebugUnwindCmd() { return CreateCommandInstance("debug-unwind"); } diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp index 645a783a..c996832c 100644 --- a/simpleperf/cmd_dumprecord.cpp +++ b/simpleperf/cmd_dumprecord.cpp @@ -466,6 +466,10 @@ bool DumpRecordCommand::DumpFeatureSection() { } // namespace +namespace simpleperf { + void RegisterDumpRecordCommand() { RegisterCommand("dump", [] { return std::unique_ptr<Command>(new DumpRecordCommand); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_dumprecord_test.cpp b/simpleperf/cmd_dumprecord_test.cpp index e8632b87..dc33e719 100644 --- a/simpleperf/cmd_dumprecord_test.cpp +++ b/simpleperf/cmd_dumprecord_test.cpp @@ -20,6 +20,8 @@ #include "get_test_data.h" #include "test_util.h" +using namespace simpleperf; + static std::unique_ptr<Command> DumpCmd() { return CreateCommandInstance("dump"); } diff --git a/simpleperf/cmd_help.cpp b/simpleperf/cmd_help.cpp index b51071b2..65bed775 100644 --- a/simpleperf/cmd_help.cpp +++ b/simpleperf/cmd_help.cpp @@ -22,6 +22,8 @@ #include "command.h" +using namespace simpleperf; + class HelpCommand : public Command { public: HelpCommand() @@ -84,7 +86,11 @@ void HelpCommand::PrintLongHelpForOneCommand(const Command& command) { printf("%s\n", command.LongHelpString().c_str()); } +namespace simpleperf { + void RegisterHelpCommand() { RegisterCommand("help", [] { return std::unique_ptr<Command>(new HelpCommand); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_inject.cpp b/simpleperf/cmd_inject.cpp index 04abeed0..69b3452f 100644 --- a/simpleperf/cmd_inject.cpp +++ b/simpleperf/cmd_inject.cpp @@ -451,6 +451,10 @@ class InjectCommand : public Command { } // namespace +namespace simpleperf { + void RegisterInjectCommand() { return RegisterCommand("inject", [] { return std::unique_ptr<Command>(new InjectCommand); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_kmem.cpp b/simpleperf/cmd_kmem.cpp index 453a2768..454747b8 100644 --- a/simpleperf/cmd_kmem.cpp +++ b/simpleperf/cmd_kmem.cpp @@ -710,7 +710,11 @@ void KmemCommand::PrintSlabReportContext(FILE* fp) { } // namespace +namespace simpleperf { + void RegisterKmemCommand() { RegisterCommand("kmem", [] { return std::unique_ptr<Command>(new KmemCommand()); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_kmem_test.cpp b/simpleperf/cmd_kmem_test.cpp index 4dab87ed..0fa30669 100644 --- a/simpleperf/cmd_kmem_test.cpp +++ b/simpleperf/cmd_kmem_test.cpp @@ -27,6 +27,8 @@ #include "record_file.h" #include "test_util.h" +using namespace simpleperf; + static std::unique_ptr<Command> KmemCmd() { return CreateCommandInstance("kmem"); } diff --git a/simpleperf/cmd_list.cpp b/simpleperf/cmd_list.cpp index ef6ba86a..396d7a8e 100644 --- a/simpleperf/cmd_list.cpp +++ b/simpleperf/cmd_list.cpp @@ -223,6 +223,10 @@ void ListCommand::ShowFeatures() { } // namespace +namespace simpleperf { + void RegisterListCommand() { RegisterCommand("list", [] { return std::unique_ptr<Command>(new ListCommand); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_list_test.cpp b/simpleperf/cmd_list_test.cpp index 6712b0a4..e2f804da 100644 --- a/simpleperf/cmd_list_test.cpp +++ b/simpleperf/cmd_list_test.cpp @@ -19,6 +19,8 @@ #include "command.h" #include "test_util.h" +using namespace simpleperf; + class ListCommandTest : public ::testing::Test { protected: virtual void SetUp() { diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 2aa99407..5bb6c00b 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -1839,7 +1839,11 @@ void RecordCommand::CollectHitFileInfo(const SampleRecord& r) { } } +namespace simpleperf { + void RegisterRecordCommand() { RegisterCommand("record", [] { return std::unique_ptr<Command>(new RecordCommand()); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp index 5a509781..3d5fad90 100644 --- a/simpleperf/cmd_report.cpp +++ b/simpleperf/cmd_report.cpp @@ -974,7 +974,11 @@ void ReportCommand::PrintReportContext(FILE* report_fp) { } // namespace +namespace simpleperf { + void RegisterReportCommand() { RegisterCommand("report", [] { return std::unique_ptr<Command>(new ReportCommand()); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_report_sample.cpp b/simpleperf/cmd_report_sample.cpp index e133fb28..2d9caf4b 100644 --- a/simpleperf/cmd_report_sample.cpp +++ b/simpleperf/cmd_report_sample.cpp @@ -33,6 +33,7 @@ #include "thread_tree.h" #include "utils.h" +using namespace simpleperf; namespace proto = simpleperf_report_proto; namespace { @@ -690,8 +691,12 @@ void ReportSampleCommand::PrintLostSituation() { } // namespace +namespace simpleperf { + void RegisterReportSampleCommand() { RegisterCommand("report-sample", [] { return std::unique_ptr<Command>(new ReportSampleCommand()); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_report_sample_test.cpp b/simpleperf/cmd_report_sample_test.cpp index 9543634d..c8529efc 100644 --- a/simpleperf/cmd_report_sample_test.cpp +++ b/simpleperf/cmd_report_sample_test.cpp @@ -21,6 +21,8 @@ #include "command.h" #include "get_test_data.h" +using namespace simpleperf; + static std::unique_ptr<Command> ReportSampleCmd() { return CreateCommandInstance("report-sample"); } diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp index 36837f9e..ae081148 100644 --- a/simpleperf/cmd_report_test.cpp +++ b/simpleperf/cmd_report_test.cpp @@ -28,6 +28,8 @@ #include "read_apk.h" #include "test_util.h" +using namespace simpleperf; + static std::unique_ptr<Command> ReportCmd() { return CreateCommandInstance("report"); } diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp index f60bdd4d..66ac1b60 100644 --- a/simpleperf/cmd_stat.cpp +++ b/simpleperf/cmd_stat.cpp @@ -914,7 +914,11 @@ bool StatCommand::ShowCounters(const std::vector<CountersInfo>& counters, } // namespace +namespace simpleperf { + void RegisterStatCommand() { RegisterCommand("stat", [] { return std::unique_ptr<Command>(new StatCommand); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_trace_sched.cpp b/simpleperf/cmd_trace_sched.cpp index a5961ec9..2977a756 100644 --- a/simpleperf/cmd_trace_sched.cpp +++ b/simpleperf/cmd_trace_sched.cpp @@ -33,6 +33,7 @@ #include "utils.h" using android::base::StringPrintf; +using namespace simpleperf; namespace { @@ -413,6 +414,10 @@ void TraceSchedCommand::ReportProcessInfo(const std::vector<ProcessInfo>& proces } // namespace +namespace simpleperf { + void RegisterTraceSchedCommand() { RegisterCommand("trace-sched", [] { return std::unique_ptr<Command>(new TraceSchedCommand()); }); } + +} // namespace simpleperf diff --git a/simpleperf/cmd_trace_sched_test.cpp b/simpleperf/cmd_trace_sched_test.cpp index c7676491..b50e3a31 100644 --- a/simpleperf/cmd_trace_sched_test.cpp +++ b/simpleperf/cmd_trace_sched_test.cpp @@ -36,6 +36,7 @@ #include "test_util.h" #include "thread_tree.h" +using namespace simpleperf; using namespace PerfFileFormat; static std::unique_ptr<Command> TraceSchedCmd() { diff --git a/simpleperf/command.cpp b/simpleperf/command.cpp index d00fc224..a7b7eb5a 100644 --- a/simpleperf/command.cpp +++ b/simpleperf/command.cpp @@ -16,6 +16,8 @@ #include "command.h" +#include <string.h> + #include <algorithm> #include <map> #include <string> @@ -27,7 +29,7 @@ #include "utils.h" -using namespace simpleperf; +namespace simpleperf { bool Command::NextArgumentOrError(const std::vector<std::string>& args, size_t* pi) { if (*pi + 1 == args.size()) { @@ -39,6 +41,90 @@ bool Command::NextArgumentOrError(const std::vector<std::string>& args, size_t* return true; } +bool Command::PreprocessOptions(const std::vector<std::string>& args, + const std::unordered_map<OptionName, OptionFormat>& option_formats, + OptionValueMap* options, + std::vector<std::pair<OptionName, OptionValue>>* ordered_options, + std::vector<std::string>* non_option_args) { + options->values.clear(); + ordered_options->clear(); + size_t i; + for (i = 0; i < args.size() && !args[i].empty() && args[i][0] == '-'; i++) { + auto it = option_formats.find(args[i]); + if (it == option_formats.end()) { + if (args[i] == "--") { + i++; + break; + } + ReportUnknownOption(args, i); + return false; + } + const OptionName& name = it->first; + const OptionFormat& format = it->second; + OptionValue value; + memset(&value, 0, sizeof(value)); + + if (i + 1 == args.size()) { + if (format.value_type != OptionValueType::NONE && + format.value_type != OptionValueType::OPT_STRING) { + LOG(ERROR) << "No argument following " << name << " option. Try `simpleperf help " << name_ + << "`"; + return false; + } + } else { + switch (format.value_type) { + case OptionValueType::NONE: + break; + case OptionValueType::STRING: + value.str_value = &args[++i]; + break; + case OptionValueType::OPT_STRING: + if (!args[i + 1].empty() && args[i + 1][0] != '-') { + value.str_value = &args[++i]; + } + break; + case OptionValueType::UINT: + if (!android::base::ParseUint(args[++i], &value.uint_value, + std::numeric_limits<uint64_t>::max(), true)) { + LOG(ERROR) << "Invalid argument for option " << name << ": " << args[i]; + return false; + } + break; + case OptionValueType::DOUBLE: + if (!android::base::ParseDouble(args[++i], &value.double_value)) { + LOG(ERROR) << "Invalid argument for option " << name << ": " << args[i]; + return false; + } + break; + } + } + + switch (format.type) { + case OptionType::SINGLE: + if (auto it = options->values.find(name); it != options->values.end()) { + it->second = value; + } else { + options->values.emplace(name, value); + } + break; + case OptionType::MULTIPLE: + options->values.emplace(name, value); + break; + case OptionType::ORDERED: + ordered_options->emplace_back(name, value); + break; + } + } + if (i < args.size()) { + if (non_option_args == nullptr) { + LOG(ERROR) << "Invalid option " << args[i] << ". Try `simpleperf help " << name_ << "`"; + return false; + } + non_option_args->assign(args.begin() + i, args.end()); + } + return true; +} + bool Command::GetDoubleOption(const std::vector<std::string>& args, size_t* pi, double* value, double min, double max) { if (!NextArgumentOrError(args, pi)) { @@ -131,9 +217,7 @@ static void StderrLogger(android::base::LogId, android::base::LogSeverity severi fprintf(stderr, "simpleperf %c %s:%u] %s\n", severity_char, file, line, message); } -namespace simpleperf { bool log_to_android_buffer = false; -} bool RunSimpleperfCmd(int argc, char** argv) { android::base::InitLogging(argv, StderrLogger); @@ -190,3 +274,5 @@ bool RunSimpleperfCmd(int argc, char** argv) { _Exit(result ? 0 : 1); return result; } + +} // namespace simpleperf diff --git a/simpleperf/command.h b/simpleperf/command.h index fe71a31a..2f0a038c 100644 --- a/simpleperf/command.h +++ b/simpleperf/command.h @@ -18,15 +18,103 @@ #define SIMPLE_PERF_COMMAND_H_ #include <functional> -#include <memory> #include <limits> +#include <map> +#include <memory> +#include <optional> #include <string> +#include <unordered_map> #include <vector> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/parseint.h> +namespace simpleperf { + +using OptionName = std::string; + +enum class OptionType { + SINGLE, // this option has a single value (use the last one in the arg list) + MULTIPLE, // this option can have multiple values (keep all values appeared in the arg list) + ORDERED, // keep the order of this option in the arg list +}; + +enum class OptionValueType { + NONE, // No value is needed + STRING, + OPT_STRING, // optional string + UINT, + DOUBLE, +}; + +struct OptionFormat { + OptionValueType value_type; + OptionType type; +}; + +union OptionValue { + const std::string* str_value; + uint64_t uint_value; + double double_value; +}; + +struct OptionValueMap { + std::multimap<OptionName, OptionValue> values; + + bool PullBoolValue(const OptionName& name) { + return PullValue(name).has_value(); + } + + template <typename T> + bool PullUintValue(const OptionName& name, T* value, uint64_t min = 0, + uint64_t max = std::numeric_limits<T>::max()) { + if (auto option_value = PullValue(name); option_value) { + if (option_value->uint_value < min || option_value->uint_value > max) { + LOG(ERROR) << "invalid " << name << ": " << option_value->uint_value; + return false; + } + *value = option_value->uint_value; + } + return true; + } + + bool PullDoubleValue(const OptionName& name, double* value, + double min = std::numeric_limits<double>::lowest(), + double max = std::numeric_limits<double>::max()) { + if (auto option_value = PullValue(name); option_value) { + if (option_value->double_value < min || option_value->double_value > max) { + LOG(ERROR) << "invalid " << name << ": " << option_value->double_value; + return false; + } + *value = option_value->double_value; + } + return true; + } + + std::optional<OptionValue> PullValue(const OptionName& name) { + std::optional<OptionValue> res; + if (auto it = values.find(name); it != values.end()) { + res.emplace(it->second); + values.erase(it); + } + return res; + } + + std::optional<std::vector<OptionValue>> PullValues(const OptionName& name) { + auto pair = values.equal_range(name); + if (pair.first != pair.second) { + std::vector<OptionValue> res; + for (auto it = pair.first; it != pair.second; ++it) { + res.emplace_back(it->second); + } + values.erase(name); + return res; + } + return {}; + } +}; + class Command { public: Command(const std::string& name, const std::string& short_help_string, @@ -51,6 +139,12 @@ class Command { virtual bool Run(const std::vector<std::string>& args) = 0; + bool PreprocessOptions(const std::vector<std::string>& args, + const std::unordered_map<OptionName, OptionFormat>& option_formats, + OptionValueMap* options, + std::vector<std::pair<OptionName, OptionValue>>* ordered_options, + std::vector<std::string>* non_option_args = nullptr); + template <typename T> bool GetUintOption(const std::vector<std::string>& args, size_t* pi, T* value, uint64_t min = 0, uint64_t max = std::numeric_limits<T>::max(), bool allow_suffixes = false) { @@ -88,8 +182,8 @@ std::unique_ptr<Command> CreateCommandInstance(const std::string& cmd_name); const std::vector<std::string> GetAllCommandNames(); bool RunSimpleperfCmd(int argc, char** argv); -namespace simpleperf { extern bool log_to_android_buffer; -} + +} // namespace simpleperf #endif // SIMPLE_PERF_COMMAND_H_ diff --git a/simpleperf/command_test.cpp b/simpleperf/command_test.cpp index 29c745e3..ab618e13 100644 --- a/simpleperf/command_test.cpp +++ b/simpleperf/command_test.cpp @@ -18,6 +18,8 @@ #include "command.h" +using namespace simpleperf; + class MockCommand : public Command { public: MockCommand() : Command("mock", "mock_short_help", "mock_long_help") { @@ -70,3 +72,112 @@ TEST(command, GetValueForOption) { ASSERT_TRUE(command.GetDoubleOption({"-s", "3.2"}, &i, &double_value, 0, 4)); ASSERT_DOUBLE_EQ(double_value, 3.2); } + +TEST(command, PreprocessOptions) { + MockCommand cmd; + OptionValueMap options; + std::vector<std::pair<OptionName, OptionValue>> ordered_options; + std::vector<std::string> non_option_args; + + std::unordered_map<OptionName, OptionFormat> option_formats = { + {"--bool-option", {OptionValueType::NONE, OptionType::SINGLE}}, + {"--str-option", {OptionValueType::STRING, OptionType::MULTIPLE}}, + {"--opt-str-option", {OptionValueType::OPT_STRING, OptionType::MULTIPLE}}, + {"--uint-option", {OptionValueType::UINT, OptionType::SINGLE}}, + {"--double-option", {OptionValueType::DOUBLE, OptionType::SINGLE}}, + + // ordered options + {"--ord-str-option", {OptionValueType::STRING, OptionType::ORDERED}}, + {"--ord-uint-option", {OptionValueType::UINT, OptionType::ORDERED}}, + }; + + // Check options. + std::vector<std::string> args = {"--bool-option", + "--str-option", + "str1", + "--str-option", + "str2", + "--opt-str-option", + "--opt-str-option", + "opt_str", + "--uint-option", + "34", + "--double-option", + "-32.75"}; + ASSERT_TRUE(cmd.PreprocessOptions(args, option_formats, &options, &ordered_options, nullptr)); + ASSERT_TRUE(options.PullBoolValue("--bool-option")); + auto values = options.PullValues("--str-option").value(); + ASSERT_EQ(values.size(), 2); + ASSERT_EQ(*values[0].str_value, "str1"); + ASSERT_EQ(*values[1].str_value, "str2"); + values = options.PullValues("--opt-str-option").value(); + ASSERT_EQ(values.size(), 2); + ASSERT_TRUE(values[0].str_value == nullptr); + ASSERT_EQ(*values[1].str_value, "opt_str"); + size_t uint_value; + ASSERT_TRUE(options.PullUintValue("--uint-option", &uint_value)); + ASSERT_EQ(uint_value, 34); + double double_value; + ASSERT_TRUE(options.PullDoubleValue("--double-option", &double_value)); + ASSERT_DOUBLE_EQ(double_value, -32.75); + ASSERT_TRUE(options.values.empty()); + + // Check ordered options. + args = {"--ord-str-option", "str1", "--ord-uint-option", "32", "--ord-str-option", "str2"}; + ASSERT_TRUE(cmd.PreprocessOptions(args, option_formats, &options, &ordered_options, nullptr)); + ASSERT_EQ(ordered_options.size(), 3); + ASSERT_EQ(ordered_options[0].first, "--ord-str-option"); + ASSERT_EQ(*(ordered_options[0].second.str_value), "str1"); + ASSERT_EQ(ordered_options[1].first, "--ord-uint-option"); + ASSERT_EQ(ordered_options[1].second.uint_value, 32); + ASSERT_EQ(ordered_options[2].first, "--ord-str-option"); + ASSERT_EQ(*(ordered_options[2].second.str_value), "str2"); + + // Check non_option_args. + ASSERT_TRUE(cmd.PreprocessOptions({"arg1", "--arg2"}, option_formats, &options, &ordered_options, + &non_option_args)); + ASSERT_EQ(non_option_args, std::vector<std::string>({"arg1", "--arg2"})); + // "--" can force following args to be non_option_args. + ASSERT_TRUE(cmd.PreprocessOptions({"--", "--bool-option"}, option_formats, &options, + &ordered_options, &non_option_args)); + ASSERT_EQ(non_option_args, std::vector<std::string>({"--bool-option"})); + + // Check different errors. + // unknown option + ASSERT_FALSE(cmd.PreprocessOptions({"--unknown-option"}, option_formats, &options, + &ordered_options, nullptr)); + // no option value + ASSERT_FALSE( + cmd.PreprocessOptions({"--str-option"}, option_formats, &options, &ordered_options, nullptr)); + // wrong option value format + ASSERT_FALSE(cmd.PreprocessOptions({"--uint-option", "-2"}, option_formats, &options, + &ordered_options, nullptr)); + ASSERT_FALSE(cmd.PreprocessOptions({"--double-option", "str"}, option_formats, &options, + &ordered_options, nullptr)); + // unexpected non_option_args + ASSERT_FALSE(cmd.PreprocessOptions({"non_option_args"}, option_formats, &options, + &ordered_options, nullptr)); +} + +TEST(command, OptionValueMap) { + OptionValue value; + value.uint_value = 10; + + OptionValueMap options; + uint64_t uint_value; + options.values.emplace("--uint-option", value); + ASSERT_FALSE(options.PullUintValue("--uint-option", &uint_value, 11)); + options.values.emplace("--uint-option", value); + ASSERT_FALSE(options.PullUintValue("--uint-option", &uint_value, 0, 9)); + options.values.emplace("--uint-option", value); + ASSERT_TRUE(options.PullUintValue("--uint-option", &uint_value, 10, 10)); + + double double_value; + value.double_value = 0.0; + options.values.emplace("--double-option", value); + ASSERT_FALSE(options.PullDoubleValue("--double-option", &double_value, 1.0)); + options.values.emplace("--double-option", value); + ASSERT_FALSE(options.PullDoubleValue("--double-option", &double_value, -2.0, -1.0)); + options.values.emplace("--double-option", value); + ASSERT_TRUE(options.PullDoubleValue("--double-option", &double_value, 0.0, 0.0)); +} diff --git a/simpleperf/gtest_main.cpp b/simpleperf/gtest_main.cpp index a6062281..013ec603 100644 --- a/simpleperf/gtest_main.cpp +++ b/simpleperf/gtest_main.cpp @@ -36,6 +36,8 @@ #include "utils.h" #include "workload.h" +using namespace simpleperf; + static std::string testdata_dir; #if defined(__ANDROID__) diff --git a/simpleperf/main.cpp b/simpleperf/main.cpp index 49d25481..d5906a25 100644 --- a/simpleperf/main.cpp +++ b/simpleperf/main.cpp @@ -21,6 +21,8 @@ #include "command.h" #include "environment.h" +using namespace simpleperf; + #if defined(__ANDROID__) bool AndroidSecurityCheck() { |