OSDN Git Service

ANRdaemon: move trace result from /sdcard to /data am: d93aa41807
[android-x86/system-extras.git] / perfprofd / tests / perfprofd_test.cc
index b70dd86..3a32204 100644 (file)
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include <android-base/stringprintf.h>
+
 #include "perfprofdcore.h"
+#include "configreader.h"
 #include "perfprofdutils.h"
 #include "perfprofdmockutils.h"
 
@@ -53,11 +56,10 @@ static std::string dest_dir;
 // Temporary config file that we will emit for the daemon to read
 #define CONFIGFILE "perfprofd.conf"
 
-static std::string encoded_file_path()
+static std::string encoded_file_path(int seq)
 {
-  std::string path(dest_dir);
-  path += "/perf.data.encoded";
-  return path;
+  return android::base::StringPrintf("%s/perf.data.encoded.%d",
+                                     dest_dir.c_str(), seq);
 }
 
 class PerfProfdTest : public testing::Test {
@@ -70,7 +72,6 @@ class PerfProfdTest : public testing::Test {
 
   virtual void TearDown() {
     mock_perfprofdutils_finish();
-    remove_dest_dir();
   }
 
   void noclean() {
@@ -96,11 +97,6 @@ class PerfProfdTest : public testing::Test {
     system(cmd.c_str());
   }
 
-  void remove_dest_dir() {
-    setup_dirs();
-    ASSERT_FALSE(dest_dir == "");
-  }
-
   void setup_dirs()
   {
     if (test_dir == "") {
@@ -147,14 +143,13 @@ class PerfProfdRunner {
  public:
   PerfProfdRunner()
       : config_path_(test_dir)
-      , aux_config_path_(dest_dir)
   {
     config_path_ += "/" CONFIGFILE;
-    aux_config_path_ += "/" CONFIGFILE;
   }
 
   ~PerfProfdRunner()
   {
+    remove_processed_file();
   }
 
   void addToConfig(const std::string &line)
@@ -163,36 +158,42 @@ class PerfProfdRunner {
     config_text_ += "\n";
   }
 
-  void addToAuxConfig(const std::string &line)
-  {
-    aux_config_text_ += line;
-    aux_config_text_ += "\n";
-  }
-
   void remove_semaphore_file()
   {
-    std::string semaphore(dest_dir);
+    std::string semaphore(test_dir);
     semaphore += "/" SEMAPHORE_FILENAME;
     unlink(semaphore.c_str());
   }
 
   void create_semaphore_file()
   {
-    std::string semaphore(dest_dir);
+    std::string semaphore(test_dir);
     semaphore += "/" SEMAPHORE_FILENAME;
     close(open(semaphore.c_str(), O_WRONLY|O_CREAT));
   }
 
+  void write_processed_file(int start_seq, int end_seq)
+  {
+    std::string processed = test_dir + "/" PROCESSED_FILENAME;
+    FILE *fp = fopen(processed.c_str(), "w");
+    for (int i = start_seq; i < end_seq; i++) {
+      fprintf(fp, "%d\n", i);
+    }
+    fclose(fp);
+  }
+
+  void remove_processed_file()
+  {
+    std::string processed = test_dir + "/" PROCESSED_FILENAME;
+    unlink(processed.c_str());
+  }
+
   int invoke()
   {
     static const char *argv[3] = { "perfprofd", "-c", "" };
     argv[2] = config_path_.c_str();
 
     writeConfigFile(config_path_, config_text_);
-    if (aux_config_text_.length()) {
-      writeConfigFile(aux_config_path_, aux_config_text_);
-    }
-
 
     // execute daemon main
     return perfprofd_main(3, (char **) argv);
@@ -201,8 +202,6 @@ class PerfProfdRunner {
  private:
   std::string config_path_;
   std::string config_text_;
-  std::string aux_config_path_;
-  std::string aux_config_text_;
 
   void writeConfigFile(const std::string &config_path,
                        const std::string &config_text)
@@ -220,13 +219,13 @@ static void readEncodedProfile(const char *testpoint,
                                wireless_android_play_playlog::AndroidPerfProfile &encodedProfile)
 {
   struct stat statb;
-  int perf_data_stat_result = stat(encoded_file_path().c_str(), &statb);
+  int perf_data_stat_result = stat(encoded_file_path(0).c_str(), &statb);
   ASSERT_NE(-1, perf_data_stat_result);
 
   // read
   std::string encoded;
   encoded.resize(statb.st_size);
-  FILE *ifp = fopen(encoded_file_path().c_str(), "r");
+  FILE *ifp = fopen(encoded_file_path(0).c_str(), "r");
   ASSERT_NE(nullptr, ifp);
   size_t items_read = fread((void*) encoded.data(), statb.st_size, 1, ifp);
   ASSERT_EQ(1, items_read);
@@ -300,14 +299,14 @@ TEST_F(PerfProfdTest, MissingGMS)
   //
   // AWP requires cooperation between the daemon and the GMS core
   // piece. If we're running on a device that has an old or damaged
-  // version of GMS core, then the directory we're interested in may
-  // not be there. This test insures that the daemon does the right
-  // thing in this case.
+  // version of GMS core, then the config directory we're interested in
+  // may not be there. This test insures that the daemon does the
+  // right thing in this case.
   //
   PerfProfdRunner runner;
   runner.addToConfig("only_debug_build=0");
-  runner.addToConfig("trace_config_read=1");
-  runner.addToConfig("destination_directory=/does/not/exist");
+  runner.addToConfig("trace_config_read=0");
+  runner.addToConfig("config_directory=/does/not/exist");
   runner.addToConfig("main_loop_iterations=1");
   runner.addToConfig("use_fixed_seed=1");
   runner.addToConfig("collection_interval=100");
@@ -320,26 +319,17 @@ TEST_F(PerfProfdTest, MissingGMS)
 
   // Verify log contents
   const std::string expected = RAW_RESULT(
-      I: starting Android Wide Profiling daemon
-      I: config file path set to /data/nativetest/perfprofd_test/perfprofd.conf
-      I: option destination_directory set to /does/not/exist
-      I: option main_loop_iterations set to 1
-      I: option use_fixed_seed set to 1
-      I: option collection_interval set to 100
-      I: random seed set to 1
       I: sleep 90 seconds
-      W: unable to open destination directory /does/not/exist: (No such file or directory)
-      I: profile collection skipped (missing destination directory)
-      I: sleep 10 seconds
-      I: finishing Android Wide Profiling daemon
-                                          );\
+      W: unable to open config directory /does/not/exist: (No such file or directory)
+      I: profile collection skipped (missing config directory)
+                                          );
 
   // check to make sure entire log matches
-  bool compareEntireLog = true;
   compareLogMessages(mock_perfprofdutils_getlogged(),
-                     expected, "MissingGMS", compareEntireLog);
+                     expected, "MissingGMS");
 }
 
+
 TEST_F(PerfProfdTest, MissingOptInSemaphoreFile)
 {
   //
@@ -351,6 +341,8 @@ TEST_F(PerfProfdTest, MissingOptInSemaphoreFile)
   //
   PerfProfdRunner runner;
   runner.addToConfig("only_debug_build=0");
+  std::string cfparam("config_directory="); cfparam += test_dir;
+  runner.addToConfig(cfparam);
   std::string ddparam("destination_directory="); ddparam += dest_dir;
   runner.addToConfig(ddparam);
   runner.addToConfig("main_loop_iterations=1");
@@ -385,6 +377,8 @@ TEST_F(PerfProfdTest, MissingPerfExecutable)
   PerfProfdRunner runner;
   runner.addToConfig("only_debug_build=0");
   runner.addToConfig("trace_config_read=1");
+  std::string cfparam("config_directory="); cfparam += test_dir;
+  runner.addToConfig(cfparam);
   std::string ddparam("destination_directory="); ddparam += dest_dir;
   runner.addToConfig(ddparam);
   runner.addToConfig("main_loop_iterations=1");
@@ -420,6 +414,8 @@ TEST_F(PerfProfdTest, BadPerfRun)
   //
   PerfProfdRunner runner;
   runner.addToConfig("only_debug_build=0");
+  std::string cfparam("config_directory="); cfparam += test_dir;
+  runner.addToConfig(cfparam);
   std::string ddparam("destination_directory="); ddparam += dest_dir;
   runner.addToConfig(ddparam);
   runner.addToConfig("main_loop_iterations=1");
@@ -485,56 +481,18 @@ TEST_F(PerfProfdTest, ConfigFileParsing)
                      expected, "ConfigFileParsing");
 }
 
-TEST_F(PerfProfdTest, AuxiliaryConfigFile)
+TEST_F(PerfProfdTest, ProfileCollectionAnnotations)
 {
-  //
-  // We want to be able to tweak profile collection parameters (sample
-  // duration, etc) using changes to gservices. To carry this out, the
-  // GMS core upload service writes out an perfprofd.conf config file when
-  // it starts up. This test verifies that we can read this file.
-  //
-
-  // Minimal settings in main config file
-  PerfProfdRunner runner;
-  runner.addToConfig("only_debug_build=0");
-  runner.addToConfig("trace_config_read=1");
-  runner.addToConfig("use_fixed_seed=1");
-  std::string ddparam("destination_directory="); ddparam += dest_dir;
-  runner.addToConfig(ddparam);
-
-  // Remaining settings in aux config file
-  runner.addToAuxConfig("main_loop_iterations=1");
-  runner.addToAuxConfig("collection_interval=100");
-  runner.addToAuxConfig("perf_path=/system/bin/true");
-  runner.addToAuxConfig("stack_profile=1");
-  runner.addToAuxConfig("sampling_period=9999");
-  runner.addToAuxConfig("sample_duration=333");
-
-  runner.remove_semaphore_file();
-
-  // Kick off daemon
-  int daemon_main_return_code = runner.invoke();
-
-  // Check return code from daemon
-  EXPECT_EQ(0, daemon_main_return_code);
-
-  // Verify log contents
-  const std::string expected = RAW_RESULT(
-      I: reading auxiliary config file /data/nativetest/perfprofd_test/tmp/perfprofd.conf
-      I: option main_loop_iterations set to 1
-      I: option collection_interval set to 100
-      I: option perf_path set to /system/bin/true
-      I: option stack_profile set to 1
-      I: option sampling_period set to 9999
-      I: option sample_duration set to 333
-      I: sleep 90 seconds
-      I: reading auxiliary config file /data/nativetest/perfprofd_test/tmp/perfprofd.conf
-      I: option main_loop_iterations set to 1
-                                          );
-
-  // check to make sure log excerpt matches
-  compareLogMessages(mock_perfprofdutils_getlogged(),
-                     expected, "AuxiliaryConfigFile");
+  unsigned util1 = collect_cpu_utilization();
+  EXPECT_LE(util1, 100);
+  EXPECT_GE(util1, 0);
+
+  // NB: expectation is that when we run this test, the device will be
+  // completed booted, will be on charger, and will not have the camera
+  // active.
+  EXPECT_FALSE(get_booting());
+  EXPECT_TRUE(get_charging());
+  EXPECT_FALSE(get_camera_active());
 }
 
 TEST_F(PerfProfdTest, BasicRunWithCannedPerf)
@@ -548,9 +506,15 @@ TEST_F(PerfProfdTest, BasicRunWithCannedPerf)
   std::string input_perf_data(test_dir);
   input_perf_data += "/canned.perf.data";
 
+  // Set up config to avoid these annotations (they are tested elsewhere)
+  ConfigReader config;
+  config.overrideUnsignedEntry("collect_cpu_utilization", 0);
+  config.overrideUnsignedEntry("collect_charging_state", 0);
+  config.overrideUnsignedEntry("collect_camera_active", 0);
+
   // Kick off encoder and check return code
   PROFILE_RESULT result =
-      encode_to_proto(input_perf_data, encoded_file_path());
+      encode_to_proto(input_perf_data, encoded_file_path(0).c_str(), config, 0);
   EXPECT_EQ(OK_PROFILE_COLLECTION, result);
 
   // Read and decode the resulting perf.data.encoded file
@@ -616,10 +580,13 @@ TEST_F(PerfProfdTest, BasicRunWithLivePerf)
   runner.addToConfig("only_debug_build=0");
   std::string ddparam("destination_directory="); ddparam += dest_dir;
   runner.addToConfig(ddparam);
+  std::string cfparam("config_directory="); cfparam += test_dir;
+  runner.addToConfig(cfparam);
   runner.addToConfig("main_loop_iterations=1");
   runner.addToConfig("use_fixed_seed=12345678");
+  runner.addToConfig("max_unprocessed_profiles=100");
   runner.addToConfig("collection_interval=9999");
-  runner.addToConfig("sample_duration=5");
+  runner.addToConfig("sample_duration=2");
 
   // Create semaphore file
   runner.create_semaphore_file();
@@ -654,6 +621,70 @@ TEST_F(PerfProfdTest, BasicRunWithLivePerf)
                      expected, "BasicRunWithLivePerf", true);
 }
 
+TEST_F(PerfProfdTest, MultipleRunWithLivePerf)
+{
+  //
+  // Basic test to exercise the main loop of the daemon. It includes
+  // a live 'perf' run
+  //
+  PerfProfdRunner runner;
+  runner.addToConfig("only_debug_build=0");
+  std::string ddparam("destination_directory="); ddparam += dest_dir;
+  runner.addToConfig(ddparam);
+  std::string cfparam("config_directory="); cfparam += test_dir;
+  runner.addToConfig(cfparam);
+  runner.addToConfig("main_loop_iterations=3");
+  runner.addToConfig("use_fixed_seed=12345678");
+  runner.addToConfig("collection_interval=9999");
+  runner.addToConfig("sample_duration=2");
+  runner.write_processed_file(1, 2);
+
+  // Create semaphore file
+  runner.create_semaphore_file();
+
+  // Kick off daemon
+  int daemon_main_return_code = runner.invoke();
+
+  // Check return code from daemon
+  EXPECT_EQ(0, daemon_main_return_code);
+
+  // Read and decode the resulting perf.data.encoded file
+  wireless_android_play_playlog::AndroidPerfProfile encodedProfile;
+  readEncodedProfile("BasicRunWithLivePerf", encodedProfile);
+
+  // Examine what we get back. Since it's a live profile, we can't
+  // really do much in terms of verifying the contents.
+  EXPECT_LT(0, encodedProfile.programs_size());
+
+  // Examine that encoded.1 file is removed while encoded.{0|2} exists.
+  EXPECT_EQ(0, access(encoded_file_path(0).c_str(), F_OK));
+  EXPECT_NE(0, access(encoded_file_path(1).c_str(), F_OK));
+  EXPECT_EQ(0, access(encoded_file_path(2).c_str(), F_OK));
+
+  // Verify log contents
+  const std::string expected = RAW_RESULT(
+      I: starting Android Wide Profiling daemon
+      I: config file path set to /data/nativetest/perfprofd_test/perfprofd.conf
+      I: random seed set to 12345678
+      I: sleep 674 seconds
+      I: initiating profile collection
+      I: profile collection complete
+      I: sleep 9325 seconds
+      I: sleep 4974 seconds
+      I: initiating profile collection
+      I: profile collection complete
+      I: sleep 5025 seconds
+      I: sleep 501 seconds
+      I: initiating profile collection
+      I: profile collection complete
+      I: sleep 9498 seconds
+      I: finishing Android Wide Profiling daemon
+                                          );
+  // check to make sure log excerpt matches
+  compareLogMessages(mock_perfprofdutils_getlogged(),
+                     expected, "BasicRunWithLivePerf", true);
+}
+
 int main(int argc, char **argv) {
   executable_path = argv[0];
   // switch to / before starting testing (perfprofd