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* rawFailLockConfig = R"(
207 deny=2
208 unlock_time=3
209 )";
210 inline constexpr const char* rawPWHistoryConfig = R"(
211 enforce_for_root
212 remember=0
213 )";
214 inline constexpr const char* rawPWQualityConfig = R"(
215 enforce_for_root
216 minlen=8
217 difok=0
218 lcredit=0
219 ocredit=0
220 dcredit=0
221 ucredit=0
222 )";
223 } // namespace
224 
225 void dumpStringToFile(const std::string& str, const std::string& filePath)
226 {
227     std::ofstream outputFileStream;
228 
229     outputFileStream.exceptions(std::ofstream::failbit | std::ofstream::badbit |
230                                 std::ofstream::eofbit);
231 
232     outputFileStream.open(filePath, std::ios::out);
233     outputFileStream << str << "\n" << std::flush;
234     outputFileStream.close();
235 }
236 
237 void removeFile(const std::string& filePath)
238 {
239     std::filesystem::remove(filePath);
240 }
241 
242 class UserMgrInTest : public testing::Test, public UserMgr
243 {
244   public:
245     UserMgrInTest() : UserMgr(busInTest, objectRootInTest)
246     {
247         tempFaillockConfigFile = "/tmp/test-data-XXXXXX";
248         mktemp(tempFaillockConfigFile.data());
249         EXPECT_NO_THROW(
250             dumpStringToFile(rawFailLockConfig, tempFaillockConfigFile));
251         tempPWHistoryConfigFile = "/tmp/test-data-XXXXXX";
252         mktemp(tempPWHistoryConfigFile.data());
253         EXPECT_NO_THROW(
254             dumpStringToFile(rawPWHistoryConfig, tempPWHistoryConfigFile));
255         tempPWQualityConfigFile = "/tmp/test-data-XXXXXX";
256         mktemp(tempPWQualityConfigFile.data());
257         EXPECT_NO_THROW(
258             dumpStringToFile(rawPWQualityConfig, tempPWQualityConfigFile));
259         // Set config files to test files
260         faillockConfigFile = tempFaillockConfigFile;
261         pwHistoryConfigFile = tempPWHistoryConfigFile;
262         pwQualityConfigFile = tempPWQualityConfigFile;
263 
264         ON_CALL(*this, executeUserAdd).WillByDefault(testing::Return());
265 
266         ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
267 
268         ON_CALL(*this, executeUserClearFailRecords)
269             .WillByDefault(testing::Return());
270 
271         ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
272 
273         ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
274 
275         ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
276             .WillByDefault(testing::Return());
277 
278         ON_CALL(*this, executeUserModifyUserEnable)
279             .WillByDefault(testing::Return());
280 
281         ON_CALL(*this, executeGroupCreation(testing::_))
282             .WillByDefault(testing::Return());
283 
284         ON_CALL(*this, executeGroupDeletion(testing::_))
285             .WillByDefault(testing::Return());
286 
287         ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
288 
289         ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
290     }
291 
292     ~UserMgrInTest() override
293     {
294         EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
295         EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
296         EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
297     }
298 
299     MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
300                 (override));
301 
302     MOCK_METHOD(void, executeUserDelete, (const char*), (override));
303 
304     MOCK_METHOD(void, executeUserClearFailRecords, (const char*), (override));
305 
306     MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
307 
308     MOCK_METHOD(void, executeUserRename, (const char*, const char*),
309                 (override));
310 
311     MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
312                 (override));
313 
314     MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
315                 (override));
316 
317     MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
318                 (override));
319 
320     MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
321 
322     MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
323 
324   protected:
325     static sdbusplus::bus_t busInTest;
326     std::string tempFaillockConfigFile;
327     std::string tempPWHistoryConfigFile;
328     std::string tempPWQualityConfigFile;
329 };
330 
331 sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
332 
333 TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
334 {
335     std::string minlen;
336     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
337               0);
338     EXPECT_EQ(minlen, "8");
339     std::string deny;
340     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
341     EXPECT_EQ(deny, "2");
342     std::string remember;
343     EXPECT_EQ(
344         getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
345         0);
346     EXPECT_EQ(remember, "0");
347 }
348 
349 TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
350 {
351     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
352               0);
353     std::string minlen;
354     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
355               0);
356     EXPECT_EQ(minlen, "16");
357 
358     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
359     std::string deny;
360     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
361     EXPECT_EQ(deny, "3");
362 
363     EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
364               0);
365     std::string remember;
366     EXPECT_EQ(
367         getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
368         0);
369     EXPECT_EQ(remember, "1");
370 }
371 
372 TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnSuccess)
373 {
374     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
375               0);
376 
377     std::string tmpFile = tempPWQualityConfigFile + "_tmp";
378     EXPECT_FALSE(std::filesystem::exists(tmpFile));
379 
380     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
381 
382     tmpFile = tempFaillockConfigFile + "_tmp";
383     EXPECT_FALSE(std::filesystem::exists(tmpFile));
384 
385     EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
386               0);
387 
388     tmpFile = tempPWHistoryConfigFile + "_tmp";
389     EXPECT_FALSE(std::filesystem::exists(tmpFile));
390 }
391 
392 TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
393 {
394     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
395     std::string minlen;
396     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
397               -1);
398 
399     EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
400     EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
401               -1);
402 
403     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
404     std::string deny;
405     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
406 
407     EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
408     EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
409 
410     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
411     std::string remember;
412     EXPECT_EQ(
413         getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
414         -1);
415 
416     EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
417     EXPECT_EQ(
418         getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
419         -1);
420 }
421 
422 TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
423 {
424     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
425     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
426               -1);
427 
428     EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
429     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
430               -1);
431 
432     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
433     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
434 
435     EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
436     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
437 
438     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
439     EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
440               -1);
441 
442     EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
443     EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
444               -1);
445 }
446 
447 TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnFailure)
448 {
449     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
450     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
451               -1);
452 
453     std::string tmpFile = tempPWQualityConfigFile + "_tmp";
454     EXPECT_FALSE(std::filesystem::exists(tmpFile));
455 
456     EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
457     EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
458               -1);
459 
460     EXPECT_FALSE(std::filesystem::exists(tmpFile));
461 
462     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
463     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
464 
465     tmpFile = tempFaillockConfigFile + "_tmp";
466     EXPECT_FALSE(std::filesystem::exists(tmpFile));
467 
468     EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
469     EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
470 
471     EXPECT_FALSE(std::filesystem::exists(tmpFile));
472 
473     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
474     EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
475               -1);
476 
477     tmpFile = tempPWHistoryConfigFile + "_tmp";
478     EXPECT_FALSE(std::filesystem::exists(tmpFile));
479 
480     EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
481     EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
482               -1);
483 
484     EXPECT_FALSE(std::filesystem::exists(tmpFile));
485 }
486 
487 TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
488 {
489     EXPECT_THROW(
490         isUserExist(""),
491         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
492 }
493 
494 TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
495 {
496     EXPECT_THROW(throwForUserDoesNotExist("whatever"),
497                  sdbusplus::xyz::openbmc_project::User::Common::Error::
498                      UserNameDoesNotExist);
499 }
500 
501 TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
502 {
503     EXPECT_THROW(
504         throwForUserExists("root"),
505         sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
506 }
507 
508 TEST_F(
509     UserMgrInTest,
510     ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
511 {
512     std::string strWith17Chars(17, 'A');
513     EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
514                  sdbusplus::xyz::openbmc_project::User::Common::Error::
515                      UserNameGroupFail);
516 }
517 
518 TEST_F(
519     UserMgrInTest,
520     ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
521 {
522     std::string strWith31Chars(31, 'A');
523     EXPECT_THROW(
524         throwForUserNameConstraints(strWith31Chars, {}),
525         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
526 }
527 
528 TEST_F(UserMgrInTest,
529        ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
530 {
531     std::string startWithNumber = "0ABC";
532     EXPECT_THROW(
533         throwForUserNameConstraints(startWithNumber, {"ipmi"}),
534         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
535 }
536 
537 TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
538 {
539     EXPECT_THROW(
540         UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
541         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
542 }
543 
544 TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
545 {
546     EXPECT_THROW(
547         UserMgr::executeUserDelete("user0"),
548         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
549 }
550 
551 TEST_F(UserMgrInTest,
552        ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
553 {
554     EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
555     EXPECT_THROW(
556         throwForMaxGrpUserCount({"ipmi"}),
557         sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
558 }
559 
560 TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
561 {
562     EXPECT_CALL(*this, executeUserAdd)
563         .WillOnce(testing::Throw(
564             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
565     EXPECT_THROW(
566         createUser("whatever", {"redfish"}, "", true),
567         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
568 }
569 
570 TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
571 {
572     std::string username = "user";
573     EXPECT_NO_THROW(
574         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
575     EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
576         .WillOnce(testing::Throw(
577             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
578         .WillOnce(testing::DoDefault());
579 
580     EXPECT_THROW(
581         deleteUser(username),
582         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
583     EXPECT_NO_THROW(UserMgr::deleteUser(username));
584 }
585 
586 TEST_F(UserMgrInTest,
587        DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
588 {
589     const char* username = "user";
590     EXPECT_NO_THROW(
591         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
592     EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
593         .WillOnce(testing::Throw(
594             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
595         .WillOnce(testing::DoDefault());
596 
597     EXPECT_THROW(
598         deleteUser(username),
599         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
600     EXPECT_NO_THROW(UserMgr::deleteUser(username));
601 }
602 
603 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
604 {
605     EXPECT_THROW(
606         throwForInvalidPrivilege("whatever"),
607         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
608 }
609 
610 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
611 {
612     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
613     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
614     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
615 }
616 
617 TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
618 {
619     EXPECT_THROW(
620         throwForInvalidGroups({"whatever"}),
621         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
622 }
623 
624 TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
625 {
626     EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
627     EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
628     EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
629     EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
630     EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
631 }
632 
633 TEST_F(UserMgrInTest, RenameUserOnSuccess)
634 {
635     std::string username = "user001";
636     EXPECT_NO_THROW(
637         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
638     std::string newUsername = "user002";
639 
640     EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
641 
642     // old username doesn't exist
643     EXPECT_THROW(getUserInfo(username),
644                  sdbusplus::xyz::openbmc_project::User::Common::Error::
645                      UserNameDoesNotExist);
646 
647     UserInfoMap userInfo = getUserInfo(newUsername);
648     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
649     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
650                 testing::UnorderedElementsAre("redfish", "ssh"));
651     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
652 
653     EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
654 }
655 
656 TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
657 {
658     std::string username = "user001";
659     EXPECT_NO_THROW(
660         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
661     std::string newUsername = "user002";
662 
663     EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
664                                          testing::StrEq(newUsername)))
665         .WillOnce(testing::Throw(
666             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
667     EXPECT_THROW(
668         UserMgr::renameUser(username, newUsername),
669         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
670 
671     // The original user is unchanged
672     UserInfoMap userInfo = getUserInfo(username);
673     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
674     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
675                 testing::UnorderedElementsAre("redfish", "ssh"));
676     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
677 
678     EXPECT_NO_THROW(UserMgr::deleteUser(username));
679 }
680 
681 TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
682 {
683     EXPECT_THROW(
684         UserMgr::executeUserRename("user0", "user1"),
685         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
686     EXPECT_THROW(
687         UserMgr::executeUserModify("user0", "ssh", true),
688         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
689 }
690 
691 TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
692 {
693     std::string username = "user001";
694     EXPECT_NO_THROW(
695         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
696     EXPECT_NO_THROW(
697         updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
698     UserInfoMap userInfo = getUserInfo(username);
699     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
700     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
701                 testing::UnorderedElementsAre("ipmi", "ssh"));
702     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
703     EXPECT_NO_THROW(UserMgr::deleteUser(username));
704 }
705 
706 TEST_F(UserMgrInTest,
707        UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
708 {
709     std::string username = "user001";
710     EXPECT_NO_THROW(
711         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
712     EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
713                                          testing::_))
714         .WillOnce(testing::Throw(
715             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
716     EXPECT_THROW(
717         updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
718         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
719     EXPECT_NO_THROW(UserMgr::deleteUser(username));
720 }
721 
722 TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
723 {
724     initializeAccountPolicy();
725     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
726     UserMgr::minPasswordLength(8);
727     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
728 }
729 
730 TEST_F(UserMgrInTest,
731        MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
732 {
733     initializeAccountPolicy();
734     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
735     EXPECT_THROW(
736         UserMgr::minPasswordLength(minPasswdLength - 1),
737         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
738     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
739 }
740 
741 TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
742 {
743     initializeAccountPolicy();
744     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
745     UserMgr::minPasswordLength(16);
746     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
747 }
748 
749 TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
750 {
751     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
752     initializeAccountPolicy();
753     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
754     EXPECT_THROW(
755         UserMgr::minPasswordLength(16),
756         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
757     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
758 }
759 
760 TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
761 {
762     initializeAccountPolicy();
763     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
764     UserMgr::rememberOldPasswordTimes(8);
765     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
766     UserMgr::rememberOldPasswordTimes(8);
767     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
768 }
769 
770 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
771 {
772     initializeAccountPolicy();
773     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
774     UserMgr::rememberOldPasswordTimes(16);
775     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
776 }
777 
778 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
779 {
780     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
781     initializeAccountPolicy();
782     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
783     EXPECT_THROW(
784         UserMgr::rememberOldPasswordTimes(16),
785         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
786     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
787 }
788 
789 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
790 {
791     initializeAccountPolicy();
792     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
793     UserMgr::maxLoginAttemptBeforeLockout(2);
794     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
795 }
796 
797 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
798 {
799     initializeAccountPolicy();
800     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
801     UserMgr::maxLoginAttemptBeforeLockout(16);
802     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
803 }
804 
805 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
806 {
807     initializeAccountPolicy();
808     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
809     EXPECT_THROW(
810         UserMgr::maxLoginAttemptBeforeLockout(16),
811         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
812     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
813 }
814 
815 TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
816 {
817     initializeAccountPolicy();
818     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
819     UserMgr::accountUnlockTimeout(3);
820     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
821 }
822 
823 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
824 {
825     initializeAccountPolicy();
826     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
827     UserMgr::accountUnlockTimeout(16);
828     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
829 }
830 
831 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
832 {
833     initializeAccountPolicy();
834     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
835     EXPECT_THROW(
836         UserMgr::accountUnlockTimeout(16),
837         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
838     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
839 }
840 
841 TEST_F(UserMgrInTest, UserEnableOnSuccess)
842 {
843     std::string username = "user001";
844     EXPECT_NO_THROW(
845         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
846     UserInfoMap userInfo = getUserInfo(username);
847     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
848 
849     EXPECT_NO_THROW(userEnable(username, false));
850 
851     userInfo = getUserInfo(username);
852     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
853 
854     EXPECT_NO_THROW(UserMgr::deleteUser(username));
855 }
856 
857 TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
858 {
859     std::string username = "user001";
860     EXPECT_NO_THROW(
861         UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
862     EXPECT_NO_THROW(UserMgr::deleteUser(username));
863     EXPECT_NO_THROW(
864         UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
865     EXPECT_NO_THROW(UserMgr::deleteUser(username));
866     EXPECT_NO_THROW(
867         UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
868     EXPECT_NO_THROW(UserMgr::deleteUser(username));
869 }
870 
871 TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
872 {
873     std::string username = "user001";
874     EXPECT_NO_THROW(
875         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
876     UserInfoMap userInfo = getUserInfo(username);
877     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
878 
879     EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
880                                                    testing::Eq(false)))
881         .WillOnce(testing::Throw(
882             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
883     EXPECT_THROW(
884         userEnable(username, false),
885         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
886 
887     userInfo = getUserInfo(username);
888     // Stay unchanged
889     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
890 
891     EXPECT_NO_THROW(UserMgr::deleteUser(username));
892 }
893 
894 TEST_F(
895     UserMgrInTest,
896     UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
897 {
898     EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
899 }
900 
901 TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
902 {
903     std::string username = "user001";
904     initializeAccountPolicy();
905     // Example output from BMC
906     // root:~# faillock --user root
907     // root:
908     // When   Type   Source   Valid
909     std::vector<std::string> output = {"whatever",
910                                        "When   Type   Source   Valid"};
911     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
912         .WillOnce(testing::Return(output));
913 
914     EXPECT_FALSE(userLockedForFailedAttempt(username));
915 }
916 
917 TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
918 {
919     std::string username = "user001";
920     initializeAccountPolicy();
921     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
922         .WillOnce(testing::Throw(
923             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
924 
925     EXPECT_THROW(
926         userLockedForFailedAttempt(username),
927         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
928 }
929 
930 TEST_F(UserMgrInTest,
931        UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
932 {
933     std::string username = "user001";
934     initializeAccountPolicy();
935 
936     // Choose a date in the past.
937     std::vector<std::string> output = {"whatever",
938                                        "10/24/2002 00:00:00 type source V"};
939     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
940         .WillOnce(testing::Return(output));
941 
942     EXPECT_THROW(
943         userLockedForFailedAttempt(username),
944         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
945 }
946 
947 TEST_F(UserMgrInTest,
948        UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
949 {
950     std::string username = "user001";
951     initializeAccountPolicy();
952 
953     // Choose a date in the past.
954     std::vector<std::string> output = {"whatever",
955                                        "2002-10-24 00:00:00 type source V"};
956     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
957         .WillOnce(testing::Return(output));
958 
959     EXPECT_EQ(userLockedForFailedAttempt(username), false);
960 }
961 
962 TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
963 {
964     // Base Redfish Roles
965     EXPECT_NO_THROW(
966         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
967     EXPECT_NO_THROW(
968         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
969     EXPECT_NO_THROW(
970         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
971     // Base Redfish Privileges
972     EXPECT_NO_THROW(
973         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
974     EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
975         "openbmc_rfp_ConfigureManager"));
976     EXPECT_NO_THROW(
977         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
978     EXPECT_NO_THROW(
979         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
980     EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
981         "openbmc_rfp_ConfigureComponents"));
982     // OEM Redfish Roles
983     EXPECT_NO_THROW(
984         checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
985     // OEM Redfish Privileges
986     EXPECT_NO_THROW(
987         checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
988 }
989 
990 TEST_F(UserMgrInTest,
991        CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
992 {
993     std::string groupName(maxSystemGroupNameLength + 1, 'A');
994     EXPECT_THROW(
995         checkAndThrowForDisallowedGroupCreation(groupName),
996         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
997 }
998 
999 TEST_F(
1000     UserMgrInTest,
1001     CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
1002 {
1003     EXPECT_THROW(
1004         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
1005         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1006     EXPECT_THROW(
1007         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
1008         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1009 }
1010 
1011 TEST_F(
1012     UserMgrInTest,
1013     CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
1014 {
1015     EXPECT_THROW(
1016         checkAndThrowForDisallowedGroupCreation("google_rfp_"),
1017         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1018     EXPECT_THROW(
1019         checkAndThrowForDisallowedGroupCreation("com_rfp_"),
1020         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1021 }
1022 
1023 TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
1024 {
1025     constexpr size_t predefGroupCount = 5;
1026 
1027     EXPECT_THAT(allGroups().size(), predefGroupCount);
1028     for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1029     {
1030         std::string groupName = "openbmc_rfr_role";
1031         groupName += std::to_string(i);
1032         EXPECT_NO_THROW(createGroup(groupName));
1033     }
1034     EXPECT_THROW(
1035         createGroup("openbmc_rfr_AnotherRole"),
1036         sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
1037     for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1038     {
1039         std::string groupName = "openbmc_rfr_role";
1040         groupName += std::to_string(i);
1041         EXPECT_NO_THROW(deleteGroup(groupName));
1042     }
1043 }
1044 
1045 TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1046 {
1047     std::string groupName = "openbmc_rfr_role";
1048     EXPECT_NO_THROW(createGroup(groupName));
1049     EXPECT_THROW(
1050         createGroup(groupName),
1051         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1052     EXPECT_NO_THROW(deleteGroup(groupName));
1053 }
1054 
1055 TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1056 {
1057     EXPECT_THAT(allGroups(),
1058                 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1059                                               "hostconsole"));
1060 }
1061 
1062 TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1063 {
1064     EXPECT_THROW(
1065         createGroup("ipmi"),
1066         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1067     EXPECT_THROW(
1068         createGroup("web"),
1069         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1070     EXPECT_THROW(
1071         createGroup("redfish"),
1072         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1073     EXPECT_THROW(
1074         createGroup("ssh"),
1075         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1076     EXPECT_THROW(
1077         createGroup("hostconsole"),
1078         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1079 }
1080 
1081 TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1082 {
1083     EXPECT_THROW(
1084         deleteGroup("ipmi"),
1085         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1086     EXPECT_THROW(
1087         deleteGroup("web"),
1088         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1089     EXPECT_THROW(
1090         deleteGroup("redfish"),
1091         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1092     EXPECT_THROW(
1093         deleteGroup("ssh"),
1094         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1095     EXPECT_THROW(
1096         deleteGroup("hostconsole"),
1097         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1098 }
1099 
1100 TEST_F(UserMgrInTest,
1101        CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1102 {
1103     EXPECT_CALL(*this, executeGroupCreation)
1104         .WillOnce(testing::Throw(
1105             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1106     EXPECT_THROW(
1107         createGroup("openbmc_rfr_role1"),
1108         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1109 }
1110 
1111 TEST_F(UserMgrInTest,
1112        DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1113 {
1114     std::string groupName = "openbmc_rfr_role1";
1115     EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1116     EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1117         .WillOnce(testing::Throw(
1118             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1119         .WillOnce(testing::DoDefault());
1120 
1121     EXPECT_THROW(
1122         deleteGroup(groupName),
1123         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1124     EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1125 }
1126 
1127 TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1128 {
1129     EXPECT_THROW(deleteGroup("whatever"),
1130                  sdbusplus::xyz::openbmc_project::User::Common::Error::
1131                      GroupNameDoesNotExist);
1132 }
1133 
1134 TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1135 {
1136     EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
1137                 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1138                                               "hostconsole"));
1139 }
1140 
1141 } // namespace user
1142 } // namespace phosphor
1143