renameUser: add unit test

Like the previous change, this test added unit test for |renameUser|. To
make it happen, this commit introduces a virtual function
|executeUserModify| which is overridden in unit test (see previous
change for why we need such overriding).

Tested: unit test passed.

Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Change-Id: I230a8c12fd6c86d0fccfc00872eff647473c1e94
diff --git a/test/user_mgr_test.cpp b/test/user_mgr_test.cpp
index 4595743..6264182 100644
--- a/test/user_mgr_test.cpp
+++ b/test/user_mgr_test.cpp
@@ -259,6 +259,8 @@
         ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
 
         ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
+
+        ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
     }
 
     ~UserMgrInTest() override
@@ -273,7 +275,9 @@
 
     MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
 
-  protected:
+    MOCK_METHOD(void, executeUserRename, (const char*, const char*),
+                (override));
+
     static sdbusplus::bus_t busInTest;
     std::string tempPamConfigFile;
 };
@@ -452,5 +456,60 @@
     EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
 }
 
+TEST_F(UserMgrInTest, RenameUserOnSuccess)
+{
+    std::string username = "user001";
+    EXPECT_NO_THROW(
+        UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
+    std::string newUsername = "user002";
+
+    EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
+
+    // old username doesn't exist
+    EXPECT_THROW(getUserInfo(username),
+                 sdbusplus::xyz::openbmc_project::User::Common::Error::
+                     UserNameDoesNotExist);
+
+    UserInfoMap userInfo = getUserInfo(newUsername);
+    EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
+    EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
+                testing::UnorderedElementsAre("redfish", "ssh"));
+    EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
+
+    EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
+}
+
+TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
+{
+    std::string username = "user001";
+    EXPECT_NO_THROW(
+        UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
+    std::string newUsername = "user002";
+
+    EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
+                                         testing::StrEq(newUsername)))
+        .WillOnce(testing::Throw(
+            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
+    EXPECT_THROW(
+        UserMgr::renameUser(username, newUsername),
+        sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
+
+    // The original user is unchanged
+    UserInfoMap userInfo = getUserInfo(username);
+    EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
+    EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
+                testing::UnorderedElementsAre("redfish", "ssh"));
+    EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
+
+    EXPECT_NO_THROW(UserMgr::deleteUser(username));
+}
+
+TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
+{
+    EXPECT_THROW(
+        UserMgr::executeUserRename("user0", "user1"),
+        sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
+}
+
 } // namespace user
 } // namespace phosphor
diff --git a/user_mgr.cpp b/user_mgr.cpp
index 37116f6..8656e66 100644
--- a/user_mgr.cpp
+++ b/user_mgr.cpp
@@ -338,9 +338,7 @@
                                 usersList[userName].get()->userGroups());
     try
     {
-        std::string newHomeDir = "/home/" + newUserName;
-        executeCmd("/usr/sbin/usermod", "-l", newUserName.c_str(),
-                   userName.c_str(), "-d", newHomeDir.c_str(), "-m");
+        executeUserRename(userName.c_str(), newUserName.c_str());
     }
     catch (const InternalFailure& e)
     {
@@ -1327,5 +1325,13 @@
     executeCmd("/usr/sbin/userdel", userName, "-r");
 }
 
+void UserMgr::executeUserRename(const char* userName, const char* newUserName)
+{
+    std::string newHomeDir = "/home/";
+    newHomeDir += newUserName;
+    executeCmd("/usr/sbin/usermod", "-l", newUserName, userName, "-d",
+               newHomeDir.c_str(), "-m");
+}
+
 } // namespace user
 } // namespace phosphor
diff --git a/user_mgr.hpp b/user_mgr.hpp
index 0195de8..b057bf0 100644
--- a/user_mgr.hpp
+++ b/user_mgr.hpp
@@ -313,6 +313,9 @@
 
     virtual void executeUserDelete(const char* userName);
 
+    virtual void executeUserRename(const char* userName,
+                                   const char* newUserName);
+
     /** @brief check for valid privielge
      *  method to check valid privilege, and throw if invalid
      *