1 /*
2  * ConfigProfileTests.cpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 #include <tests/TestThat.hpp>
17 
18 #include <core/ConfigProfile.hpp>
19 
20 namespace rstudio {
21 namespace core {
22 namespace tests {
23 
24 TEST_CASE("config profile")
25 {
26    SECTION("can parse single level")
27    {
28       std::string profileStr = R"([*]
29           param=val
30           param2=val2)";
31 
32       ConfigProfile profile;
33       profile.addSections({{0, "*"}});
34       profile.addParams("param", std::string(),
35                         "param2", std::string());
36 
37       Error error = profile.parseString(profileStr);
38       REQUIRE_FALSE(error);
39 
40       std::string param;
41       error = profile.getParam("param", &param, {{0, std::string()}});
42       REQUIRE_FALSE(error);
43       REQUIRE(param == "val");
44 
45       std::string param2;
46       error = profile.getParam("param2", &param2,
47                                {{0, std::string()},
48                                {1, "higherLevel"}});
49       REQUIRE_FALSE(error);
50       REQUIRE(param2 == "val2");
51 
52       std::string param3;
53       error = profile.getParam("param3", &param3,
54                               {{0, std::string()}});
55       REQUIRE(error);
56    }
57 
58    SECTION("can parse two levels")
59    {
60       std::string profileStr = R"([*]
61           param=val
62           param2=val2
63 
64           [@user]
65           param=user-param
66           param3=user-param3
67 
68           [@admin]"
69           adminParam=admin-param)";
70 
71       ConfigProfile profile;
72       profile.addSections({{0, "*"},
73                           {1, "@"}});
74 
75       profile.addParams("param", std::string(),
76                         "param2", std::string(),
77                         "param3", std::string(),
78                         "adminParam", std::string());
79 
80       Error error = profile.parseString(profileStr);
81       REQUIRE_FALSE(error);
82 
83       std::string param;
84       error = profile.getParam("param", &param, {{0, std::string()}});
85       REQUIRE_FALSE(error);
86       REQUIRE(param == "val");
87 
88       std::string param2;
89       error = profile.getParam("param2", &param2, {{0, std::string()}});
90       REQUIRE_FALSE(error);
91       REQUIRE(param2 == "val2");
92 
93       std::string userParam;
94       error = profile.getParam("param", &userParam,
95                                {{0, std::string()},
96                                {1, "user"}});
97       REQUIRE_FALSE(error);
98       REQUIRE(userParam == "user-param");
99 
100       std::string param3;
101       error = profile.getParam("param3", &param3,
102                                {{0, std::string()},
103                                {1, "non-user"}});
104       REQUIRE_FALSE(error);
105       REQUIRE(param3 == std::string());
106 
107       std::string userParam3;
108       error = profile.getParam("param3", &userParam3,
109                                {{0, std::string()},
110                                {1, "user"}});
111       REQUIRE_FALSE(error);
112       REQUIRE(userParam3 == "user-param3");
113 
114       std::string adminParam;
115       error = profile.getParam("adminParam", &adminParam,
116                                {{0, std::string()},
117                                {1, "admin"}});
118       REQUIRE_FALSE(error);
119       REQUIRE(adminParam == "admin-param");
120    }
121 
122    SECTION("can parse three levels")
123    {
124       std::string profileStr = R"([*]
125           param=val
126           param2=val2
127 
128           [@user]
129           param=user-param
130           param3=user-param3
131 
132           [@admin]
133           adminParam=admin-param
134           param3=admin-param3
135 
136           [bdylan]
137           adminParam=bad-admin)";
138 
139       ConfigProfile profile;
140       profile.addSections({{0, "*"},
141                           {1, "@"},
142                           {2, std::string()}});
143 
144       profile.addParams("param", std::string(),
145                         "param2", std::string(),
146                         "param3", std::string(),
147                         "adminParam", std::string(),
148                         "neverUsedParam", std::string("never used"),
149                         "booleanNotUsed", true);
150 
151       Error error = profile.parseString(profileStr);
152       REQUIRE_FALSE(error);
153 
154       std::string param;
155       error = profile.getParam("param", &param, {{0, std::string()}});
156       REQUIRE_FALSE(error);
157       REQUIRE(param == "val");
158 
159       std::string param2;
160       error = profile.getParam("param2", &param2,
161                                {{0, std::string()},
162                                {1, "admin"}});
163       REQUIRE_FALSE(error);
164       REQUIRE(param2 == "val2");
165 
166       std::string userParam;
167       error = profile.getParam("param", &userParam,
168                                {{0, std::string()},
169                                {1, "user"}});
170       REQUIRE_FALSE(error);
171       REQUIRE(userParam == "user-param");
172 
173       std::string param3;
174       error = profile.getParam("param3", &param3,
175                                {{0, std::string()},
176                                {1, "non-user"}});
177       REQUIRE_FALSE(error);
178       REQUIRE(param3 == std::string());
179 
180       std::string userParam3;
181       error = profile.getParam("param3", &userParam3,
182                                {{0, std::string()},
183                                {1, "user"},
184                                {2, "josh"}});
185       REQUIRE_FALSE(error);
186       REQUIRE(userParam3 == "user-param3");
187 
188       std::string adminParam;
189       error = profile.getParam("adminParam", &adminParam,
190                                {{0, std::string()},
191                                {1, "admin"},
192                                {1, "user"}});
193       REQUIRE_FALSE(error);
194       REQUIRE(adminParam == "admin-param");
195 
196       std::string bdylanAdminParam;
197       error = profile.getParam("adminParam", &bdylanAdminParam,
198                                {{0, std::string()},
199                                {1, "admin"},
200                                {2, "bdylan"}});
201       REQUIRE_FALSE(error);
202       REQUIRE(bdylanAdminParam == "bad-admin");
203 
204       std::string bdylanAdminParam2;
205       error = profile.getParam("adminParam", &bdylanAdminParam2,
206                                {{2, "bdylan"}});
207       REQUIRE_FALSE(error);
208       REQUIRE(bdylanAdminParam2 == "bad-admin");
209 
210       std::string regularAdminParam;
211       error = profile.getParam("adminParam", &regularAdminParam,
212                                {{0, std::string()},
213                                {1, "admin"},
214                                {2, "joseph"}});
215       REQUIRE_FALSE(error);
216       REQUIRE(regularAdminParam == "admin-param");
217 
218       std::string bdylanParam3;
219       error = profile.getParam("param3", &bdylanParam3,
220                                {{0, std::string()},
221                                {1, "admin"},
222                                {2, "bdylan"}});
223       REQUIRE_FALSE(error);
224       REQUIRE(bdylanParam3 == "admin-param3");
225 
226       std::string neverUsedParam;
227       error = profile.getParam("neverUsedParam", &neverUsedParam,
228                                {{0, std::string()},
229                                {1, "admin"},
230                                {2, "bdylan"}});
231       REQUIRE_FALSE(error);
232       REQUIRE(neverUsedParam == "never used");
233 
234       bool boolNeverUsedParam = false;
235       error = profile.getParam("booleanNotUsed", &boolNeverUsedParam,
236                                {{0, std::string()},
237                                {1, "admin"},
238                                {2, "bdylan"}});
239       REQUIRE_FALSE(error);
240       REQUIRE(boolNeverUsedParam);
241    }
242 
243    SECTION("Can get level names")
244    {
245       std::string profileStr = R"([*]
246           param=val
247           param2=val2
248 
249           [@user]
250           param=user-param
251           param3=user-param3
252 
253           [@admin]
254           adminParam=admin-param
255           param3=admin-param3
256 
257           [bdylan]
258           adminParam=bad-admin)";
259 
260       ConfigProfile profile;
261       profile.addSections({{0, "*"},
262                           {1, "@"},
263                           {2, std::string()}});
264 
265       profile.addParams("param", std::string(),
266                         "param2", std::string(),
267                         "param3", std::string(),
268                         "adminParam", std::string(),
269                         "neverUsedParam", std::string("never used"),
270                         "booleanNotUsed", true);
271 
272       Error error = profile.parseString(profileStr);
273       REQUIRE_FALSE(error);
274 
275       std::vector<std::string> level1Names = profile.getLevelNames(1);
276       REQUIRE(level1Names.size() == 2);
277       REQUIRE(std::find(level1Names.begin(), level1Names.end(), "user") != level1Names.end());
278       REQUIRE(std::find(level1Names.begin(), level1Names.end(), "admin") != level1Names.end());
279 
280       std::vector<std::string> level2Names = profile.getLevelNames(2);
281       REQUIRE(level2Names.size() == 1);
282       REQUIRE(std::find(level2Names.begin(), level2Names.end(), "bdylan") != level2Names.end());
283       REQUIRE(std::find(level2Names.begin(), level2Names.end(), "bdaylan") == level2Names.end());
284    }
285 }
286 
287 } // end namespace tests
288 } // end namespace core
289 } // end namespace rstudio
290