--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/smack.h>
+#include <sys/capability.h>
+
+#include <thread>
+#include <string>
+#include <memory>
+#include <mutex>
+
+#include <dpl/test/test_runner_child.h>
+#include <dpl/test/test_runner.h>
+
+#include <app_install_helper.h>
+#include <sm_api.h>
+#include <sm_commons.h>
+#include <memory.h>
+
+using namespace SecurityManagerTest;
+
+namespace {
+bool finish = false;
+const size_t THREADS = 10;
+
+const std::string SYNC_TEST_APP("app100");
+
+typedef std::unique_ptr<_cap_struct, decltype(&cap_free)> CapPtr;
+
+std::string thread_errors;
+std::mutex error_mutex;
+
+#define THREAD_ASSERT_MSG(test, message) \
+ do \
+ { \
+ if (!(test)) \
+ { \
+ std::ostringstream assertMsg; \
+ assertMsg << #test << " " << __FILE__ << " " << __LINE__ << " " << \
+ message << std::endl; \
+ std::lock_guard<std::mutex> guard(error_mutex); \
+ thread_errors.append(assertMsg.str()); \
+ } \
+ } while (0)
+
+void threadFn(int i)
+{
+ if (i % 2 == 0) {
+ // block all signals
+ sigset_t sigset;
+ THREAD_ASSERT_MSG(sigfillset(&sigset) == 0, "sigfillset failed");
+ THREAD_ASSERT_MSG(sigprocmask(SIG_BLOCK, &sigset, NULL) == 0, "sigprocmask failed");
+ }
+
+ while (!finish)
+ usleep(1000);
+
+ AppInstallHelper helper(SYNC_TEST_APP.c_str());
+ std::string expectedLabel = helper.generateAppLabel();
+
+ char* label;
+ THREAD_ASSERT_MSG(smack_new_label_from_self(&label) > 0, "smack_new_label_from_self failed");
+ CStringPtr labelPtr(label);
+
+ THREAD_ASSERT_MSG(expectedLabel.compare(label) == 0,
+ "Thread " << i << " has a wrong label: " << label);
+
+ CapPtr expectedCaps(cap_init(), cap_free);
+ THREAD_ASSERT_MSG(expectedCaps, "cap_init() failed");
+ THREAD_ASSERT_MSG(cap_clear(expectedCaps.get()) == 0, "cap_clear() failed");
+
+ CapPtr realCaps(cap_get_proc(), cap_free);
+ THREAD_ASSERT_MSG(realCaps, "cap_get_proc() failed");
+ THREAD_ASSERT_MSG(cap_compare(realCaps.get(), expectedCaps.get()) == 0,
+ "Thread " << i << " has wrong caps");
+}
+
+struct ThreadWrapper
+{
+
+ ThreadWrapper()
+ {
+ }
+ ~ThreadWrapper()
+ {
+ finish = true;
+ thread.join();
+ }
+
+ void run(int i)
+ {
+ THREAD_ASSERT_MSG(!thread.joinable(), "Thread already started");
+ thread = std::thread(threadFn, i);
+ }
+
+ std::thread thread;
+};
+
+} // anonymous namespace
+
+RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_PREPARE_APP)
+
+// TODO merge it into one test
+RUNNER_TEST(security_manager_100_synchronize_credentials_1_prepare)
+{
+ AppInstallHelper helper(SYNC_TEST_APP.c_str());
+
+ InstallRequest install;
+ install.setAppId(helper.getAppId());
+ install.setPkgId(helper.getPkgId());
+ Api::install(install);
+}
+
+RUNNER_CHILD_TEST(security_manager_100_synchronize_credentials_2_test)
+{
+ AppInstallHelper helper(SYNC_TEST_APP.c_str());
+ {
+ ThreadWrapper threads[THREADS];
+
+ for (size_t i = 0; i < THREADS; i++)
+ threads[i].run(i);
+
+ Api::prepareApp(helper.getAppId().c_str());
+ }
+ RUNNER_ASSERT_MSG(thread_errors.empty(), std::endl << thread_errors);
+}
+
+RUNNER_TEST(security_manager_100_synchronize_credentials_3_cleanup)
+{
+ AppInstallHelper helper(SYNC_TEST_APP.c_str());
+
+ InstallRequest uninstall;
+ uninstall.setAppId(helper.getAppId());
+ Api::uninstall(uninstall);
+}