WiP Add prepare_app* benchmark ref/drafts/security-manager
authorKonrad Lipinski <k.lipinski2@samsung.com>
Fri, 20 Dec 2019 12:35:18 +0000 (13:35 +0100)
committerKonrad Lipinski <k.lipinski2@samsung.com>
Fri, 20 Dec 2019 12:35:18 +0000 (13:35 +0100)
Change-Id: Id0b92350b620546352adba6b2305f4b3c6435f56

src/common/synchronization_pipe.cpp
src/common/synchronization_pipe.h
src/common/tests_common.cpp
src/common/tests_common.h
src/security-manager-tests/test_cases_prepare_app.cpp

index dcf9d30..0a1fbc9 100644 (file)
@@ -20,6 +20,7 @@
  * @brief       A crippled abstraction of widely praised, but often misused communication mechanism
  */
 
+#include <poll.h>
 #include <stdexcept>
 #include <unistd.h>
 
@@ -76,15 +77,33 @@ void SynchronizationPipe::claimChildEp() {
 }
 
 void SynchronizationPipe::post() {
+       post("#", 1);
+}
+
+void SynchronizationPipe::wait() {
+       char dummy;
+       wait(&dummy, 1);
+}
+
+void SynchronizationPipe::pollForWait() {
     RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
-    auto ret = TEMP_FAILURE_RETRY(write(m_writeEp, "#", 1));
+
+       pollfd fds[1];
+       fds->fd = m_readEp;
+       fds->events = POLLIN;
+    auto ret = TEMP_FAILURE_RETRY(poll(fds, 1, -1));
+    RUNNER_ASSERT_ERRNO(ret > 0);
+}
+
+void SynchronizationPipe::post(const void *data, size_t size) {
+    RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
+    auto ret = TEMP_FAILURE_RETRY(write(m_writeEp, data, size));
     RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Write failed ret = " << ret);
 }
 
-void SynchronizationPipe::wait() {
+void SynchronizationPipe::wait(void *data, size_t size) {
     RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
 
-    char buf;
-    auto ret = TEMP_FAILURE_RETRY(read(m_readEp, &buf, 1));
+    auto ret = TEMP_FAILURE_RETRY(read(m_readEp, data, size));
     RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Read failed ret = " << ret);
 }
index e072ca2..c12de40 100644 (file)
@@ -33,6 +33,10 @@ public:
 
     void post();
     void wait();
+       void pollForWait();
+
+       void post(const void *data, size_t size);
+       void wait(void *data, size_t size);
 
 private:
     int m_pipeCP[2];    // Child -> Parent
index 235b062..17deb41 100644 (file)
@@ -226,13 +226,14 @@ void removeDir(const std::string &path)
     RUNNER_ASSERT_ERRNO_MSG(0 == rmdir(path.c_str()), "rmdir for <" << path << "> failed");
 }
 
-void waitPid(pid_t pid)
+pid_t waitPid(pid_t pid)
 {
     int status;
     pid_t ret = waitpid(pid, &status, 0);
-    RUNNER_ASSERT_MSG((ret != -1) && WIFEXITED(status) && WEXITSTATUS(status) == 0,
+    RUNNER_ASSERT_MSG((ret > 0) && WIFEXITED(status) && WEXITSTATUS(status) == 0,
         "Child process exited abnormally" <<
         ": ret=" << ret << ", errno=" << errno << ", status=" << status);
+       return ret;
 }
 
 pid_t runInChild(const std::function<void(void)> &process) {
index bfb46d9..2035b8b 100644 (file)
@@ -56,7 +56,7 @@ void mktreeSafe(const std::string &path, mode_t mode);
 void creatSafe(const std::string &path, mode_t mode);
 void symlinkSafe(const std::string &targetPath, const std::string &linkPath);
 void removeDir(const std::string &path);
-void waitPid(pid_t pid);
+pid_t waitPid(pid_t pid = -1);
 
 pid_t runInChild(const std::function<void(void)> &process);
 void runInChildParentWait(const std::function<void(void)> &process);
index ee38606..850bd41 100644 (file)
@@ -369,3 +369,98 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test)
         Api::cleanupApp(app.getAppId().c_str(), tmpUser.getUid(), pid);
     }
 }
+
+namespace {
+class Timestamp {
+       uint64_t _;
+       explicit Timestamp(uint64_t ts) : _(ts) {}
+public:
+       Timestamp operator-(const Timestamp &other) const {
+               RUNNER_ASSERT(_ > other._);
+               return Timestamp(_ - other._);
+       }
+       Timestamp operator+(const Timestamp &other) const {
+               return Timestamp(_ + other._);
+       }
+       bool operator<(const Timestamp &other) const {
+               return _ < other._;
+       }
+       Timestamp() = default;
+       static Timestamp now() {
+               timespec ts;
+               const auto res = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+        RUNNER_ASSERT_ERRNO(!res);
+               return Timestamp(ts.tv_sec * 1000000000ULL + ts.tv_nsec);
+       }
+       static void report(const Timestamp *ts, size_t n) {
+               //TODO calc/feedback
+               for (size_t i = 0; i < n; i++)
+                       std::cerr << i << ": " << ts[i]._ << '\n';
+       }
+};
+} // namespace
+
+RUNNER_TEST(security_manager_200_prepare_app_perf)
+{
+    TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false);
+    tmpUser.create();
+
+       constexpr int nApps = 2; // 2+ == intermittent fail TODO investigate
+
+       std::vector<AppInstallHelper> apps;
+       const auto uid = tmpUser.getUid();
+       std::vector<ScopedInstaller> appInstalls;
+       apps.reserve(nApps);
+       appInstalls.reserve(nApps);
+
+       for (int i = 0; i < nApps; i++) {
+               apps.emplace_back(AppInstallHelper("app200_" + std::to_string(i), uid));
+               auto &app = apps.back();
+               for (const auto &p : { EXTERNAL_STORAGE_PRIVILEGE, MEDIA_STORAGE_PRIVILEGE })
+                       app.addPrivilege(p);
+               appInstalls.emplace_back(ScopedInstaller(app));
+       }
+
+       SynchronizationPipe synchPipe;
+       for (const auto &app : apps) {
+               pid_t pid = fork();
+               RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+               if (!pid) {
+                       synchPipe.claimChildEp();
+                       RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
+
+                       const auto appId = app.getAppId();
+
+                       synchPipe.post(); // declare readiness to start measuring
+                       synchPipe.pollForWait(); // wait for parent to signal all children simultaneously
+
+                       Timestamp beg = Timestamp::now();
+                       Api::prepareAppCandidate();
+                       Timestamp mid = Timestamp::now();
+                       Api::prepareApp(appId);
+                       Timestamp end = Timestamp::now();
+
+                       Timestamp ts[2] = { mid-beg, end-mid };
+                       synchPipe.post(ts, sizeof ts); // post measurement payload
+                       exit(0);
+               }
+       }
+
+       synchPipe.claimParentEp();
+       for (int i = 0; i < nApps; i++) // wait for all kids to be ready to start measurement
+               synchPipe.wait();
+       synchPipe.post(); // signal them all simultaneously
+
+       Timestamp candidate[nApps], prepare[nApps], everything[nApps];
+       for (int i = 0; i < nApps; i++) {
+               Timestamp ts[2];
+               synchPipe.wait(ts, sizeof ts);
+               candidate[i] = ts[0];
+               prepare[i] = ts[1];
+               everything[i] = ts[0] + ts[1];
+               Api::cleanupApp(apps[i].getAppId(), uid, waitPid());
+       }
+       Timestamp::report(candidate, nApps);
+       Timestamp::report(prepare, nApps);
+       Timestamp::report(everything, nApps);
+}