simpleperf: add --cpu to filter cpus in report command.

Also refactor report command to use PreprocessOptions().
Also refactor GetCpusFromString() to check input errors from the --cpu
option.
Also simplify return type of OptionValueMap::PullValues(), to reduce one
block layer when using it.

Bug: 160611908
Test: run simpleperf_unit_test.

Change-Id: Ic6749909c73f448dd073ef5501834ef0afc341cb
diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp
index 7485aba..01f513e 100644
--- a/simpleperf/cmd_report_test.cpp
+++ b/simpleperf/cmd_report_test.cpp
@@ -16,10 +16,12 @@
 
 #include <gtest/gtest.h>
 
+#include <regex>
 #include <set>
 #include <unordered_map>
 
 #include <android-base/file.h>
+#include <android-base/parseint.h>
 #include <android-base/strings.h>
 
 #include "command.h"
@@ -65,6 +67,17 @@
     success = true;
   }
 
+  size_t GetSampleCount() {
+    std::smatch m;
+    if (std::regex_search(content, m, std::regex(R"(Samples: (\d+))"))) {
+      size_t count;
+      if (android::base::ParseUint(m[1], &count)) {
+        return count;
+      }
+    }
+    return 0;
+  }
+
   std::string content;
   std::vector<std::string> lines;
   bool success;
@@ -221,7 +234,7 @@
         Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--pids", "2,bogus"});
         exit(success ? 0 : 1);
       },
-      testing::ExitedWithCode(1), "invalid id in --pids option: bogus");
+      testing::ExitedWithCode(1), "Invalid tid 'bogus'");
 }
 
 TEST_F(ReportCommandTest, tid_filter_option) {
@@ -245,7 +258,7 @@
         Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--tids", "2,bogus"});
         exit(success ? 0 : 1);
       },
-      testing::ExitedWithCode(1), "invalid id in --tids option: bogus");
+      testing::ExitedWithCode(1), "Invalid tid 'bogus'");
 }
 
 TEST_F(ReportCommandTest, comm_filter_option) {
@@ -524,6 +537,22 @@
   ASSERT_NE(std::string::npos, content.find("generic_jit_symbol_one"));
 }
 
+TEST_F(ReportCommandTest, cpu_option) {
+  Report("perf.data");
+  ASSERT_TRUE(success);
+  ASSERT_EQ(2409, GetSampleCount());
+  Report("perf.data", {"--cpu", "2"});
+  ASSERT_TRUE(success);
+  ASSERT_EQ(603, GetSampleCount());
+  Report("perf.data", {"--cpu", "2-6,16"});
+  ASSERT_TRUE(success);
+  ASSERT_EQ(1806, GetSampleCount());
+  Report("perf.data", {"--cpu", "2-6", "--cpu", "16"});
+  ASSERT_TRUE(success);
+  ASSERT_EQ(1806, GetSampleCount());
+  ASSERT_FALSE(ReportCmd()->Run({"-i", GetTestData("perf.data"), "--cpu", "-2"}));
+}
+
 #if defined(__linux__)
 #include "event_selection_set.h"