xref: /dpdk/app/test/test_cfgfile.c (revision 554e802ee3204a24149f76946c8ad81b2582349c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Wind River Systems, Inc.
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdint.h>
8 #include <unistd.h>
9 
10 #ifdef RTE_EXEC_ENV_WINDOWS
11 #include <io.h>
12 #endif
13 
14 #include <rte_cfgfile.h>
15 
16 #include "test.h"
17 
18 #include "test_cfgfiles.h"
19 
20 static int
21 make_tmp_file(char *filename, const char *prefix, const char *data)
22 {
23 	size_t len = strlen(data);
24 	size_t count;
25 	FILE *f;
26 
27 #ifdef RTE_EXEC_ENV_WINDOWS
28 	char tempDirName[MAX_PATH - 14];
29 
30 	if (GetTempPathA(sizeof(tempDirName), tempDirName) == 0)
31 		return -1;
32 
33 	if (GetTempFileNameA(tempDirName, prefix, 0, filename) == 0)
34 		return -1;
35 
36 	f = fopen(filename, "wt");
37 #else
38 	snprintf(filename, PATH_MAX, "/tmp/%s_XXXXXXX", prefix);
39 
40 	int fd = mkstemp(filename);
41 	if (fd < 0)
42 		return -1;
43 
44 	f = fdopen(fd, "w");
45 #endif
46 	if (f == NULL)
47 		return -1;
48 
49 	count = fwrite(data, sizeof(char), len, f);
50 	fclose(f);
51 
52 	return (count == len) ? 0 : -1;
53 }
54 
55 
56 static int
57 _test_cfgfile_sample(struct rte_cfgfile *cfgfile)
58 {
59 	const char *value;
60 	int ret;
61 
62 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
63 	TEST_ASSERT(ret == 2, "Unexpected number of sections: %d", ret);
64 
65 	ret = rte_cfgfile_has_section(cfgfile, "section1");
66 	TEST_ASSERT(ret, "section1 section missing");
67 
68 	ret = rte_cfgfile_section_num_entries(cfgfile, "section1");
69 	TEST_ASSERT(ret == 1, "section1 unexpected number of entries: %d", ret);
70 
71 	value = rte_cfgfile_get_entry(cfgfile, "section1", "key1");
72 	TEST_ASSERT(strcmp("value1", value) == 0,
73 		    "key1 unexpected value: %s", value);
74 
75 	ret = rte_cfgfile_has_section(cfgfile, "section2");
76 	TEST_ASSERT(ret, "section2 section missing");
77 
78 	ret = rte_cfgfile_section_num_entries(cfgfile, "section2");
79 	TEST_ASSERT(ret == 2, "section2 unexpected number of entries: %d", ret);
80 
81 	value = rte_cfgfile_get_entry(cfgfile, "section2", "key2");
82 	TEST_ASSERT(strcmp("value2", value) == 0,
83 		    "key2 unexpected value: %s", value);
84 
85 	value = rte_cfgfile_get_entry(cfgfile, "section2", "key3");
86 	TEST_ASSERT(strcmp("value3", value) == 0,
87 		    "key3 unexpected value: %s", value);
88 
89 	return 0;
90 }
91 
92 static int
93 test_cfgfile_sample1(void)
94 {
95 	struct rte_cfgfile *cfgfile;
96 	char filename[PATH_MAX];
97 	int ret;
98 
99 	ret = make_tmp_file(filename, "sample1", sample1_ini);
100 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
101 
102 	cfgfile = rte_cfgfile_load(filename, 0);
103 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
104 
105 	ret = _test_cfgfile_sample(cfgfile);
106 	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
107 
108 	ret = rte_cfgfile_close(cfgfile);
109 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
110 
111 	ret = remove(filename);
112 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
113 
114 	return 0;
115 }
116 
117 static int
118 test_cfgfile_sample2(void)
119 {
120 	struct rte_cfgfile_parameters params;
121 	struct rte_cfgfile *cfgfile;
122 	char filename[PATH_MAX];
123 	int ret;
124 
125 	ret = make_tmp_file(filename, "sample2", sample2_ini);
126 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
127 
128 	/* override comment character */
129 	memset(&params, 0, sizeof(params));
130 	params.comment_character = '#';
131 
132 	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
133 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2");
134 
135 	ret = _test_cfgfile_sample(cfgfile);
136 	TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
137 
138 	ret = rte_cfgfile_close(cfgfile);
139 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
140 
141 	ret = remove(filename);
142 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
143 
144 	return 0;
145 }
146 
147 static int
148 test_cfgfile_realloc_sections(void)
149 {
150 	struct rte_cfgfile *cfgfile;
151 	char filename[PATH_MAX];
152 	int ret;
153 	const char *value;
154 
155 	ret = make_tmp_file(filename, "realloc", realloc_sections_ini);
156 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
157 
158 	cfgfile = rte_cfgfile_load(filename, 0);
159 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
160 
161 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
162 	TEST_ASSERT(ret == 9, "Unexpected number of sections: %d", ret);
163 
164 	ret = rte_cfgfile_has_section(cfgfile, "section9");
165 	TEST_ASSERT(ret, "section9 missing");
166 
167 	ret = rte_cfgfile_section_num_entries(cfgfile, "section3");
168 	TEST_ASSERT(ret == 21,
169 			"section3 unexpected number of entries: %d", ret);
170 
171 	ret = rte_cfgfile_section_num_entries(cfgfile, "section9");
172 	TEST_ASSERT(ret == 8, "section9 unexpected number of entries: %d", ret);
173 
174 	value = rte_cfgfile_get_entry(cfgfile, "section9", "key8");
175 	TEST_ASSERT(strcmp("value8_section9", value) == 0,
176 		    "key unexpected value: %s", value);
177 
178 	ret = remove(filename);
179 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
180 
181 	char tmp[PATH_MAX] = "/tmp/";
182 #ifdef RTE_EXEC_ENV_WINDOWS
183 	ret = GetTempPathA(sizeof(tmp), tmp);
184 	TEST_ASSERT(ret > 0, "Failed to get tmp directory");
185 #endif
186 	snprintf(filename, sizeof(filename), "%s%s", tmp, "cfg_save.ini");
187 
188 	ret = rte_cfgfile_save(cfgfile, filename);
189 	TEST_ASSERT_SUCCESS(ret, "Failed to save to %s", filename);
190 
191 	ret = remove(filename);
192 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
193 
194 	ret = rte_cfgfile_close(cfgfile);
195 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
196 
197 	return 0;
198 }
199 
200 static int
201 test_cfgfile_invalid_section_header(void)
202 {
203 	struct rte_cfgfile *cfgfile;
204 	char filename[PATH_MAX];
205 	int ret;
206 
207 	ret = make_tmp_file(filename, "invalid", invalid_section_ini);
208 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
209 
210 	cfgfile = rte_cfgfile_load(filename, 0);
211 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
212 
213 	ret = remove(filename);
214 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
215 
216 	return 0;
217 }
218 
219 static int
220 test_cfgfile_invalid_comment(void)
221 {
222 	struct rte_cfgfile_parameters params;
223 	struct rte_cfgfile *cfgfile;
224 	char filename[PATH_MAX];
225 	int ret;
226 
227 	/* override comment character with an invalid one */
228 	memset(&params, 0, sizeof(params));
229 	params.comment_character = '$';
230 
231 	ret = make_tmp_file(filename, "sample2", sample2_ini);
232 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
233 
234 	cfgfile = rte_cfgfile_load_with_params(filename, 0, &params);
235 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
236 
237 	ret = remove(filename);
238 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
239 
240 	return 0;
241 }
242 
243 static int
244 test_cfgfile_invalid_key_value_pair(void)
245 {
246 	struct rte_cfgfile *cfgfile;
247 	char filename[PATH_MAX];
248 	int ret;
249 
250 	ret = make_tmp_file(filename, "empty_key", empty_key_value_ini);
251 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
252 
253 	cfgfile = rte_cfgfile_load(filename, 0);
254 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
255 
256 	ret = remove(filename);
257 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
258 
259 	return 0;
260 }
261 
262 static int
263 test_cfgfile_empty_key_value_pair(void)
264 {
265 	struct rte_cfgfile *cfgfile;
266 	const char *value;
267 	char filename[PATH_MAX];
268 	int ret;
269 
270 	ret = make_tmp_file(filename, "empty_key_value", empty_key_value_ini);
271 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
272 
273 	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_EMPTY_VALUES);
274 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value");
275 
276 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
277 	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
278 
279 	ret = rte_cfgfile_has_section(cfgfile, "section1");
280 	TEST_ASSERT(ret, "section1 missing");
281 
282 	ret = rte_cfgfile_section_num_entries(cfgfile, "section1");
283 	TEST_ASSERT(ret == 1, "section1 unexpected number of entries: %d", ret);
284 
285 	value = rte_cfgfile_get_entry(cfgfile, "section1", "key");
286 	TEST_ASSERT(strlen(value) == 0, "key unexpected value: %s", value);
287 
288 	ret = rte_cfgfile_close(cfgfile);
289 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
290 
291 	ret = remove(filename);
292 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
293 
294 	return 0;
295 }
296 
297 static int
298 test_cfgfile_missing_section(void)
299 {
300 	struct rte_cfgfile *cfgfile;
301 	char filename[PATH_MAX];
302 	int ret;
303 
304 	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
305 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
306 
307 	cfgfile = rte_cfgfile_load(filename, 0);
308 	TEST_ASSERT_NULL(cfgfile, "Expected failure did not occur");
309 
310 	ret = remove(filename);
311 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
312 
313 	return 0;
314 }
315 
316 static int
317 test_cfgfile_global_properties(void)
318 {
319 	struct rte_cfgfile *cfgfile;
320 	const char *value;
321 	char filename[PATH_MAX];
322 	int ret;
323 
324 	ret = make_tmp_file(filename, "missing_section", missing_section_ini);
325 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
326 
327 	cfgfile = rte_cfgfile_load(filename, CFG_FLAG_GLOBAL_SECTION);
328 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
329 
330 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
331 	TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
332 
333 	ret = rte_cfgfile_has_section(cfgfile, "GLOBAL");
334 	TEST_ASSERT(ret, "global section missing");
335 
336 	ret = rte_cfgfile_section_num_entries(cfgfile, "GLOBAL");
337 	TEST_ASSERT(ret == 1, "GLOBAL unexpected number of entries: %d", ret);
338 
339 	value = rte_cfgfile_get_entry(cfgfile, "GLOBAL", "key");
340 	TEST_ASSERT(strcmp("value", value) == 0,
341 		    "key unexpected value: %s", value);
342 
343 	ret = rte_cfgfile_close(cfgfile);
344 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
345 
346 	ret = remove(filename);
347 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
348 
349 	return 0;
350 }
351 
352 static int
353 test_cfgfile_empty_file(void)
354 {
355 	struct rte_cfgfile *cfgfile;
356 	char filename[PATH_MAX];
357 	int ret;
358 
359 	ret = make_tmp_file(filename, "empty", empty_ini);
360 	TEST_ASSERT_SUCCESS(ret, "Failed to setup temp file");
361 
362 	cfgfile = rte_cfgfile_load(filename, 0);
363 	TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
364 
365 	ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
366 	TEST_ASSERT(ret == 0, "Unexpected number of sections: %d", ret);
367 
368 	ret = rte_cfgfile_close(cfgfile);
369 	TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
370 
371 	ret = remove(filename);
372 	TEST_ASSERT_SUCCESS(ret, "Failed to remove file");
373 
374 	return 0;
375 }
376 
377 static struct
378 unit_test_suite test_cfgfile_suite  = {
379 	.suite_name = "Test Cfgfile Unit Test Suite",
380 	.unit_test_cases = {
381 		TEST_CASE(test_cfgfile_sample1),
382 		TEST_CASE(test_cfgfile_sample2),
383 		TEST_CASE(test_cfgfile_realloc_sections),
384 		TEST_CASE(test_cfgfile_invalid_section_header),
385 		TEST_CASE(test_cfgfile_invalid_comment),
386 		TEST_CASE(test_cfgfile_invalid_key_value_pair),
387 		TEST_CASE(test_cfgfile_empty_key_value_pair),
388 		TEST_CASE(test_cfgfile_missing_section),
389 		TEST_CASE(test_cfgfile_global_properties),
390 		TEST_CASE(test_cfgfile_empty_file),
391 
392 		TEST_CASES_END()
393 	}
394 };
395 
396 static int
397 test_cfgfile(void)
398 {
399 	return unit_test_suite_runner(&test_cfgfile_suite);
400 }
401 
402 REGISTER_FAST_TEST(cfgfile_autotest, true, true, test_cfgfile);
403