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