1 #include "helpers.hpp"
2 #include "utils/dbus_path_utils.hpp"
3 #include "utils/make_id_name.hpp"
4 #include "utils/string_utils.hpp"
5 
6 #include <sdbusplus/exception.hpp>
7 
8 #include <gmock/gmock.h>
9 
10 using namespace testing;
11 using namespace std::literals::string_literals;
12 using namespace utils::string_utils;
13 
14 class ScenarioBase : public Test
15 {
16   public:
17     std::string_view defaultName = "defName";
18     std::vector<std::string> conflicts;
19 };
20 
21 class ScenarioNameProvided : public ScenarioBase
22 {
23   public:
24     auto makeIdName(std::string_view id, std::string_view name) const
25     {
26         return utils::makeIdName(id, name, defaultName, conflicts);
27     }
28 };
29 
30 TEST_F(ScenarioNameProvided, throwsWhenProvidedNameIsTooLong)
31 {
32     EXPECT_THROW(this->makeIdName("", getTooLongName()),
33                  sdbusplus::exception::SdBusError);
34 }
35 
36 class TestMakeIdNameNameProvided : public ScenarioNameProvided
37 {};
38 
39 TEST_F(TestMakeIdNameNameProvided, usesIdWhenProvided)
40 {
41     const std::string name = "name";
42 
43     EXPECT_THAT(this->makeIdName("id0", name), Eq(std::pair{"id0"s, name}));
44     EXPECT_THAT(this->makeIdName("prefix/id2", name),
45                 Eq(std::pair{"prefix/id2"s, name}));
46 }
47 
48 TEST_F(TestMakeIdNameNameProvided, usedDefaultWhenNothingProvided)
49 {
50     this->defaultName = "def";
51 
52     EXPECT_THAT(this->makeIdName("", ""), Eq(std::pair{"def"s, "def"s}));
53     EXPECT_THAT(this->makeIdName("abc/", ""),
54                 Eq(std::pair{"abc/def"s, "def"s}));
55 }
56 
57 TEST_F(TestMakeIdNameNameProvided, usedDefaultWhenNameContainsNoIdChars)
58 {
59     this->defaultName = "def";
60     const std::string name = " !";
61 
62     EXPECT_THAT(this->makeIdName("", name), Eq(std::pair{"def"s, name}));
63     EXPECT_THAT(this->makeIdName("prefix/", name),
64                 Eq(std::pair{"prefix/def"s, name}));
65 }
66 
67 class ScenarioNameNotProvided : public ScenarioBase
68 {
69   public:
70     auto makeIdName(std::string_view id, std::string_view name) const
71     {
72         return utils::makeIdName(id, "", name, conflicts);
73     }
74 };
75 
76 class TestMakeIdNameNameNotProvided : public ScenarioNameNotProvided
77 {};
78 
79 TEST_F(TestMakeIdNameNameNotProvided, usesIdAsNameWhenProvided)
80 {
81     EXPECT_THAT(this->makeIdName("id0", defaultName),
82                 Eq(std::pair{"id0"s, "id0"s}));
83     EXPECT_THAT(this->makeIdName("prefix/id2", defaultName),
84                 Eq(std::pair{"prefix/id2"s, "id2"s}));
85 }
86 
87 template <class Scenario>
88 class TestMakeIdName : public Scenario
89 {};
90 
91 using TestScenarios =
92     ::testing::Types<ScenarioNameProvided, ScenarioNameNotProvided>;
93 TYPED_TEST_SUITE(TestMakeIdName, TestScenarios);
94 
95 TYPED_TEST(TestMakeIdName, throwsWhenProvidedIdContainsIncorrectCharacters)
96 {
97     EXPECT_THROW(this->makeIdName("Id%@%!@%!%()%fooo/Id", "name"),
98                  sdbusplus::exception::SdBusError);
99     EXPECT_THROW(this->makeIdName("Id/Id%@%!@%!%()%fooo", "name"),
100                  sdbusplus::exception::SdBusError);
101     EXPECT_THROW(this->makeIdName("/123", "trigger"),
102                  sdbusplus::exception::SdBusError);
103     EXPECT_THROW(this->makeIdName("/123/", "trigger"),
104                  sdbusplus::exception::SdBusError);
105 }
106 
107 TYPED_TEST(TestMakeIdName, throwsWhenProvidedIdContainsTooLongSegment)
108 {
109     std::string longPrefix = getTooLongPrefix();
110     std::string longSuffix = getTooLongId();
111     EXPECT_THROW(this->makeIdName(longPrefix + "/", "name"),
112                  sdbusplus::exception::SdBusError);
113     EXPECT_THROW(this->makeIdName(longPrefix + "/Id", "name"),
114                  sdbusplus::exception::SdBusError);
115     EXPECT_THROW(this->makeIdName(longPrefix + "/" + longSuffix, "name"),
116                  sdbusplus::exception::SdBusError);
117     EXPECT_THROW(this->makeIdName("Prefix/" + longSuffix, "name"),
118                  sdbusplus::exception::SdBusError);
119     EXPECT_THROW(this->makeIdName(longSuffix, "name"),
120                  sdbusplus::exception::SdBusError);
121 }
122 
123 TYPED_TEST(TestMakeIdName, throwsWhenProvidedIdOrPrefixTooLong)
124 {
125     EXPECT_THROW(this->makeIdName(getTooLongId(), "name"),
126                  sdbusplus::exception::SdBusError);
127     EXPECT_THROW(this->makeIdName(getTooLongPrefix() + "/Id", "name"),
128                  sdbusplus::exception::SdBusError);
129     EXPECT_THROW(this->makeIdName("Prefix/" + getTooLongId(), "trigger"),
130                  sdbusplus::exception::SdBusError);
131 }
132 
133 TYPED_TEST(TestMakeIdName, throwsWhenIdContainsMoreThanOneSlash)
134 {
135     EXPECT_THROW(this->makeIdName("/12/", "name"),
136                  sdbusplus::exception::SdBusError);
137     EXPECT_THROW(this->makeIdName("12//", "name"),
138                  sdbusplus::exception::SdBusError);
139     EXPECT_THROW(this->makeIdName("12//123", "name"),
140                  sdbusplus::exception::SdBusError);
141     EXPECT_THROW(this->makeIdName("12/12/123", "name"),
142                  sdbusplus::exception::SdBusError);
143 }
144 
145 TYPED_TEST(TestMakeIdName, usesNameWhenThereAreConflicts)
146 {
147     this->conflicts = {"trigger"};
148     EXPECT_THAT(this->makeIdName("", "trigger"),
149                 Eq(std::pair{"trigger0"s, "trigger"s}));
150 
151     this->conflicts = {"trigger", "trigger0"};
152     EXPECT_THAT(this->makeIdName("", "trigger"),
153                 Eq(std::pair{"trigger1"s, "trigger"s}));
154 
155     this->conflicts = {getMaxId()};
156     std::string expectedId = getMaxId();
157     expectedId[expectedId.length() - 1] = '0';
158     EXPECT_THAT(this->makeIdName("", getMaxId()),
159                 Eq(std::pair{expectedId, getMaxId()}));
160 }
161 
162 TYPED_TEST(TestMakeIdName, throwsWhenProvidedIdIsTaken)
163 {
164     this->conflicts = {"id", "prefix/id"};
165 
166     EXPECT_THROW(this->makeIdName("id", "name"),
167                  sdbusplus::exception::SdBusError);
168     EXPECT_THROW(this->makeIdName("prefix/id", "name"),
169                  sdbusplus::exception::SdBusError);
170 }
171 
172 TYPED_TEST(TestMakeIdName, usesNameWhenIdNotProvided)
173 {
174     EXPECT_THAT(this->makeIdName("", "name"), Eq(std::pair{"name"s, "name"s}));
175     EXPECT_THAT(this->makeIdName("abc/", "name"),
176                 Eq(std::pair{"abc/name"s, "name"s}));
177     EXPECT_THAT(this->makeIdName("123/", "name"),
178                 Eq(std::pair{"123/name"s, "name"s}));
179 }
180 
181 TYPED_TEST(TestMakeIdName, usesNameWithoutInvalidCharactersWhenIdNotProvided)
182 {
183     EXPECT_THAT(this->makeIdName("", "n#a$/m@e"),
184                 Eq(std::pair{"name"s, "n#a$/m@e"s}));
185     EXPECT_THAT(this->makeIdName("", "n!^aŹ/me"),
186                 Eq(std::pair{"name"s, "n!^aŹ/me"s}));
187     EXPECT_THAT(this->makeIdName("p/", "n!^aŹ/m*(e"),
188                 Eq(std::pair{"p/name"s, "n!^aŹ/m*(e"s}));
189 }
190