xref: /openbmc/phosphor-user-manager/test/user_mgr_test.cpp (revision 601d3db44097d89a7d24ae287e8bbe72e7e92d5d)
1 #include "mock_user_mgr.hpp"
2 #include "user_mgr.hpp"
3 
4 #include <sdbusplus/test/sdbus_mock.hpp>
5 #include <xyz/openbmc_project/Common/error.hpp>
6 #include <xyz/openbmc_project/User/Common/error.hpp>
7 
8 #include <exception>
9 #include <filesystem>
10 #include <fstream>
11 #include <vector>
12 
13 #include <gmock/gmock.h>
14 #include <gtest/gtest.h>
15 
16 namespace phosphor
17 {
18 namespace user
19 {
20 
21 using ::testing::Return;
22 using ::testing::Throw;
23 
24 using InternalFailure =
25     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
26 using UserNameDoesNotExist =
27     sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameDoesNotExist;
28 
29 class TestUserMgr : public testing::Test
30 {
31   public:
32     sdbusplus::SdBusMock sdBusMock;
33     sdbusplus::bus_t bus;
34     MockManager mockManager;
35 
36     TestUserMgr() :
37         bus(sdbusplus::get_mocked_new(&sdBusMock)), mockManager(bus, objpath)
38     {}
39 
40     void createLocalUser(const std::string& userName,
41                          std::vector<std::string> groupNames,
42                          const std::string& priv, bool enabled)
43     {
44         sdbusplus::message::object_path tempObjPath(usersObjPath);
45         tempObjPath /= userName;
46         std::string userObj(tempObjPath);
47         mockManager.usersList.emplace(
48             userName, std::make_unique<phosphor::user::Users>(
49                           mockManager.bus, userObj.c_str(), groupNames, priv,
50                           enabled, mockManager));
51     }
52 
53     DbusUserObj createPrivilegeMapperDbusObject(void)
54     {
55         DbusUserObj object;
56         DbusUserObjValue objValue;
57 
58         DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
59         DbusUserPropVariant enabled(true);
60         DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
61         std::string intf = "xyz.openbmc_project.Object.Enable";
62         objValue.emplace(intf, property);
63         object.emplace(objPath, objValue);
64 
65         DbusUserObjPath objectPath(
66             "/xyz/openbmc_project/user/ldap/openldap/role_map/1");
67         std::string group = "ldapGroup";
68         std::string priv = "priv-admin";
69         DbusUserObjProperties properties = {std::make_pair("GroupName", group),
70                                             std::make_pair("Privilege", priv)};
71         std::string interface = "xyz.openbmc_project.User.PrivilegeMapperEntry";
72 
73         objValue.emplace(interface, properties);
74         object.emplace(objectPath, objValue);
75 
76         return object;
77     }
78 
79     DbusUserObj createLdapConfigObjectWithoutPrivilegeMapper(void)
80     {
81         DbusUserObj object;
82         DbusUserObjValue objValue;
83 
84         DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
85         DbusUserPropVariant enabled(true);
86         DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
87         std::string intf = "xyz.openbmc_project.Object.Enable";
88         objValue.emplace(intf, property);
89         object.emplace(objPath, objValue);
90         return object;
91     }
92 };
93 
94 TEST_F(TestUserMgr, ldapEntryDoesNotExist)
95 {
96     std::string userName = "user";
97     UserInfoMap userInfo;
98 
99     EXPECT_CALL(mockManager, getPrimaryGroup(userName))
100         .WillRepeatedly(Throw(UserNameDoesNotExist()));
101     EXPECT_THROW(userInfo = mockManager.getUserInfo(userName),
102                  UserNameDoesNotExist);
103 }
104 
105 TEST_F(TestUserMgr, localUser)
106 {
107     UserInfoMap userInfo;
108     std::string userName = "testUser";
109     std::string privilege = "priv-admin";
110     std::vector<std::string> groups{"testGroup"};
111     // Create local user
112     createLocalUser(userName, groups, privilege, true);
113     EXPECT_CALL(mockManager, userLockedForFailedAttempt(userName)).Times(1);
114     userInfo = mockManager.getUserInfo(userName);
115 
116     EXPECT_EQ(privilege, std::get<std::string>(userInfo["UserPrivilege"]));
117     EXPECT_EQ(groups,
118               std::get<std::vector<std::string>>(userInfo["UserGroups"]));
119     EXPECT_EQ(true, std::get<bool>(userInfo["UserEnabled"]));
120     EXPECT_EQ(false, std::get<bool>(userInfo["UserLockedForFailedAttempt"]));
121     EXPECT_EQ(false, std::get<bool>(userInfo["UserPasswordExpired"]));
122     EXPECT_EQ(false, std::get<bool>(userInfo["RemoteUser"]));
123 }
124 
125 TEST_F(TestUserMgr, ldapUserWithPrivMapper)
126 {
127     UserInfoMap userInfo;
128     std::string userName = "ldapUser";
129     std::string ldapGroup = "ldapGroup";
130     gid_t primaryGid = 1000;
131 
132     EXPECT_CALL(mockManager, getPrimaryGroup(userName))
133         .WillRepeatedly(Return(primaryGid));
134     // Create privilege mapper dbus object
135     DbusUserObj object = createPrivilegeMapperDbusObject();
136     EXPECT_CALL(mockManager, getPrivilegeMapperObject())
137         .WillRepeatedly(Return(object));
138     EXPECT_CALL(mockManager, isGroupMember(userName, primaryGid, ldapGroup))
139         .WillRepeatedly(Return(true));
140     userInfo = mockManager.getUserInfo(userName);
141     EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
142     EXPECT_EQ("priv-admin", std::get<std::string>(userInfo["UserPrivilege"]));
143 }
144 
145 TEST_F(TestUserMgr, ldapUserWithoutPrivMapper)
146 {
147     using ::testing::_;
148 
149     UserInfoMap userInfo;
150     std::string userName = "ldapUser";
151     std::string ldapGroup = "ldapGroup";
152     gid_t primaryGid = 1000;
153 
154     EXPECT_CALL(mockManager, getPrimaryGroup(userName))
155         .WillRepeatedly(Return(primaryGid));
156     // Create LDAP config object without privilege mapper
157     DbusUserObj object = createLdapConfigObjectWithoutPrivilegeMapper();
158     EXPECT_CALL(mockManager, getPrivilegeMapperObject())
159         .WillRepeatedly(Return(object));
160     EXPECT_CALL(mockManager, isGroupMember(_, _, _)).Times(0);
161     userInfo = mockManager.getUserInfo(userName);
162     EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
163     EXPECT_EQ("priv-user", std::get<std::string>(userInfo["UserPrivilege"]));
164 }
165 
166 TEST(GetCSVFromVector, EmptyVectorReturnsEmptyString)
167 {
168     EXPECT_EQ(getCSVFromVector({}), "");
169 }
170 
171 TEST(GetCSVFromVector, ElementsAreJoinedByComma)
172 {
173     EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123"}), "123");
174     EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123", "456"}),
175               "123,456");
176 }
177 
178 TEST(RemoveStringFromCSV, WithoutDeleteStringReturnsFalse)
179 {
180     std::string expected = "whatever,https";
181     std::string str = expected;
182     EXPECT_FALSE(removeStringFromCSV(str, "ssh"));
183     EXPECT_EQ(str, expected);
184 
185     std::string empty;
186     EXPECT_FALSE(removeStringFromCSV(empty, "ssh"));
187 }
188 
189 TEST(RemoveStringFromCSV, WithDeleteStringReturnsTrue)
190 {
191     std::string expected = "whatever";
192     std::string str = "whatever,https";
193     EXPECT_TRUE(removeStringFromCSV(str, "https"));
194     EXPECT_EQ(str, expected);
195 
196     str = "https";
197     EXPECT_TRUE(removeStringFromCSV(str, "https"));
198     EXPECT_EQ(str, "");
199 }
200 
201 namespace
202 {
203 inline constexpr const char* objectRootInTest = "/xyz/openbmc_project/user";
204 
205 // Fake configs; referenced configs on real BMC
206 inline constexpr const char* rawConfig = R"(
207 #
208 # /etc/pam.d/common-password - password-related modules common to all services
209 #
210 # This file is included from other service-specific PAM config files,
211 # and should contain a list of modules that define the services to be
212 # used to change user passwords.  The default is pam_unix.
213 
214 # Explanation of pam_unix options:
215 #
216 # The "sha512" option enables salted SHA512 passwords.  Without this option,
217 # the default is Unix crypt.  Prior releases used the option "md5".
218 #
219 # The "obscure" option replaces the old `OBSCURE_CHECKS_ENAB' option in
220 # login.defs.
221 #
222 # See the pam_unix manpage for other options.
223 
224 # here are the per-package modules (the "Primary" block)
225 password	[success=ok default=die]	pam_faillock.so authsucc
226 password	[success=ok default=die]	pam_pwquality.so debug
227 password	[success=ok default=die]	pam_ipmicheck.so spec_grp_name=ipmi use_authtok
228 password	[success=ok ignore=ignore default=die]	pam_pwhistory.so debug enforce_for_root remember=0 use_authtok
229 password	[success=ok default=die]	pam_unix.so sha512 use_authtok
230 password	[success=1 default=die] 	pam_ipmisave.so spec_grp_name=ipmi spec_pass_file=/etc/ipmi_pass key_file=/etc/key_file
231 # here's the fallback if no module succeeds
232 password	requisite			pam_deny.so
233 # prime the stack with a positive return value if there isn't one already;
234 # this avoids us returning an error just because nothing sets a success code
235 # since the modules above will each just jump around
236 password	required			pam_permit.so
237 # and here are more per-package modules (the "Additional" block)
238 )";
239 inline constexpr const char* rawFailLockConfig = R"(
240 deny=2
241 unlock_time=3
242 )";
243 inline constexpr const char* rawPWQualityConfig = R"(
244 enforce_for_root
245 minlen=8
246 difok=0
247 lcredit=0
248 ocredit=0
249 dcredit=0
250 ucredit=0
251 )";
252 } // namespace
253 
254 void dumpStringToFile(const std::string& str, const std::string& filePath)
255 {
256     std::ofstream outputFileStream;
257 
258     outputFileStream.exceptions(std::ofstream::failbit | std::ofstream::badbit |
259                                 std::ofstream::eofbit);
260 
261     outputFileStream.open(filePath, std::ios::out);
262     outputFileStream << str << "\n" << std::flush;
263     outputFileStream.close();
264 }
265 
266 void removeFile(const std::string& filePath)
267 {
268     std::filesystem::remove(filePath);
269 }
270 
271 class UserMgrInTest : public testing::Test, public UserMgr
272 {
273   public:
274     UserMgrInTest() : UserMgr(busInTest, objectRootInTest)
275     {
276         tempPamConfigFile = "/tmp/test-data-XXXXXX";
277         mktemp(tempPamConfigFile.data());
278         EXPECT_NO_THROW(dumpStringToFile(rawConfig, tempPamConfigFile));
279         tempFaillockConfigFile = "/tmp/test-data-XXXXXX";
280         mktemp(tempFaillockConfigFile.data());
281         EXPECT_NO_THROW(
282             dumpStringToFile(rawFailLockConfig, tempFaillockConfigFile));
283         tempPWQualityConfigFile = "/tmp/test-data-XXXXXX";
284         mktemp(tempPWQualityConfigFile.data());
285         EXPECT_NO_THROW(
286             dumpStringToFile(rawPWQualityConfig, tempPWQualityConfigFile));
287         // Set config files to test files
288         pamPasswdConfigFile = tempPamConfigFile;
289         faillockConfigFile = tempFaillockConfigFile;
290         pwQualityConfigFile = tempPWQualityConfigFile;
291 
292         ON_CALL(*this, executeUserAdd).WillByDefault(testing::Return());
293 
294         ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
295 
296         ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
297 
298         ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
299 
300         ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
301             .WillByDefault(testing::Return());
302 
303         ON_CALL(*this, executeUserModifyUserEnable)
304             .WillByDefault(testing::Return());
305 
306         ON_CALL(*this, executeGroupCreation(testing::_))
307             .WillByDefault(testing::Return());
308 
309         ON_CALL(*this, executeGroupDeletion(testing::_))
310             .WillByDefault(testing::Return());
311 
312         ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
313 
314         ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
315     }
316 
317     ~UserMgrInTest() override
318     {
319         EXPECT_NO_THROW(removeFile(tempPamConfigFile));
320         EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
321         EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
322     }
323 
324     MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
325                 (override));
326 
327     MOCK_METHOD(void, executeUserDelete, (const char*), (override));
328 
329     MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
330 
331     MOCK_METHOD(void, executeUserRename, (const char*, const char*),
332                 (override));
333 
334     MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
335                 (override));
336 
337     MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
338                 (override));
339 
340     MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
341                 (override));
342 
343     MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
344 
345     MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
346 
347   protected:
348     static sdbusplus::bus_t busInTest;
349     std::string tempPamConfigFile;
350     std::string tempFaillockConfigFile;
351     std::string tempPWQualityConfigFile;
352 };
353 
354 sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
355 
356 TEST_F(UserMgrInTest, GetPamModuleArgValueOnSuccess)
357 {
358     std::string remember;
359     EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
360               0);
361     EXPECT_EQ(remember, "0");
362 }
363 
364 TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
365 {
366     std::string minlen;
367     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
368               0);
369     EXPECT_EQ(minlen, "8");
370     std::string deny;
371     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
372     EXPECT_EQ(deny, "2");
373 }
374 
375 TEST_F(UserMgrInTest, SetPamModuleArgValueOnSuccess)
376 {
377     EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), 0);
378     std::string remember;
379     EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
380               0);
381     EXPECT_EQ(remember, "1");
382 }
383 
384 TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
385 {
386     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
387               0);
388     std::string minlen;
389     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
390               0);
391     EXPECT_EQ(minlen, "16");
392 
393     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
394     std::string deny;
395     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
396     EXPECT_EQ(deny, "3");
397 }
398 
399 TEST_F(UserMgrInTest, GetPamModuleArgValueOnFailure)
400 {
401     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
402     std::string remember;
403     EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
404               -1);
405 
406     EXPECT_NO_THROW(removeFile(tempPamConfigFile));
407     EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
408               -1);
409 }
410 
411 TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
412 {
413     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
414     std::string minlen;
415     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
416               -1);
417 
418     EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
419     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
420               -1);
421 
422     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
423     std::string deny;
424     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
425 
426     EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
427     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
428 }
429 
430 TEST_F(UserMgrInTest, SetPamModuleArgValueOnFailure)
431 {
432     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
433     EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
434 
435     EXPECT_NO_THROW(removeFile(tempPamConfigFile));
436     EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
437 }
438 
439 TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
440 {
441     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
442     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
443               -1);
444 
445     EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
446     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
447               -1);
448 
449     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
450     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
451 
452     EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
453     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
454 }
455 
456 TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
457 {
458     EXPECT_THROW(
459         isUserExist(""),
460         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
461 }
462 
463 TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
464 {
465     EXPECT_THROW(throwForUserDoesNotExist("whatever"),
466                  sdbusplus::xyz::openbmc_project::User::Common::Error::
467                      UserNameDoesNotExist);
468 }
469 
470 TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
471 {
472     EXPECT_THROW(
473         throwForUserExists("root"),
474         sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
475 }
476 
477 TEST_F(
478     UserMgrInTest,
479     ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
480 {
481     std::string strWith17Chars(17, 'A');
482     EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
483                  sdbusplus::xyz::openbmc_project::User::Common::Error::
484                      UserNameGroupFail);
485 }
486 
487 TEST_F(
488     UserMgrInTest,
489     ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
490 {
491     std::string strWith31Chars(31, 'A');
492     EXPECT_THROW(
493         throwForUserNameConstraints(strWith31Chars, {}),
494         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
495 }
496 
497 TEST_F(UserMgrInTest,
498        ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
499 {
500     std::string startWithNumber = "0ABC";
501     EXPECT_THROW(
502         throwForUserNameConstraints(startWithNumber, {"ipmi"}),
503         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
504 }
505 
506 TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
507 {
508     EXPECT_THROW(
509         UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
510         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
511 }
512 
513 TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
514 {
515     EXPECT_THROW(
516         UserMgr::executeUserDelete("user0"),
517         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
518 }
519 
520 TEST_F(UserMgrInTest,
521        ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
522 {
523     EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
524     EXPECT_THROW(
525         throwForMaxGrpUserCount({"ipmi"}),
526         sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
527 }
528 
529 TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
530 {
531     EXPECT_CALL(*this, executeUserAdd)
532         .WillOnce(testing::Throw(
533             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
534     EXPECT_THROW(
535         createUser("whatever", {"redfish"}, "", true),
536         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
537 }
538 
539 TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
540 {
541     std::string username = "user";
542     EXPECT_NO_THROW(
543         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
544     EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
545         .WillOnce(testing::Throw(
546             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
547         .WillOnce(testing::DoDefault());
548 
549     EXPECT_THROW(
550         deleteUser(username),
551         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
552     EXPECT_NO_THROW(UserMgr::deleteUser(username));
553 }
554 
555 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
556 {
557     EXPECT_THROW(
558         throwForInvalidPrivilege("whatever"),
559         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
560 }
561 
562 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
563 {
564     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
565     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
566     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
567 }
568 
569 TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
570 {
571     EXPECT_THROW(
572         throwForInvalidGroups({"whatever"}),
573         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
574 }
575 
576 TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
577 {
578     EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
579     EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
580     EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
581     EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
582     EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
583 }
584 
585 TEST_F(UserMgrInTest, RenameUserOnSuccess)
586 {
587     std::string username = "user001";
588     EXPECT_NO_THROW(
589         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
590     std::string newUsername = "user002";
591 
592     EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
593 
594     // old username doesn't exist
595     EXPECT_THROW(getUserInfo(username),
596                  sdbusplus::xyz::openbmc_project::User::Common::Error::
597                      UserNameDoesNotExist);
598 
599     UserInfoMap userInfo = getUserInfo(newUsername);
600     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
601     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
602                 testing::UnorderedElementsAre("redfish", "ssh"));
603     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
604 
605     EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
606 }
607 
608 TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
609 {
610     std::string username = "user001";
611     EXPECT_NO_THROW(
612         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
613     std::string newUsername = "user002";
614 
615     EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
616                                          testing::StrEq(newUsername)))
617         .WillOnce(testing::Throw(
618             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
619     EXPECT_THROW(
620         UserMgr::renameUser(username, newUsername),
621         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
622 
623     // The original user is unchanged
624     UserInfoMap userInfo = getUserInfo(username);
625     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
626     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
627                 testing::UnorderedElementsAre("redfish", "ssh"));
628     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
629 
630     EXPECT_NO_THROW(UserMgr::deleteUser(username));
631 }
632 
633 TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
634 {
635     EXPECT_THROW(
636         UserMgr::executeUserRename("user0", "user1"),
637         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
638     EXPECT_THROW(
639         UserMgr::executeUserModify("user0", "ssh", true),
640         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
641 }
642 
643 TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
644 {
645     std::string username = "user001";
646     EXPECT_NO_THROW(
647         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
648     EXPECT_NO_THROW(
649         updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
650     UserInfoMap userInfo = getUserInfo(username);
651     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
652     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
653                 testing::UnorderedElementsAre("ipmi", "ssh"));
654     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
655     EXPECT_NO_THROW(UserMgr::deleteUser(username));
656 }
657 
658 TEST_F(UserMgrInTest,
659        UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
660 {
661     std::string username = "user001";
662     EXPECT_NO_THROW(
663         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
664     EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
665                                          testing::_))
666         .WillOnce(testing::Throw(
667             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
668     EXPECT_THROW(
669         updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
670         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
671     EXPECT_NO_THROW(UserMgr::deleteUser(username));
672 }
673 
674 TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
675 {
676     initializeAccountPolicy();
677     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
678     UserMgr::minPasswordLength(8);
679     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
680 }
681 
682 TEST_F(UserMgrInTest,
683        MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
684 {
685     initializeAccountPolicy();
686     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
687     EXPECT_THROW(
688         UserMgr::minPasswordLength(minPasswdLength - 1),
689         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
690     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
691 }
692 
693 TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
694 {
695     initializeAccountPolicy();
696     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
697     UserMgr::minPasswordLength(16);
698     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
699 }
700 
701 TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
702 {
703     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
704     initializeAccountPolicy();
705     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
706     EXPECT_THROW(
707         UserMgr::minPasswordLength(16),
708         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
709     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
710 }
711 
712 TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
713 {
714     initializeAccountPolicy();
715     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
716     UserMgr::rememberOldPasswordTimes(8);
717     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
718     UserMgr::rememberOldPasswordTimes(8);
719     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
720 }
721 
722 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
723 {
724     initializeAccountPolicy();
725     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
726     UserMgr::rememberOldPasswordTimes(16);
727     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
728 }
729 
730 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
731 {
732     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
733     initializeAccountPolicy();
734     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
735     EXPECT_THROW(
736         UserMgr::rememberOldPasswordTimes(16),
737         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
738     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
739 }
740 
741 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
742 {
743     initializeAccountPolicy();
744     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
745     UserMgr::maxLoginAttemptBeforeLockout(2);
746     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
747 }
748 
749 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
750 {
751     initializeAccountPolicy();
752     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
753     UserMgr::maxLoginAttemptBeforeLockout(16);
754     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
755 }
756 
757 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
758 {
759     initializeAccountPolicy();
760     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
761     EXPECT_THROW(
762         UserMgr::maxLoginAttemptBeforeLockout(16),
763         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
764     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
765 }
766 
767 TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
768 {
769     initializeAccountPolicy();
770     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
771     UserMgr::accountUnlockTimeout(3);
772     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
773 }
774 
775 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
776 {
777     initializeAccountPolicy();
778     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
779     UserMgr::accountUnlockTimeout(16);
780     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
781 }
782 
783 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
784 {
785     initializeAccountPolicy();
786     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
787     EXPECT_THROW(
788         UserMgr::accountUnlockTimeout(16),
789         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
790     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
791 }
792 
793 TEST_F(UserMgrInTest, UserEnableOnSuccess)
794 {
795     std::string username = "user001";
796     EXPECT_NO_THROW(
797         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
798     UserInfoMap userInfo = getUserInfo(username);
799     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
800 
801     EXPECT_NO_THROW(userEnable(username, false));
802 
803     userInfo = getUserInfo(username);
804     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
805 
806     EXPECT_NO_THROW(UserMgr::deleteUser(username));
807 }
808 
809 TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
810 {
811     std::string username = "user001";
812     EXPECT_NO_THROW(
813         UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
814     EXPECT_NO_THROW(UserMgr::deleteUser(username));
815     EXPECT_NO_THROW(
816         UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
817     EXPECT_NO_THROW(UserMgr::deleteUser(username));
818     EXPECT_NO_THROW(
819         UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
820     EXPECT_NO_THROW(UserMgr::deleteUser(username));
821 }
822 
823 TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
824 {
825     std::string username = "user001";
826     EXPECT_NO_THROW(
827         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
828     UserInfoMap userInfo = getUserInfo(username);
829     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
830 
831     EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
832                                                    testing::Eq(false)))
833         .WillOnce(testing::Throw(
834             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
835     EXPECT_THROW(
836         userEnable(username, false),
837         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
838 
839     userInfo = getUserInfo(username);
840     // Stay unchanged
841     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
842 
843     EXPECT_NO_THROW(UserMgr::deleteUser(username));
844 }
845 
846 TEST_F(
847     UserMgrInTest,
848     UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
849 {
850     EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
851 }
852 
853 TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
854 {
855     std::string username = "user001";
856     initializeAccountPolicy();
857     // Example output from BMC
858     // root:~# faillock --user root
859     // root:
860     // When   Type   Source   Valid
861     std::vector<std::string> output = {"whatever",
862                                        "When   Type   Source   Valid"};
863     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
864         .WillOnce(testing::Return(output));
865 
866     EXPECT_FALSE(userLockedForFailedAttempt(username));
867 }
868 
869 TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
870 {
871     std::string username = "user001";
872     initializeAccountPolicy();
873     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
874         .WillOnce(testing::Throw(
875             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
876 
877     EXPECT_THROW(
878         userLockedForFailedAttempt(username),
879         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
880 }
881 
882 TEST_F(UserMgrInTest,
883        UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
884 {
885     std::string username = "user001";
886     initializeAccountPolicy();
887 
888     // Choose a date in the past.
889     std::vector<std::string> output = {"whatever",
890                                        "10/24/2002 00:00:00 type source V"};
891     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
892         .WillOnce(testing::Return(output));
893 
894     EXPECT_THROW(
895         userLockedForFailedAttempt(username),
896         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
897 }
898 
899 TEST_F(UserMgrInTest,
900        UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
901 {
902     std::string username = "user001";
903     initializeAccountPolicy();
904 
905     // Choose a date in the past.
906     std::vector<std::string> output = {"whatever",
907                                        "2002-10-24 00:00:00 type source V"};
908     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
909         .WillOnce(testing::Return(output));
910 
911     EXPECT_EQ(userLockedForFailedAttempt(username), false);
912 }
913 
914 TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
915 {
916     // Base Redfish Roles
917     EXPECT_NO_THROW(
918         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
919     EXPECT_NO_THROW(
920         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
921     EXPECT_NO_THROW(
922         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
923     // Base Redfish Privileges
924     EXPECT_NO_THROW(
925         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
926     EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
927         "openbmc_rfp_ConfigureManager"));
928     EXPECT_NO_THROW(
929         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
930     EXPECT_NO_THROW(
931         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
932     EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
933         "openbmc_rfp_ConfigureComponents"));
934     // OEM Redfish Roles
935     EXPECT_NO_THROW(
936         checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
937     // OEM Redfish Privileges
938     EXPECT_NO_THROW(
939         checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
940 }
941 
942 TEST_F(UserMgrInTest,
943        CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
944 {
945     std::string groupName(maxSystemGroupNameLength + 1, 'A');
946     EXPECT_THROW(
947         checkAndThrowForDisallowedGroupCreation(groupName),
948         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
949 }
950 
951 TEST_F(
952     UserMgrInTest,
953     CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
954 {
955     EXPECT_THROW(
956         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
957         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
958     EXPECT_THROW(
959         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
960         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
961 }
962 
963 TEST_F(
964     UserMgrInTest,
965     CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
966 {
967     EXPECT_THROW(
968         checkAndThrowForDisallowedGroupCreation("google_rfp_"),
969         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
970     EXPECT_THROW(
971         checkAndThrowForDisallowedGroupCreation("com_rfp_"),
972         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
973 }
974 
975 TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
976 {
977     constexpr size_t predefGroupCount = 5;
978 
979     EXPECT_THAT(allGroups().size(), predefGroupCount);
980     for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
981     {
982         std::string groupName = "openbmc_rfr_role";
983         groupName += std::to_string(i);
984         EXPECT_NO_THROW(createGroup(groupName));
985     }
986     EXPECT_THROW(
987         createGroup("openbmc_rfr_AnotherRole"),
988         sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
989     for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
990     {
991         std::string groupName = "openbmc_rfr_role";
992         groupName += std::to_string(i);
993         EXPECT_NO_THROW(deleteGroup(groupName));
994     }
995 }
996 
997 TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
998 {
999     std::string groupName = "openbmc_rfr_role";
1000     EXPECT_NO_THROW(createGroup(groupName));
1001     EXPECT_THROW(
1002         createGroup(groupName),
1003         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1004     EXPECT_NO_THROW(deleteGroup(groupName));
1005 }
1006 
1007 TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1008 {
1009     EXPECT_THAT(allGroups(),
1010                 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1011                                               "hostconsole"));
1012 }
1013 
1014 TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1015 {
1016     EXPECT_THROW(
1017         createGroup("ipmi"),
1018         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1019     EXPECT_THROW(
1020         createGroup("web"),
1021         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1022     EXPECT_THROW(
1023         createGroup("redfish"),
1024         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1025     EXPECT_THROW(
1026         createGroup("ssh"),
1027         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1028     EXPECT_THROW(
1029         createGroup("hostconsole"),
1030         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1031 }
1032 
1033 TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1034 {
1035     EXPECT_THROW(
1036         deleteGroup("ipmi"),
1037         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1038     EXPECT_THROW(
1039         deleteGroup("web"),
1040         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1041     EXPECT_THROW(
1042         deleteGroup("redfish"),
1043         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1044     EXPECT_THROW(
1045         deleteGroup("ssh"),
1046         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1047     EXPECT_THROW(
1048         deleteGroup("hostconsole"),
1049         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1050 }
1051 
1052 TEST_F(UserMgrInTest,
1053        CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1054 {
1055     EXPECT_CALL(*this, executeGroupCreation)
1056         .WillOnce(testing::Throw(
1057             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1058     EXPECT_THROW(
1059         createGroup("openbmc_rfr_role1"),
1060         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1061 }
1062 
1063 TEST_F(UserMgrInTest,
1064        DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1065 {
1066     std::string groupName = "openbmc_rfr_role1";
1067     EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1068     EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1069         .WillOnce(testing::Throw(
1070             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1071         .WillOnce(testing::DoDefault());
1072 
1073     EXPECT_THROW(
1074         deleteGroup(groupName),
1075         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1076     EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1077 }
1078 
1079 TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1080 {
1081     EXPECT_THROW(deleteGroup("whatever"),
1082                  sdbusplus::xyz::openbmc_project::User::Common::Error::
1083                      GroupNameDoesNotExist);
1084 }
1085 
1086 TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1087 {
1088     EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
1089                 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1090                                               "hostconsole"));
1091 }
1092 
1093 } // namespace user
1094 } // namespace phosphor
1095