userLockedForFailedAttempt: add unit test
This commit adds unit test for the |userLockedForFailedAttempt|
function. In order to do so, this commits adds a new virtual function
which reads the failed attempt. The function is overridden in unit test.
Tested: unit test passed.
Coverage:
lines......: 83.1% (2007 of 2415 lines)
functions..: 94.1% (430 of 457 functions)
branches...: 32.3% (3181 of 9855 branches)
Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Change-Id: I940ec42936c8b1c387fc0f19db13bc90a61c9852
diff --git a/test/user_mgr_test.cpp b/test/user_mgr_test.cpp
index f613f9e..474e055 100644
--- a/test/user_mgr_test.cpp
+++ b/test/user_mgr_test.cpp
@@ -290,6 +290,9 @@
MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
(override));
+ MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
+ (override));
+
protected:
static sdbusplus::bus_t busInTest;
std::string tempPamConfigFile;
@@ -716,5 +719,100 @@
EXPECT_NO_THROW(UserMgr::deleteUser(username));
}
+TEST_F(
+ UserMgrInTest,
+ UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
+{
+ EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
+}
+
+TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
+{
+ std::string username = "user001";
+ initializeAccountPolicy();
+ // Example output from BMC
+ // root@s7106:~# pam_tally2 -u root
+ // Login Failures Latest failure From
+ // root 0
+ std::vector<std::string> output = {"whatever", "root\t0"};
+ EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
+ .WillOnce(testing::Return(output));
+
+ EXPECT_FALSE(userLockedForFailedAttempt(username));
+}
+
+TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
+{
+ std::string username = "user001";
+ initializeAccountPolicy();
+ EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
+ .WillOnce(testing::Throw(
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
+
+ EXPECT_THROW(
+ userLockedForFailedAttempt(username),
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
+}
+
+TEST_F(UserMgrInTest,
+ UserLockedForFailedAttemptThrowsInternalFailureIfFailAttemptsOutOfRange)
+{
+ std::string username = "user001";
+ initializeAccountPolicy();
+ std::vector<std::string> output = {"whatever", "root\t1000000"};
+ EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
+ .WillOnce(testing::Return(output));
+
+ EXPECT_THROW(
+ userLockedForFailedAttempt(username),
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
+}
+
+TEST_F(UserMgrInTest,
+ UserLockedForFailedAttemptThrowsInternalFailureIfNoFailDateTime)
+{
+ std::string username = "user001";
+ initializeAccountPolicy();
+ std::vector<std::string> output = {"whatever", "root\t2"};
+ EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
+ .WillOnce(testing::Return(output));
+
+ EXPECT_THROW(
+ userLockedForFailedAttempt(username),
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
+}
+
+TEST_F(UserMgrInTest,
+ UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
+{
+ std::string username = "user001";
+ initializeAccountPolicy();
+
+ // Choose a date in the past.
+ std::vector<std::string> output = {"whatever",
+ "root\t2\t10/24/2002\t00:00:00"};
+ EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
+ .WillOnce(testing::Return(output));
+
+ EXPECT_THROW(
+ userLockedForFailedAttempt(username),
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
+}
+
+TEST_F(UserMgrInTest,
+ UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
+{
+ std::string username = "user001";
+ initializeAccountPolicy();
+
+ // Choose a date in the past.
+ std::vector<std::string> output = {"whatever",
+ "root\t2\t10/24/02\t00:00:00"};
+ EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
+ .WillOnce(testing::Return(output));
+
+ EXPECT_EQ(userLockedForFailedAttempt(username), false);
+}
+
} // namespace user
} // namespace phosphor
diff --git a/user_mgr.cpp b/user_mgr.cpp
index f7d5e8e..adfa6ab 100644
--- a/user_mgr.cpp
+++ b/user_mgr.cpp
@@ -656,7 +656,7 @@
std::vector<std::string> output;
try
{
- output = executeCmd("/usr/sbin/pam_tally2", "-u", userName.c_str());
+ output = getFailedAttempt(userName.c_str());
}
catch (const InternalFailure& e)
{
@@ -1352,5 +1352,10 @@
(enabled ? "" : "1970-01-01"));
}
+std::vector<std::string> UserMgr::getFailedAttempt(const char* userName)
+{
+ return executeCmd("/usr/sbin/pam_tally2", "-u", userName);
+}
+
} // namespace user
} // namespace phosphor
diff --git a/user_mgr.hpp b/user_mgr.hpp
index 3f0d59c..6f7c7ce 100644
--- a/user_mgr.hpp
+++ b/user_mgr.hpp
@@ -323,6 +323,8 @@
virtual void executeUserModifyUserEnable(const char* userName,
bool enabled);
+ virtual std::vector<std::string> getFailedAttempt(const char* userName);
+
/** @brief check for valid privielge
* method to check valid privilege, and throw if invalid
*