From: Konrad Lipinski Date: Fri, 20 Dec 2019 12:35:18 +0000 (+0100) Subject: WiP Add prepare_app* benchmark X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fref%2Fdrafts%2Fsecurity-manager;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git WiP Add prepare_app* benchmark Change-Id: Id0b92350b620546352adba6b2305f4b3c6435f56 --- diff --git a/src/common/synchronization_pipe.cpp b/src/common/synchronization_pipe.cpp index dcf9d30c..0a1fbc9f 100644 --- a/src/common/synchronization_pipe.cpp +++ b/src/common/synchronization_pipe.cpp @@ -20,6 +20,7 @@ * @brief A crippled abstraction of widely praised, but often misused communication mechanism */ +#include #include #include @@ -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); } diff --git a/src/common/synchronization_pipe.h b/src/common/synchronization_pipe.h index e072ca28..c12de40a 100644 --- a/src/common/synchronization_pipe.h +++ b/src/common/synchronization_pipe.h @@ -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 diff --git a/src/common/tests_common.cpp b/src/common/tests_common.cpp index 235b062c..17deb417 100644 --- a/src/common/tests_common.cpp +++ b/src/common/tests_common.cpp @@ -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 &process) { diff --git a/src/common/tests_common.h b/src/common/tests_common.h index bfb46d95..2035b8b0 100644 --- a/src/common/tests_common.h +++ b/src/common/tests_common.h @@ -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 &process); void runInChildParentWait(const std::function &process); diff --git a/src/security-manager-tests/test_cases_prepare_app.cpp b/src/security-manager-tests/test_cases_prepare_app.cpp index ee386061..850bd416 100644 --- a/src/security-manager-tests/test_cases_prepare_app.cpp +++ b/src/security-manager-tests/test_cases_prepare_app.cpp @@ -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 apps; + const auto uid = tmpUser.getUid(); + std::vector 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); +}