xref: /openbmc/phosphor-user-manager/test/user_mgr_test.cpp (revision c992c26e1f9c716976a31fa9f571579e2a3e765a)
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     std::string startWithDisallowedCharacter = "[test";
568     EXPECT_THROW(
569         throwForUserNameConstraints(startWithNumber, {"ipmi"}),
570         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
571     EXPECT_THROW(
572         throwForUserNameConstraints(startWithDisallowedCharacter, {"ipmi"}),
573         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
574 }
575 
576 TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
577 {
578     EXPECT_THROW(
579         UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
580         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
581 }
582 
583 TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
584 {
585     EXPECT_THROW(
586         UserMgr::executeUserDelete("user0"),
587         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
588 }
589 
590 TEST_F(UserMgrInTest,
591        ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
592 {
593     EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
594     EXPECT_THROW(
595         throwForMaxGrpUserCount({"ipmi"}),
596         sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
597 }
598 
599 TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
600 {
601     EXPECT_CALL(*this, executeUserAdd)
602         .WillOnce(testing::Throw(
603             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
604     EXPECT_THROW(
605         createUser("whatever", {"redfish"}, "", true),
606         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
607 }
608 
609 TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
610 {
611     std::string username = "user";
612     EXPECT_NO_THROW(
613         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
614     EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
615         .WillOnce(testing::Throw(
616             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
617         .WillOnce(testing::DoDefault());
618 
619     EXPECT_THROW(
620         deleteUser(username),
621         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
622     EXPECT_NO_THROW(UserMgr::deleteUser(username));
623 }
624 
625 TEST_F(UserMgrInTest,
626        DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
627 {
628     const char* username = "user";
629     EXPECT_NO_THROW(
630         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
631     EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
632         .WillOnce(testing::Throw(
633             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
634         .WillOnce(testing::DoDefault());
635 
636     EXPECT_THROW(
637         deleteUser(username),
638         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
639     EXPECT_NO_THROW(UserMgr::deleteUser(username));
640 }
641 
642 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
643 {
644     EXPECT_THROW(
645         throwForInvalidPrivilege("whatever"),
646         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
647 }
648 
649 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
650 {
651     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
652     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
653     EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
654 }
655 
656 TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
657 {
658     EXPECT_THROW(
659         throwForInvalidGroups({"whatever"}),
660         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
661 }
662 
663 TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
664 {
665     EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
666     EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
667     EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
668     EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
669     EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
670 }
671 
672 TEST_F(UserMgrInTest, RenameUserOnSuccess)
673 {
674     std::string username = "user001";
675     EXPECT_NO_THROW(
676         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
677     std::string newUsername = "user002";
678 
679     EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
680 
681     // old username doesn't exist
682     EXPECT_THROW(getUserInfo(username),
683                  sdbusplus::xyz::openbmc_project::User::Common::Error::
684                      UserNameDoesNotExist);
685 
686     UserInfoMap userInfo = getUserInfo(newUsername);
687     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
688     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
689                 testing::UnorderedElementsAre("redfish", "ssh"));
690     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
691 
692     EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
693 }
694 
695 TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
696 {
697     std::string username = "user001";
698     EXPECT_NO_THROW(
699         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
700     std::string newUsername = "user002";
701 
702     EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
703                                          testing::StrEq(newUsername)))
704         .WillOnce(testing::Throw(
705             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
706     EXPECT_THROW(
707         UserMgr::renameUser(username, newUsername),
708         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
709 
710     // The original user is unchanged
711     UserInfoMap userInfo = getUserInfo(username);
712     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
713     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
714                 testing::UnorderedElementsAre("redfish", "ssh"));
715     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
716 
717     EXPECT_NO_THROW(UserMgr::deleteUser(username));
718 }
719 
720 TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
721 {
722     EXPECT_THROW(
723         UserMgr::executeUserRename("user0", "user1"),
724         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
725     EXPECT_THROW(
726         UserMgr::executeUserModify("user0", "ssh", true),
727         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
728 }
729 
730 TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
731 {
732     std::string username = "user001";
733     EXPECT_NO_THROW(
734         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
735     EXPECT_NO_THROW(
736         updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
737     UserInfoMap userInfo = getUserInfo(username);
738     EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
739     EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
740                 testing::UnorderedElementsAre("ipmi", "ssh"));
741     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
742     EXPECT_NO_THROW(UserMgr::deleteUser(username));
743 }
744 
745 TEST_F(UserMgrInTest,
746        UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
747 {
748     std::string username = "user001";
749     EXPECT_NO_THROW(
750         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
751     EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
752                                          testing::_))
753         .WillOnce(testing::Throw(
754             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
755     EXPECT_THROW(
756         updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
757         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
758     EXPECT_NO_THROW(UserMgr::deleteUser(username));
759 }
760 
761 TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
762 {
763     initializeAccountPolicy();
764     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
765     UserMgr::minPasswordLength(8);
766     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
767 }
768 
769 TEST_F(UserMgrInTest,
770        MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
771 {
772     initializeAccountPolicy();
773     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
774     EXPECT_THROW(
775         UserMgr::minPasswordLength(minPasswdLength - 1),
776         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
777     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
778 }
779 
780 TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
781 {
782     initializeAccountPolicy();
783     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
784     UserMgr::minPasswordLength(16);
785     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
786 }
787 
788 TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
789 {
790     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
791     initializeAccountPolicy();
792     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
793     EXPECT_THROW(
794         UserMgr::minPasswordLength(16),
795         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
796     EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
797 }
798 
799 TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
800 {
801     initializeAccountPolicy();
802     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
803     UserMgr::rememberOldPasswordTimes(8);
804     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
805     UserMgr::rememberOldPasswordTimes(8);
806     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
807 }
808 
809 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
810 {
811     initializeAccountPolicy();
812     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
813     UserMgr::rememberOldPasswordTimes(16);
814     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
815 }
816 
817 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
818 {
819     EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
820     initializeAccountPolicy();
821     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
822     EXPECT_THROW(
823         UserMgr::rememberOldPasswordTimes(16),
824         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
825     EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
826 }
827 
828 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
829 {
830     initializeAccountPolicy();
831     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
832     UserMgr::maxLoginAttemptBeforeLockout(2);
833     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
834 }
835 
836 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
837 {
838     initializeAccountPolicy();
839     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
840     UserMgr::maxLoginAttemptBeforeLockout(16);
841     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
842 }
843 
844 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
845 {
846     initializeAccountPolicy();
847     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
848     EXPECT_THROW(
849         UserMgr::maxLoginAttemptBeforeLockout(16),
850         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
851     EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
852 }
853 
854 TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
855 {
856     initializeAccountPolicy();
857     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
858     UserMgr::accountUnlockTimeout(3);
859     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
860 }
861 
862 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
863 {
864     initializeAccountPolicy();
865     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
866     UserMgr::accountUnlockTimeout(16);
867     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
868 }
869 
870 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
871 {
872     initializeAccountPolicy();
873     EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
874     EXPECT_THROW(
875         UserMgr::accountUnlockTimeout(16),
876         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
877     EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
878 }
879 
880 TEST_F(UserMgrInTest, UserEnableOnSuccess)
881 {
882     std::string username = "user001";
883     EXPECT_NO_THROW(
884         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
885     UserInfoMap userInfo = getUserInfo(username);
886     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
887 
888     EXPECT_NO_THROW(userEnable(username, false));
889 
890     userInfo = getUserInfo(username);
891     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
892 
893     EXPECT_NO_THROW(UserMgr::deleteUser(username));
894 }
895 
896 TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
897 {
898     std::string username = "user001";
899     EXPECT_NO_THROW(
900         UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
901     EXPECT_NO_THROW(UserMgr::deleteUser(username));
902     EXPECT_NO_THROW(
903         UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
904     EXPECT_NO_THROW(UserMgr::deleteUser(username));
905     EXPECT_NO_THROW(
906         UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
907     EXPECT_NO_THROW(UserMgr::deleteUser(username));
908 }
909 
910 TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
911 {
912     std::string username = "user001";
913     EXPECT_NO_THROW(
914         UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
915     UserInfoMap userInfo = getUserInfo(username);
916     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
917 
918     EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
919                                                    testing::Eq(false)))
920         .WillOnce(testing::Throw(
921             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
922     EXPECT_THROW(
923         userEnable(username, false),
924         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
925 
926     userInfo = getUserInfo(username);
927     // Stay unchanged
928     EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
929 
930     EXPECT_NO_THROW(UserMgr::deleteUser(username));
931 }
932 
933 TEST_F(
934     UserMgrInTest,
935     UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
936 {
937     EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
938 }
939 
940 TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
941 {
942     std::string username = "user001";
943     initializeAccountPolicy();
944     // Example output from BMC
945     // root:~# faillock --user root
946     // root:
947     // When   Type   Source   Valid
948     std::vector<std::string> output = {"whatever",
949                                        "When   Type   Source   Valid"};
950     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
951         .WillOnce(testing::Return(output));
952 
953     EXPECT_FALSE(userLockedForFailedAttempt(username));
954 }
955 
956 TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
957 {
958     std::string username = "user001";
959     initializeAccountPolicy();
960     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
961         .WillOnce(testing::Throw(
962             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
963 
964     EXPECT_THROW(
965         userLockedForFailedAttempt(username),
966         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
967 }
968 
969 TEST_F(UserMgrInTest,
970        UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
971 {
972     std::string username = "user001";
973     initializeAccountPolicy();
974 
975     // Choose a date in the past.
976     std::vector<std::string> output = {"whatever",
977                                        "10/24/2002 00:00:00 type source V"};
978     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
979         .WillOnce(testing::Return(output));
980 
981     EXPECT_THROW(
982         userLockedForFailedAttempt(username),
983         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
984 }
985 
986 TEST_F(UserMgrInTest,
987        UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
988 {
989     std::string username = "user001";
990     initializeAccountPolicy();
991 
992     // Choose a date in the past.
993     std::vector<std::string> output = {"whatever",
994                                        "2002-10-24 00:00:00 type source V"};
995     EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
996         .WillOnce(testing::Return(output));
997 
998     EXPECT_EQ(userLockedForFailedAttempt(username), false);
999 }
1000 
1001 TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
1002 {
1003     // Base Redfish Roles
1004     EXPECT_NO_THROW(
1005         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
1006     EXPECT_NO_THROW(
1007         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
1008     EXPECT_NO_THROW(
1009         checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
1010     // Base Redfish Privileges
1011     EXPECT_NO_THROW(
1012         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
1013     EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1014         "openbmc_rfp_ConfigureManager"));
1015     EXPECT_NO_THROW(
1016         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
1017     EXPECT_NO_THROW(
1018         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
1019     EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1020         "openbmc_rfp_ConfigureComponents"));
1021     // OEM Redfish Roles
1022     EXPECT_NO_THROW(
1023         checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
1024     // OEM Redfish Privileges
1025     EXPECT_NO_THROW(
1026         checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
1027 }
1028 
1029 TEST_F(UserMgrInTest,
1030        CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
1031 {
1032     std::string groupName(maxSystemGroupNameLength + 1, 'A');
1033     EXPECT_THROW(
1034         checkAndThrowForDisallowedGroupCreation(groupName),
1035         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1036 }
1037 
1038 TEST_F(
1039     UserMgrInTest,
1040     CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
1041 {
1042     EXPECT_THROW(
1043         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
1044         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1045     EXPECT_THROW(
1046         checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
1047         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1048 }
1049 
1050 TEST_F(
1051     UserMgrInTest,
1052     CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
1053 {
1054     EXPECT_THROW(
1055         checkAndThrowForDisallowedGroupCreation("google_rfp_"),
1056         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1057     EXPECT_THROW(
1058         checkAndThrowForDisallowedGroupCreation("com_rfp_"),
1059         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1060 }
1061 
1062 TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
1063 {
1064     constexpr size_t predefGroupCount = 5;
1065 
1066     EXPECT_THAT(allGroups().size(), predefGroupCount);
1067     for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1068     {
1069         std::string groupName = "openbmc_rfr_role";
1070         groupName += std::to_string(i);
1071         EXPECT_NO_THROW(createGroup(groupName));
1072     }
1073     EXPECT_THROW(
1074         createGroup("openbmc_rfr_AnotherRole"),
1075         sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
1076     for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1077     {
1078         std::string groupName = "openbmc_rfr_role";
1079         groupName += std::to_string(i);
1080         EXPECT_NO_THROW(deleteGroup(groupName));
1081     }
1082 }
1083 
1084 TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1085 {
1086     std::string groupName = "openbmc_rfr_role";
1087     EXPECT_NO_THROW(createGroup(groupName));
1088     EXPECT_THROW(
1089         createGroup(groupName),
1090         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1091     EXPECT_NO_THROW(deleteGroup(groupName));
1092 }
1093 
1094 TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1095 {
1096     EXPECT_THAT(allGroups(),
1097                 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1098                                               "hostconsole"));
1099 }
1100 
1101 TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1102 {
1103     EXPECT_THROW(
1104         createGroup("ipmi"),
1105         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1106     EXPECT_THROW(
1107         createGroup("web"),
1108         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1109     EXPECT_THROW(
1110         createGroup("redfish"),
1111         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1112     EXPECT_THROW(
1113         createGroup("ssh"),
1114         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1115     EXPECT_THROW(
1116         createGroup("hostconsole"),
1117         sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1118 }
1119 
1120 TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1121 {
1122     EXPECT_THROW(
1123         deleteGroup("ipmi"),
1124         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1125     EXPECT_THROW(
1126         deleteGroup("web"),
1127         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1128     EXPECT_THROW(
1129         deleteGroup("redfish"),
1130         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1131     EXPECT_THROW(
1132         deleteGroup("ssh"),
1133         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1134     EXPECT_THROW(
1135         deleteGroup("hostconsole"),
1136         sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1137 }
1138 
1139 TEST_F(UserMgrInTest,
1140        CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1141 {
1142     EXPECT_CALL(*this, executeGroupCreation)
1143         .WillOnce(testing::Throw(
1144             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1145     EXPECT_THROW(
1146         createGroup("openbmc_rfr_role1"),
1147         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1148 }
1149 
1150 TEST_F(UserMgrInTest,
1151        DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1152 {
1153     std::string groupName = "openbmc_rfr_role1";
1154     EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1155     EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1156         .WillOnce(testing::Throw(
1157             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1158         .WillOnce(testing::DoDefault());
1159 
1160     EXPECT_THROW(
1161         deleteGroup(groupName),
1162         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1163     EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1164 }
1165 
1166 TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1167 {
1168     EXPECT_THROW(deleteGroup("whatever"),
1169                  sdbusplus::xyz::openbmc_project::User::Common::Error::
1170                      GroupNameDoesNotExist);
1171 }
1172 
1173 TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1174 {
1175     EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
1176                 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1177                                               "hostconsole"));
1178 }
1179 
1180 } // namespace user
1181 } // namespace phosphor
1182