From 72787be539ea0f165ffcbe72ab7fae2781935fd4 Mon Sep 17 00:00:00 2001 From: Sangyoon Jang Date: Fri, 23 Dec 2016 16:03:05 +0900 Subject: [PATCH] Fix smoketest Smoketest should test both global/local case. This patch make smoketest can test global/local test, but test only global case because of current platform policy. It should be test local case also later. Change-Id: I160009196d8f7997fe91ebd2d8ab0d653b2da347 Signed-off-by: Sangyoon Jang --- src/unit_tests/smoke_test.cc | 216 ++++++++++++++++++++++++++++--------------- 1 file changed, 139 insertions(+), 77 deletions(-) diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index 01ff7a7..6731a6c 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -40,20 +40,28 @@ namespace ci = common_installer; namespace { -const uid_t kTestUserId = tzplatform_getuid(TZ_SYS_DEFAULT_USER); -const gid_t kTestGroupId = tzplatform_getgid(TZ_SYS_DEFAULT_USER); -const char kTestGroupName[] = "system_share"; +const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); +const uid_t kGlobalUserGid = tzplatform_getgid(TZ_SYS_GLOBALAPP_USER); +// TODO(s89.jang): Test local case also +const uid_t kTestUserId = kGlobalUserUid; +const gid_t kTestGroupId = kGlobalUserGid; +const char kSystemShareGroupName[] = "system_share"; const std::string kTestUserIdStr = std::to_string(kTestUserId); const bf::path kSmokePackagesDirectory = - "/usr/share/tpk-backend-ut/test_samples/smoke/"; - -const char kApplicationDir[] = ".applications"; -const char kApplicationDirBackup[] = ".applications.bck"; -const char KUserAppsDir[] = "apps_rw"; -const char KUserAppsDirBackup[] = "apps_rw.bck"; -const char kUserDataBaseDir[] = "/opt/dbspace/user"; +"/usr/share/tpk-backend-ut/test_samples/smoke/"; + +// common entries +const std::vector kDBEntries = { + {".pkgmgr_parser.db"}, + {".pkgmgr_parser.db-journal"}, + {".pkgmgr_cert.db"}, + {".pkgmgr_cert.db-journal"}, +}; +// globaluser entries +const char kGlobalManifestDir[] = "/opt/share/packages"; +const char kSkelDir[] = "/etc/skel/apps_rw"; enum class RequestResult { NORMAL, @@ -156,24 +164,48 @@ bool ValidateFileContentInPackage(const std::string& pkgid, return content == expected; } -void ValidatePackageFS(const std::string& pkgid, const std::string& appid) { - bf::path root_path = ci::GetRootAppPath(false, - kTestUserId); +void ValidatePackageRWFS(const std::string& pkgid, uid_t uid, gid_t gid) { + bf::path root_path = ci::GetRootAppPath(false, uid); bf::path package_path = root_path / pkgid; - bf::path binary_path = package_path / "bin" / appid; bf::path data_path = package_path / "data"; - bf::path shared_path = package_path / "shared"; bf::path cache_path = package_path / "cache"; + bf::path shared_data_path = package_path / "shared" / "data"; + + ASSERT_TRUE(bf::exists(data_path)); + ASSERT_TRUE(bf::exists(cache_path)); + + struct stat stats; + stat(data_path.c_str(), &stats); + // gid of data, and shared/data should be system_share + boost::optional system_share = + ci::GetGidByGroupName(kSystemShareGroupName); + ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << data_path; + ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " << data_path; + if (bf::exists(shared_data_path)) { + stat(shared_data_path.c_str(), &stats); + ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << shared_data_path; + ASSERT_EQ(*system_share, stats.st_gid) << "Invalid gid: " + << shared_data_path; + } + + stat(cache_path.c_str(), &stats); + ASSERT_EQ(uid, stats.st_uid) << "Invalid gid: " << cache_path; + ASSERT_EQ(gid, stats.st_gid) << "Invalid gid: " << cache_path; +} + +void ValidatePackageFS(const std::string& pkgid, const std::string& appid, + uid_t uid, gid_t gid) { + bf::path root_path = ci::GetRootAppPath(false, uid); + bf::path package_path = root_path / pkgid; + bf::path binary_path = package_path / "bin" / appid; + bf::path shared_path = package_path / "shared"; ASSERT_TRUE(bf::exists(root_path)); ASSERT_TRUE(bf::exists(package_path)); ASSERT_TRUE(bf::exists(binary_path)); - ASSERT_TRUE(bf::exists(data_path)); ASSERT_TRUE(bf::exists(shared_path)); - ASSERT_TRUE(bf::exists(cache_path)); bf::path manifest_path = - bf::path(getUserManifestPath( - kTestUserId, false)) / (pkgid + ".xml"); + bf::path(getUserManifestPath(uid, false)) / (pkgid + ".xml"); ASSERT_TRUE(bf::exists(manifest_path)); // backups should not exist @@ -186,15 +218,12 @@ void ValidatePackageFS(const std::string& pkgid, const std::string& appid) { iter != bf::recursive_directory_iterator(); ++iter) { if (bf::is_symlink(symlink_status(iter->path()))) continue; + if (iter->path().filename() == "data") + continue; struct stat stats; stat(iter->path().c_str(), &stats); - ASSERT_EQ(kTestUserId, stats.st_uid) << "Invalid uid: " << iter->path(); - if (iter->path().filename() == "data") { - boost::optional gid = ci::GetGidByGroupName(kTestGroupName); - ASSERT_EQ(*gid, stats.st_gid) << "Invalid gid: " << iter->path(); - } else { - ASSERT_EQ(kTestGroupId, stats.st_gid) << "Invalid gid: " << iter->path(); - } + ASSERT_EQ(uid, stats.st_uid) << "Invalid uid: " << iter->path(); + ASSERT_EQ(gid, stats.st_gid) << "Invalid gid: " << iter->path(); } } @@ -220,7 +249,14 @@ void ValidatePackage(const std::string& pkgid, const std::string& appid) { ASSERT_TRUE(ci::QueryIsPackageInstalled( pkgid, ci::GetRequestMode(kTestUserId), kTestUserId)); - ValidatePackageFS(pkgid, appid); + ValidatePackageFS(pkgid, appid, kTestUserId, kTestGroupId); + if (kTestUserId == kGlobalUserUid) { + ci::UserList list = ci::GetUserList(); + for (auto& l : list) + ValidatePackageRWFS(pkgid, std::get<0>(l), std::get<1>(l)); + } else { + ValidatePackageRWFS(pkgid, kTestUserId, kTestGroupId); + } } void CheckPackageNonExistance(const std::string& pkgid, @@ -367,65 +403,93 @@ ci::AppInstaller::Result Recover(const bf::path& recovery_file, return CallBackend(SIZEOFARRAY(argv), argv, mode); } +void BackupPath(const bf::path& path) { + bf::path backup_path = path.string() + ".bck"; + std::cout << "Backup path: " << path << " to " << backup_path << std::endl; + bs::error_code error; + bf::remove_all(backup_path, error); + if (error) + LOG(ERROR) << "Remove failed: " << backup_path + << " (" << error.message() << ")"; + if (bf::exists(path)) { + bf::rename(path, backup_path, error); + if (error) + LOG(ERROR) << "Failed to setup test environment. Does some previous" + << " test crashed? Path: " + << backup_path << " should not exist."; + assert(!error); + } +} + +void RestorePath(const bf::path& path) { + bf::path backup_path = path.string() + ".bck"; + std::cout << "Restore path: " << path << " from " << backup_path << std::endl; + bs::error_code error; + bf::remove_all(path, error); + if (error) + LOG(ERROR) << "Remove failed: " << path + << " (" << error.message() << ")"; + if (bf::exists(backup_path)) { + bf::rename(backup_path, path, error); + if (error) + LOG(ERROR) << "Failed to restore backup path: " << backup_path + << " (" << error.message() << ")"; + } +} + +std::vector SetupBackupDirectories(uid_t uid) { + std::vector entries; + bf::path db_dir = bf::path("/opt/dbspace"); + if (uid != kGlobalUserUid) + db_dir = db_dir / "user" / std::to_string(uid); + for (auto e : kDBEntries) { + bf::path path = db_dir / e; + entries.emplace_back(path); + } + + if (uid == kGlobalUserUid) { + entries.emplace_back(kSkelDir); + entries.emplace_back(kGlobalManifestDir); + ci::UserList list = ci::GetUserList(); + for (auto l : list) { + bf::path apps = std::get<2>(l) / "apps_rw"; + entries.emplace_back(apps); + } + } else { + tzplatform_set_user(uid); + bf::path approot = tzplatform_getenv(TZ_USER_APPROOT); + tzplatform_reset_user(); + entries.emplace_back(approot); + } + + bf::path apps_rw = ci::GetRootAppPath(false, uid); + entries.emplace_back(apps_rw); + + return entries; +} + } // namespace namespace common_installer { class SmokeEnvironment : public testing::Environment { public: - explicit SmokeEnvironment(const bf::path& home) : home_(home) { + explicit SmokeEnvironment(uid_t uid) : uid_(uid) { } void SetUp() override { - bf::path UserDBDir = bf::path(kUserDataBaseDir) / kTestUserIdStr; - bf::path UserDBDirBackup = UserDBDir.string() + std::string(".bck"); - - bs::error_code error; - bf::remove_all(home_ / kApplicationDirBackup, error); - bf::remove_all(home_ / KUserAppsDirBackup, error); - bf::remove_all(UserDBDirBackup, error); - if (bf::exists(home_ / KUserAppsDir)) { - bf::rename(home_ / KUserAppsDir, home_ / KUserAppsDirBackup, error); - if (error) - LOG(ERROR) << "Failed to setup test environment. Does some previous" - << " test crashed? Directory: " - << (home_ / KUserAppsDirBackup) << " should not exist."; - assert(!error); - } - if (bf::exists(home_ / kApplicationDir)) { - bf::rename(home_ / kApplicationDir, home_ / kApplicationDirBackup, error); - if (error) - LOG(ERROR) << "Failed to setup test environment. Does some previous" - << " test crashed? Directory: " - << (home_ / kApplicationDirBackup) << " should not exist."; - assert(!error); - } - if (bf::exists(UserDBDir)) { - bf::rename(UserDBDir, UserDBDirBackup, error); - if (error) - LOG(ERROR) << "Failed to setup test environment. Does some previous" - << " test crashed? Directory: " - << UserDBDirBackup << " should not exist."; - assert(!error); - } + backups_ = SetupBackupDirectories(uid_); + for (auto& path : backups_) + BackupPath(path); } void TearDown() override { - bf::path UserDBDir = bf::path(kUserDataBaseDir) / kTestUserIdStr; - bf::path UserDBDirBackup = UserDBDir.string() + std::string(".bck"); - - bs::error_code error; - bf::remove_all(home_ / kApplicationDir, error); - bf::remove_all(home_ / KUserAppsDir, error); - bf::remove_all(UserDBDir, error); - if (bf::exists(home_ / KUserAppsDirBackup)) - bf::rename(home_ / KUserAppsDirBackup, home_ / KUserAppsDir, error); - if (bf::exists(home_ / kApplicationDirBackup)) - bf::rename(home_ / kApplicationDirBackup, home_ / kApplicationDir, error); - if (bf::exists(UserDBDirBackup)) - bf::rename(UserDBDirBackup, UserDBDir, error); + // TODO(s89.jang): Uninstall smoke packages to clear security context + for (auto& path : backups_) + RestorePath(path); } private: - bf::path home_; + uid_t uid_; + std::vector backups_; }; class SmokeTest : public testing::Test { @@ -520,7 +584,7 @@ TEST_F(SmokeTest, DisablePkg) { ASSERT_EQ(Install(path), ci::AppInstaller::Result::OK); ASSERT_EQ(DisablePackage(pkgid), ci::AppInstaller::Result::OK); ASSERT_TRUE(ci::QueryIsDisabledPackage(pkgid, kTestUserId)); - ValidatePackageFS(pkgid, {appid}); + ValidatePackage(pkgid, appid); } TEST_F(SmokeTest, RecoveryMode_Tpk_Installation) { @@ -721,9 +785,7 @@ TEST_F(SmokeTest, TEP_Tpk_Mount_TepInstallNoTepUpdateRollback) { int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); - bf::path directory = - bf::path("/home") / tzplatform_getenv(TZ_SYS_DEFAULT_USER); testing::AddGlobalTestEnvironment( - new common_installer::SmokeEnvironment(directory)); + new common_installer::SmokeEnvironment(kGlobalUserUid)); return RUN_ALL_TESTS(); } -- 2.7.4