Branch data Line data Source code
1 : : /*
2 : : SSSD
3 : :
4 : : util-tests.c
5 : :
6 : : Authors:
7 : : Stephen Gallagher <sgallagh@redhat.com>
8 : :
9 : : Copyright (C) 2010 Red Hat
10 : :
11 : : This program is free software; you can redistribute it and/or modify
12 : : it under the terms of the GNU General Public License as published by
13 : : the Free Software Foundation; either version 3 of the License, or
14 : : (at your option) any later version.
15 : :
16 : : This program is distributed in the hope that it will be useful,
17 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : GNU General Public License for more details.
20 : :
21 : : You should have received a copy of the GNU General Public License
22 : : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : : */
24 : :
25 : : #include <popt.h>
26 : : #include <talloc.h>
27 : : #include <check.h>
28 : : #include <sys/types.h>
29 : : #include <sys/stat.h>
30 : : #include <fcntl.h>
31 : : #include "util/util.h"
32 : : #include "util/sss_utf8.h"
33 : : #include "util/murmurhash3.h"
34 : : #include "tests/common.h"
35 : :
36 : : #define FILENAME_TEMPLATE "tests-atomicio-XXXXXX"
37 : : char *filename;
38 : : int atio_fd;
39 : :
40 : 1 : START_TEST(test_add_string_to_list)
41 : : {
42 : : int ret;
43 : :
44 : 1 : char **list = NULL;
45 : :
46 : 1 : ret = add_string_to_list(NULL, NULL, NULL);
47 : 1 : fail_unless(ret == EINVAL, "NULL input accepted");
48 : :
49 : 1 : ret = add_string_to_list(global_talloc_context, "ABC", &list);
50 : 1 : fail_unless(ret == EOK, "Adding string to non-existing list failed.");
51 : 1 : fail_unless(list != NULL, "No new list created.");
52 : 1 : fail_unless(list[0] != NULL, "String not added to new list.");
53 [ + - ][ + - ]: 1 : fail_unless(strcmp(list[0], "ABC") == 0,
[ + - ]
54 : : "Wrong string added to newly created list.");
55 : 1 : fail_unless(list[1] == NULL,
56 : : "Missing terminating NULL in newly created list.");
57 : :
58 : 1 : ret = add_string_to_list(global_talloc_context, "DEF", &list);
59 : 1 : fail_unless(ret == EOK, "Adding string to list failed.");
60 : 1 : fail_unless(list != NULL, "No list returned.");
61 [ + - ][ + - ]: 1 : fail_unless(strcmp(list[0], "ABC") == 0, "Wrong first string in new list.");
[ + - ]
62 [ + - ][ + - ]: 1 : fail_unless(strcmp(list[1], "DEF") == 0, "Wrong string added to list.");
[ + - ]
63 : 1 : fail_unless(list[2] == NULL, "Missing terminating NULL.");
64 : :
65 : 1 : list[0] = NULL;
66 : 1 : ret = add_string_to_list(global_talloc_context, "ABC", &list);
67 : 1 : fail_unless(ret == EOK, "Adding string to empty list failed.");
68 : 1 : fail_unless(list != NULL, "No list returned.");
69 : 1 : fail_unless(list[0] != NULL, "String not added to empty list.");
70 [ + - ][ + - ]: 1 : fail_unless(strcmp(list[0], "ABC") == 0,
[ + - ]
71 : : "Wrong string added to empty list.");
72 : 1 : fail_unless(list[1] == NULL,
73 : : "Missing terminating NULL in newly created list.");
74 : :
75 : 1 : talloc_free(list);
76 : : }
77 : 1 : END_TEST
78 : :
79 : 1 : START_TEST(test_string_in_list)
80 : : {
81 : : bool is_in;
82 : 1 : char *empty_list[] = {NULL};
83 : 1 : char *list[] = {discard_const("ABC"),
84 : : discard_const("DEF"),
85 : : discard_const("GHI"),
86 : : NULL};
87 : :
88 : 1 : is_in = string_in_list(NULL, NULL, false);
89 : 1 : fail_unless(!is_in, "NULL string is in NULL list.");
90 : :
91 : 1 : is_in = string_in_list(NULL, empty_list, false);
92 : 1 : fail_unless(!is_in, "NULL string is in empty list.");
93 : :
94 : 1 : is_in = string_in_list(NULL, list, false);
95 : 1 : fail_unless(!is_in, "NULL string is in list.");
96 : :
97 : 1 : is_in = string_in_list("ABC", NULL, false);
98 : 1 : fail_unless(!is_in, "String is in NULL list.");
99 : :
100 : 1 : is_in = string_in_list("ABC", empty_list, false);
101 : 1 : fail_unless(!is_in, "String is in empty list.");
102 : :
103 : 1 : is_in = string_in_list("ABC", list, false);
104 : 1 : fail_unless(is_in, "String is not list.");
105 : :
106 : 1 : is_in = string_in_list("abc", list, false);
107 : 1 : fail_unless(is_in, "String is not case in-sensitive list.");
108 : :
109 : 1 : is_in = string_in_list("abc", list, true);
110 : 1 : fail_unless(!is_in, "Wrong string found in case sensitive list.");
111 : :
112 : 1 : is_in = string_in_list("123", list, false);
113 : 1 : fail_unless(!is_in, "Wrong string found in list.");
114 : :
115 : : }
116 : 1 : END_TEST
117 : :
118 : 1 : START_TEST(test_parse_args)
119 : : {
120 : : struct pa_testcase {
121 : : const char *argstr;
122 : : const char **parsed;
123 : : };
124 : :
125 : : TALLOC_CTX *test_ctx;
126 : : int i, ii;
127 : : int ret;
128 : : char **parsed;
129 : : char **only_ret;
130 : : char **only_exp;
131 : : char **both;
132 : :
133 : 1 : test_ctx = talloc_new(NULL);
134 : :
135 : : /* Positive tests */
136 : 1 : const char *parsed1[] = { "foo", NULL };
137 : 1 : const char *parsed2[] = { "foo", "a", NULL };
138 : 1 : const char *parsed3[] = { "foo", "b", NULL };
139 : 1 : const char *parsed4[] = { "foo", "a c", NULL };
140 : 1 : const char *parsed5[] = { "foo", "a", "d", NULL };
141 : 1 : const char *parsed6[] = { "foo", "a", "e", NULL };
142 : 1 : const char *parsed7[] = { "foo", "a", "f", NULL };
143 : 1 : const char *parsed8[] = { "foo", "a\tg", NULL };
144 : 1 : struct pa_testcase tc[] = {
145 : : { "foo", parsed1 },
146 : : { "foo a", parsed2 },
147 : : { "foo b", parsed3 },
148 : : { "foo a\\ c", parsed4 },
149 : : { "foo a d ", parsed5 },
150 : : { "foo a e ", parsed6 },
151 : : { "foo a f ", parsed7 },
152 : : { "foo a\\\tg", parsed8 },
153 : : { NULL, NULL }
154 : : };
155 : :
156 [ + + ]: 9 : for (i=0; tc[i].argstr != NULL; i++) {
157 : 8 : parsed = parse_args(tc[i].argstr);
158 [ - + ][ # # ]: 8 : fail_if(parsed == NULL && tc[i].parsed != NULL,
159 : : "Could not parse correct argument string '%s'\n");
160 : :
161 : 8 : ret = diff_string_lists(test_ctx, parsed, discard_const(tc[i].parsed),
162 : : &only_ret, &only_exp, &both);
163 : 8 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
164 : 8 : fail_unless(only_ret[0] == NULL, "The parser returned more data than expected\n");
165 : 8 : fail_unless(only_exp[0] == NULL, "The parser returned less data than expected\n");
166 : :
167 [ + + ]: 34 : for (ii = 0; parsed[ii]; ii++) free(parsed[ii]);
168 : 8 : free(parsed);
169 : : }
170 : :
171 : 1 : talloc_free(test_ctx);
172 : : }
173 : 1 : END_TEST
174 : :
175 : 1 : START_TEST(test_diff_string_lists)
176 : : {
177 : : TALLOC_CTX *test_ctx;
178 : : char **l1;
179 : : char **l2;
180 : : char **l3;
181 : : char **only_l1;
182 : : char **only_l2;
183 : : char **both;
184 : : int ret;
185 : :
186 : 1 : test_ctx = talloc_new(NULL);
187 : :
188 : : /* Test with all values returned */
189 : 1 : l1 = talloc_array(test_ctx, char *, 4);
190 : 1 : l1[0] = talloc_strdup(l1, "a");
191 : 1 : l1[1] = talloc_strdup(l1, "b");
192 : 1 : l1[2] = talloc_strdup(l1, "c");
193 : 1 : l1[3] = NULL;
194 : :
195 : 1 : l2 = talloc_array(test_ctx, char *, 4);
196 : 1 : l2[0] = talloc_strdup(l1, "d");
197 : 1 : l2[1] = talloc_strdup(l1, "c");
198 : 1 : l2[2] = talloc_strdup(l1, "b");
199 : 1 : l2[3] = NULL;
200 : :
201 : 1 : ret = diff_string_lists(test_ctx,
202 : : l1, l2,
203 : : &only_l1, &only_l2, &both);
204 : :
205 : 1 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
206 [ + - ]: 1 : fail_unless(strcmp(only_l1[0], "a") == 0, "Missing \"a\" from only_l1");
207 : 1 : fail_unless(only_l1[1] == NULL, "only_l1 not NULL-terminated");
208 [ + - ]: 1 : fail_unless(strcmp(only_l2[0], "d") == 0, "Missing \"d\" from only_l2");
209 : 1 : fail_unless(only_l2[1] == NULL, "only_l2 not NULL-terminated");
210 [ + - ]: 1 : fail_unless(strcmp(both[0], "c") == 0, "Missing \"c\" from both");
211 [ + - ]: 1 : fail_unless(strcmp(both[1], "b") == 0, "Missing \"b\" from both");
212 : 1 : fail_unless(both[2] == NULL, "both not NULL-terminated");
213 : :
214 : 1 : talloc_zfree(only_l1);
215 : 1 : talloc_zfree(only_l2);
216 : 1 : talloc_zfree(both);
217 : :
218 : : /* Test with restricted return values */
219 : 1 : ret = diff_string_lists(test_ctx,
220 : : l1, l2,
221 : : &only_l1, &only_l2, NULL);
222 : :
223 : 1 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
224 [ + - ]: 1 : fail_unless(strcmp(only_l1[0], "a") == 0, "Missing \"a\" from only_l1");
225 : 1 : fail_unless(only_l1[1] == NULL, "only_l1 not NULL-terminated");
226 [ + - ]: 1 : fail_unless(strcmp(only_l2[0], "d") == 0, "Missing \"d\" from only_l2");
227 : 1 : fail_unless(only_l2[1] == NULL, "only_l2 not NULL-terminated");
228 : 1 : fail_unless(both == NULL, "Nothing returned to both");
229 : :
230 : 1 : talloc_zfree(only_l1);
231 : 1 : talloc_zfree(only_l2);
232 : 1 : talloc_zfree(both);
233 : :
234 : 1 : ret = diff_string_lists(test_ctx,
235 : : l1, l2,
236 : : &only_l1, NULL, NULL);
237 : :
238 : 1 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
239 [ + - ]: 1 : fail_unless(strcmp(only_l1[0], "a") == 0, "Missing \"a\" from only_l1");
240 : 1 : fail_unless(only_l1[1] == NULL, "only_l1 not NULL-terminated");
241 : 1 : fail_unless(only_l2 == NULL, "Nothing returned to only_l2");
242 : 1 : fail_unless(both == NULL, "Nothing returned to both");
243 : :
244 : 1 : talloc_zfree(only_l1);
245 : 1 : talloc_zfree(only_l2);
246 : 1 : talloc_zfree(both);
247 : :
248 : 1 : ret = diff_string_lists(test_ctx,
249 : : l1, l2,
250 : : NULL, &only_l2, NULL);
251 : :
252 : 1 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
253 [ + - ]: 1 : fail_unless(strcmp(only_l2[0], "d") == 0, "Missing \"d\" from only_l2");
254 : 1 : fail_unless(only_l2[1] == NULL, "only_l2 not NULL-terminated");
255 : 1 : fail_unless(only_l1 == NULL, "Nothing returned to only_l1");
256 : 1 : fail_unless(both == NULL, "Nothing returned to both");
257 : :
258 : 1 : talloc_zfree(only_l1);
259 : 1 : talloc_zfree(only_l2);
260 : 1 : talloc_zfree(both);
261 : :
262 : : /* Test with no overlap */
263 : 1 : l3 = talloc_array(test_ctx, char *, 4);
264 : 1 : l3[0] = talloc_strdup(l1, "d");
265 : 1 : l3[1] = talloc_strdup(l1, "e");
266 : 1 : l3[2] = talloc_strdup(l1, "f");
267 : 1 : l3[3] = NULL;
268 : :
269 : 1 : ret = diff_string_lists(test_ctx,
270 : : l1, l3,
271 : : &only_l1, &only_l2, &both);
272 : :
273 : 1 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
274 [ + - ]: 1 : fail_unless(strcmp(only_l1[0], "a") == 0, "Missing \"a\" from only_l1");
275 [ + - ]: 1 : fail_unless(strcmp(only_l1[1], "b") == 0, "Missing \"b\" from only_l1");
276 [ + - ]: 1 : fail_unless(strcmp(only_l1[2], "c") == 0, "Missing \"c\" from only_l1");
277 : 1 : fail_unless(only_l1[3] == NULL, "only_l1 not NULL-terminated");
278 [ + - ]: 1 : fail_unless(strcmp(only_l2[0], "d") == 0, "Missing \"f\" from only_l2");
279 [ + - ]: 1 : fail_unless(strcmp(only_l2[1], "e") == 0, "Missing \"e\" from only_l2");
280 [ + - ]: 1 : fail_unless(strcmp(only_l2[2], "f") == 0, "Missing \"d\" from only_l2");
281 : 1 : fail_unless(only_l2[3] == NULL, "only_l2 not NULL-terminated");
282 : 1 : fail_unless(both[0] == NULL, "both should have zero entries");
283 : :
284 : 1 : talloc_zfree(only_l1);
285 : 1 : talloc_zfree(only_l2);
286 : 1 : talloc_zfree(both);
287 : :
288 : : /* Test with 100% overlap */
289 : 1 : ret = diff_string_lists(test_ctx,
290 : : l1, l1,
291 : : &only_l1, &only_l2, &both);
292 : :
293 : 1 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
294 : 1 : fail_unless(only_l1[0] == NULL, "only_l1 should have zero entries");
295 : 1 : fail_unless(only_l2[0] == NULL, "only_l2 should have zero entries");
296 [ + - ]: 1 : fail_unless(strcmp(both[0], "a") == 0, "Missing \"a\" from both");
297 [ + - ]: 1 : fail_unless(strcmp(both[1], "b") == 0, "Missing \"b\" from both");
298 [ + - ]: 1 : fail_unless(strcmp(both[2], "c") == 0, "Missing \"c\" from both");
299 : 1 : fail_unless(both[3] == NULL, "both is not NULL-terminated");
300 : :
301 : 1 : talloc_zfree(only_l1);
302 : 1 : talloc_zfree(only_l2);
303 : 1 : talloc_zfree(both);
304 : :
305 : : /* Test with no second list */
306 : 1 : ret = diff_string_lists(test_ctx,
307 : : l1, NULL,
308 : : &only_l1, &only_l2, &both);
309 : :
310 : 1 : fail_unless(ret == EOK, "diff_string_lists returned error [%d]", ret);
311 [ + - ]: 1 : fail_unless(strcmp(only_l1[0], "a") == 0, "Missing \"a\" from only_l1");
312 [ + - ]: 1 : fail_unless(strcmp(only_l1[1], "b") == 0, "Missing \"b\" from only_l1");
313 [ + - ]: 1 : fail_unless(strcmp(only_l1[2], "c") == 0, "Missing \"c\" from only_l1");
314 : 1 : fail_unless(only_l1[3] == NULL, "only_l1 not NULL-terminated");
315 : 1 : fail_unless(only_l2[0] == NULL, "only_l2 should have zero entries");
316 : 1 : fail_unless(both[0] == NULL, "both should have zero entries");
317 : :
318 : 1 : talloc_free(test_ctx);
319 : : }
320 : 1 : END_TEST
321 : :
322 : :
323 : 1 : START_TEST(test_sss_filter_sanitize)
324 : : {
325 : : errno_t ret;
326 : 1 : char *sanitized = NULL;
327 : :
328 : 1 : TALLOC_CTX *test_ctx = talloc_new(NULL);
329 : 1 : fail_if (test_ctx == NULL, "Out of memory");
330 : :
331 : 1 : const char no_specials[] = "username";
332 : 1 : ret = sss_filter_sanitize(test_ctx, no_specials, &sanitized);
333 : 1 : fail_unless(ret == EOK, "no_specials error [%d][%s]",
334 : : ret, strerror(ret));
335 : 1 : fail_unless(strcmp(no_specials, sanitized)==0,
336 : : "Expected [%s], got [%s]",
337 : : no_specials, sanitized);
338 : :
339 : 1 : const char has_asterisk[] = "*username";
340 : 1 : const char has_asterisk_expected[] = "\\2ausername";
341 : 1 : ret = sss_filter_sanitize(test_ctx, has_asterisk, &sanitized);
342 : 1 : fail_unless(ret == EOK, "has_asterisk error [%d][%s]",
343 : : ret, strerror(ret));
344 : 1 : fail_unless(strcmp(has_asterisk_expected, sanitized)==0,
345 : : "Expected [%s], got [%s]",
346 : : has_asterisk_expected, sanitized);
347 : :
348 : 1 : const char has_lparen[] = "user(name";
349 : 1 : const char has_lparen_expected[] = "user\\28name";
350 : 1 : ret = sss_filter_sanitize(test_ctx, has_lparen, &sanitized);
351 : 1 : fail_unless(ret == EOK, "has_lparen error [%d][%s]",
352 : : ret, strerror(ret));
353 : 1 : fail_unless(strcmp(has_lparen_expected, sanitized)==0,
354 : : "Expected [%s], got [%s]",
355 : : has_lparen_expected, sanitized);
356 : :
357 : 1 : const char has_rparen[] = "user)name";
358 : 1 : const char has_rparen_expected[] = "user\\29name";
359 : 1 : ret = sss_filter_sanitize(test_ctx, has_rparen, &sanitized);
360 : 1 : fail_unless(ret == EOK, "has_rparen error [%d][%s]",
361 : : ret, strerror(ret));
362 : 1 : fail_unless(strcmp(has_rparen_expected, sanitized)==0,
363 : : "Expected [%s], got [%s]",
364 : : has_rparen_expected, sanitized);
365 : :
366 : 1 : const char has_backslash[] = "username\\";
367 : 1 : const char has_backslash_expected[] = "username\\5c";
368 : 1 : ret = sss_filter_sanitize(test_ctx, has_backslash, &sanitized);
369 : 1 : fail_unless(ret == EOK, "has_backslash error [%d][%s]",
370 : : ret, strerror(ret));
371 : 1 : fail_unless(strcmp(has_backslash_expected, sanitized)==0,
372 : : "Expected [%s], got [%s]",
373 : : has_backslash_expected, sanitized);
374 : :
375 : 1 : const char has_all[] = "\\(user)*name";
376 : 1 : const char has_all_expected[] = "\\5c\\28user\\29\\2aname";
377 : 1 : ret = sss_filter_sanitize(test_ctx, has_all, &sanitized);
378 : 1 : fail_unless(ret == EOK, "has_all error [%d][%s]",
379 : : ret, strerror(ret));
380 : 1 : fail_unless(strcmp(has_all_expected, sanitized)==0,
381 : : "Expected [%s], got [%s]",
382 : : has_all_expected, sanitized);
383 : :
384 : 1 : talloc_free(test_ctx);
385 : : }
386 : 1 : END_TEST
387 : :
388 : 1 : START_TEST(test_size_t_overflow)
389 : : {
390 : 1 : fail_unless(!SIZE_T_OVERFLOW(1, 1), "unexpected overflow");
391 : 1 : fail_unless(!SIZE_T_OVERFLOW(SIZE_T_MAX, 0), "unexpected overflow");
392 : 1 : fail_unless(!SIZE_T_OVERFLOW(SIZE_T_MAX-10, 10), "unexpected overflow");
393 : 1 : fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, 1), "overflow not detected");
394 : 1 : fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, SIZE_T_MAX),
395 : : "overflow not detected");
396 : 1 : fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, ULLONG_MAX),
397 : : "overflow not detected");
398 : 1 : fail_unless(SIZE_T_OVERFLOW(SIZE_T_MAX, -10), "overflow not detected");
399 : : }
400 : 1 : END_TEST
401 : :
402 : 1 : START_TEST(test_utf8_lowercase)
403 : : {
404 : 1 : const uint8_t munchen_utf8_upcase[] = { 'M', 0xC3, 0x9C, 'N', 'C', 'H', 'E', 'N', 0x0 };
405 : 1 : const uint8_t munchen_utf8_lowcase[] = { 'm', 0xC3, 0xBC, 'n', 'c', 'h', 'e', 'n', 0x0 };
406 : : uint8_t *lcase;
407 : : size_t nlen;
408 : :
409 : 1 : lcase = sss_utf8_tolower(munchen_utf8_upcase,
410 : : strlen((const char *)munchen_utf8_upcase),
411 : : &nlen);
412 : 1 : fail_if(strlen((const char *) munchen_utf8_upcase) != nlen); /* This is not true for utf8 strings in general */
413 : 1 : fail_if(memcmp(lcase, munchen_utf8_lowcase, nlen));
414 : 1 : sss_utf8_free(lcase);
415 : : }
416 : 1 : END_TEST
417 : :
418 : 1 : START_TEST(test_utf8_talloc_lowercase)
419 : : {
420 : 1 : const uint8_t munchen_utf8_upcase[] = { 'M', 0xC3, 0x9C, 'N', 'C', 'H', 'E', 'N', 0x0 };
421 : 1 : const uint8_t munchen_utf8_lowcase[] = { 'm', 0xC3, 0xBC, 'n', 'c', 'h', 'e', 'n', 0x0 };
422 : : uint8_t *lcase;
423 : : size_t nsize;
424 : :
425 : : TALLOC_CTX *test_ctx;
426 : 1 : test_ctx = talloc_new(NULL);
427 : 1 : fail_if(test_ctx == NULL);
428 : :
429 : 1 : lcase = sss_tc_utf8_tolower(test_ctx, munchen_utf8_upcase,
430 : : strlen((const char *) munchen_utf8_upcase),
431 : : &nsize);
432 : 1 : fail_if(memcmp(lcase, munchen_utf8_lowcase, nsize));
433 : 1 : talloc_free(test_ctx);
434 : : }
435 : 1 : END_TEST
436 : :
437 : 1 : START_TEST(test_utf8_talloc_str_lowercase)
438 : : {
439 : 1 : const uint8_t munchen_utf8_upcase[] = { 'M', 0xC3, 0x9C, 'N', 'C', 'H', 'E', 'N', 0x0 };
440 : 1 : const uint8_t munchen_utf8_lowcase[] = { 'm', 0xC3, 0xBC, 'n', 'c', 'h', 'e', 'n', 0x0 };
441 : : char *lcase;
442 : :
443 : : TALLOC_CTX *test_ctx;
444 : 1 : test_ctx = talloc_new(NULL);
445 : 1 : fail_if(test_ctx == NULL);
446 : :
447 : 1 : lcase = sss_tc_utf8_str_tolower(test_ctx, (const char *) munchen_utf8_upcase);
448 : 1 : fail_if(memcmp(lcase, munchen_utf8_lowcase, strlen(lcase)));
449 : 1 : talloc_free(test_ctx);
450 : : }
451 : 1 : END_TEST
452 : :
453 : 1 : START_TEST(test_utf8_caseeq)
454 : : {
455 : 1 : const uint8_t munchen_utf8_upcase[] = { 'M', 0xC3, 0x9C, 'N', 'C', 'H', 'E', 'N', 0x0 };
456 : 1 : const uint8_t munchen_utf8_lowcase[] = { 'm', 0xC3, 0xBC, 'n', 'c', 'h', 'e', 'n', 0x0 };
457 : 1 : const uint8_t czech_utf8_lowcase[] = { 0xC4, 0x8D, 'e', 'c', 'h', 0x0 };
458 : 1 : const uint8_t czech_utf8_upcase[] = { 0xC4, 0x8C, 'e', 'c', 'h', 0x0 };
459 : 1 : const uint8_t czech_utf8_lowcase_neg[] = { 0xC4, 0x8E, 'e', 'c', 'h', 0x0 };
460 : : errno_t ret;
461 : :
462 : 1 : ret = sss_utf8_case_eq(munchen_utf8_upcase, munchen_utf8_lowcase);
463 : 1 : fail_unless(ret == EOK, "Latin 1 Supplement comparison failed\n");
464 : :
465 : 1 : ret = sss_utf8_case_eq(czech_utf8_upcase, czech_utf8_lowcase);
466 : 1 : fail_unless(ret == EOK, "Latin Extended A comparison failed\n");
467 : :
468 : 1 : ret = sss_utf8_case_eq(czech_utf8_upcase, czech_utf8_lowcase_neg);
469 : 1 : fail_if(ret == EOK, "Negative test succeeded\n");
470 : : }
471 : 1 : END_TEST
472 : :
473 : 1 : START_TEST(test_utf8_check)
474 : : {
475 : 1 : const char *invalid = "ad\351la\357d";
476 : 1 : const uint8_t valid[] = { 'M', 0xC3, 0x9C, 'N', 'C', 'H', 'E', 'N', 0x0 };
477 : : bool ret;
478 : :
479 : 1 : ret = sss_utf8_check(valid, strlen((const char *) valid));
480 : 1 : fail_unless(ret == true, "Positive test failed\n");
481 : :
482 : 1 : ret = sss_utf8_check((const uint8_t *) invalid, strlen(invalid));
483 : 1 : fail_unless(ret == false, "Negative test succeeded\n");
484 : : }
485 : 1 : END_TEST
486 : :
487 : 1 : START_TEST(test_murmurhash3_check)
488 : : {
489 : 1 : const char *tests[6] = { "1052800007", "1052800008", "1052800000",
490 : : "abcdefghijk", "abcdefghili", "abcdefgh000" };
491 : : uint32_t results[6];
492 : : int i, j;
493 : :
494 [ + + ]: 7 : for (i = 0; i< 6; i++) {
495 : 6 : results[i] = murmurhash3(tests[i],
496 : 6 : strlen(tests[i]),
497 : : 0xdeadbeef);
498 [ + + ]: 21 : for (j = 0; j < i; j++) {
499 : 15 : fail_if(results[i] == results[j]);
500 : : }
501 : : }
502 : : }
503 : 1 : END_TEST
504 : :
505 : 1 : START_TEST(test_murmurhash3_random)
506 : : {
507 : : char test[16];
508 : : uint32_t result1;
509 : : uint32_t result2;
510 : : unsigned int init_seed;
511 : : unsigned int seed;
512 : : size_t len;
513 : : int i;
514 : :
515 : : /* generate a random string so each time we test with different values */
516 : 1 : init_seed = time(0);
517 : 1 : seed = init_seed;
518 : : /* use also random length (min len = 1) */
519 : 1 : len = 1 + rand_r(&seed) % 14;
520 [ + + ]: 7 : for (i = 0; i < len; i++) {
521 : 6 : test[i] = 1 + rand_r(&seed) % 254;
522 : : }
523 : 1 : test[len] = '\0'; /* null terminate */
524 : :
525 : 1 : fprintf(stdout, "test_murmurhash3_random seed: %d\n", init_seed);
526 : :
527 : 1 : result1 = murmurhash3(test, len + 1, init_seed);
528 : 1 : result2 = murmurhash3(test, len + 1, init_seed);
529 : 1 : fail_if(result1 != result2);
530 : : }
531 : 1 : END_TEST
532 : :
533 : 5 : void setup_atomicio(void)
534 : : {
535 : : int ret;
536 : : mode_t old_umask;
537 : :
538 [ + - ]: 5 : filename = strdup(FILENAME_TEMPLATE);
539 : 5 : fail_unless(filename != NULL, "strdup failed");
540 : :
541 : 5 : atio_fd = -1;
542 : 5 : old_umask = umask(077);
543 : 5 : ret = mkstemp(filename);
544 : 5 : umask(old_umask);
545 : 5 : fail_unless(ret != -1, "mkstemp failed [%d][%s]", errno, strerror(errno));
546 : 5 : atio_fd = ret;
547 : 5 : }
548 : :
549 : 5 : void teardown_atomicio(void)
550 : : {
551 : : int ret;
552 : :
553 [ + - ]: 5 : if (atio_fd != -1) {
554 : 5 : ret = close(atio_fd);
555 : 5 : fail_unless(ret == 0, "close failed [%d][%s]", errno, strerror(errno));
556 : : }
557 : :
558 : 5 : fail_unless(filename != NULL, "unknown filename");
559 : 5 : ret = unlink(filename);
560 : 5 : free(filename);
561 : 5 : fail_unless(ret == 0, "unlink failed [%d][%s]", errno, strerror(errno));
562 : 5 : }
563 : :
564 : 1 : START_TEST(test_atomicio_read_from_file)
565 : : {
566 : 1 : const ssize_t bufsize = 64;
567 : : char buf[64];
568 : : int fd;
569 : : ssize_t numread;
570 : : errno_t ret;
571 : :
572 : 1 : fd = open("/dev/zero", O_RDONLY);
573 : 1 : fail_if(fd == -1, "Cannot open /dev/zero");
574 : :
575 : 1 : errno = 0;
576 : 1 : numread = sss_atomic_read_s(fd, buf, bufsize);
577 : 1 : ret = errno;
578 : :
579 : 1 : fail_unless(ret == 0, "Error %d while reading\n", ret);
580 : 1 : fail_unless(numread == bufsize,
581 : : "Read %d bytes expected %d\n", numread, bufsize);
582 : 1 : close(fd);
583 : : }
584 : 1 : END_TEST
585 : :
586 : 1 : START_TEST(test_atomicio_read_from_small_file)
587 : : {
588 : 1 : char wbuf[] = "foobar";
589 : 1 : ssize_t wsize = strlen(wbuf)+1;
590 : : ssize_t numwritten;
591 : : char rbuf[64];
592 : : ssize_t numread;
593 : : errno_t ret;
594 : :
595 : 1 : fail_if(atio_fd < 0, "No fd to test?\n");
596 : :
597 : 1 : errno = 0;
598 : 1 : numwritten = sss_atomic_write_s(atio_fd, wbuf, wsize);
599 : 1 : ret = errno;
600 : :
601 : 1 : fail_unless(ret == 0, "Error %d while writing\n", ret);
602 : 1 : fail_unless(numwritten == wsize,
603 : : "Wrote %d bytes expected %d\n", numwritten, wsize);
604 : :
605 : 1 : fsync(atio_fd);
606 : 1 : lseek(atio_fd, 0, SEEK_SET);
607 : :
608 : 1 : errno = 0;
609 : 1 : numread = sss_atomic_read_s(atio_fd, rbuf, 64);
610 : 1 : ret = errno;
611 : :
612 : 1 : fail_unless(ret == 0, "Error %d while reading\n", ret);
613 : 1 : fail_unless(numread == numwritten,
614 : : "Read %d bytes expected %d\n", numread, numwritten);
615 : : }
616 : 1 : END_TEST
617 : :
618 : 1 : START_TEST(test_atomicio_read_from_large_file)
619 : : {
620 : 1 : char wbuf[] = "123456781234567812345678";
621 : 1 : ssize_t wsize = strlen(wbuf)+1;
622 : : ssize_t numwritten;
623 : : char rbuf[8];
624 : : ssize_t numread;
625 : : ssize_t total;
626 : : errno_t ret;
627 : :
628 : 1 : fail_if(atio_fd < 0, "No fd to test?\n");
629 : :
630 : 1 : errno = 0;
631 : 1 : numwritten = sss_atomic_write_s(atio_fd, wbuf, wsize);
632 : 1 : ret = errno;
633 : :
634 : 1 : fail_unless(ret == 0, "Error %d while writing\n", ret);
635 : 1 : fail_unless(numwritten == wsize,
636 : : "Wrote %d bytes expected %d\n", numwritten, wsize);
637 : :
638 : 1 : fsync(atio_fd);
639 : 1 : lseek(atio_fd, 0, SEEK_SET);
640 : :
641 : 1 : total = 0;
642 : : do {
643 : 5 : errno = 0;
644 : 5 : numread = sss_atomic_read_s(atio_fd, rbuf, 8);
645 : 5 : ret = errno;
646 : :
647 : 5 : fail_if(numread == -1, "Read error %d: %s\n", ret, strerror(ret));
648 : 5 : total += numread;
649 [ + + ]: 5 : } while (numread != 0);
650 : :
651 : 1 : fail_unless(ret == 0, "Error %d while reading\n", ret);
652 : 1 : fail_unless(total == numwritten,
653 : : "Read %d bytes expected %d\n", numread, numwritten);
654 : : }
655 : 1 : END_TEST
656 : :
657 : 1 : START_TEST(test_atomicio_read_exact_sized_file)
658 : : {
659 : 1 : char wbuf[] = "12345678";
660 : 1 : ssize_t wsize = strlen(wbuf)+1;
661 : : ssize_t numwritten;
662 : : char rbuf[9];
663 : : ssize_t numread;
664 : : errno_t ret;
665 : :
666 : 1 : fail_if(atio_fd < 0, "No fd to test?\n");
667 : :
668 : 1 : errno = 0;
669 : 1 : numwritten = sss_atomic_write_s(atio_fd, wbuf, wsize);
670 : 1 : ret = errno;
671 : :
672 : 1 : fail_unless(ret == 0, "Error %d while writing\n", ret);
673 : 1 : fail_unless(numwritten == wsize,
674 : : "Wrote %d bytes expected %d\n", numwritten, wsize);
675 : :
676 : 1 : fsync(atio_fd);
677 : 1 : lseek(atio_fd, 0, SEEK_SET);
678 : :
679 : 1 : errno = 0;
680 : 1 : numread = sss_atomic_read_s(atio_fd, rbuf, 9);
681 : 1 : ret = errno;
682 : :
683 : 1 : fail_unless(ret == 0, "Error %d while reading\n", ret);
684 : 1 : fail_unless(numread == numwritten,
685 : : "Read %d bytes expected %d\n", numread, numwritten);
686 : :
687 : 1 : fail_unless(rbuf[8] == '\0', "String not NULL terminated?");
688 : 1 : fail_unless(strcmp(wbuf, rbuf) == 0, "Read something else than wrote?");
689 : :
690 : : /* We've reached end-of-file, next read must return 0 */
691 : 1 : errno = 0;
692 : 1 : numread = sss_atomic_read_s(atio_fd, rbuf, 9);
693 : 1 : ret = errno;
694 : :
695 : 1 : fail_unless(ret == 0, "Error %d while reading\n", ret);
696 : 1 : fail_unless(numread == 0, "More data to read?");
697 : : }
698 : 1 : END_TEST
699 : :
700 : 1 : START_TEST(test_atomicio_read_from_empty_file)
701 : : {
702 : : char buf[64];
703 : : int fd;
704 : : ssize_t numread;
705 : : errno_t ret;
706 : :
707 : 1 : fd = open("/dev/null", O_RDONLY);
708 : 1 : fail_if(fd == -1, "Cannot open /dev/null");
709 : :
710 : 1 : errno = 0;
711 : 1 : numread = sss_atomic_read_s(fd, buf, 64);
712 : 1 : ret = errno;
713 : :
714 : 1 : fail_unless(ret == 0, "Error %d while reading\n", ret);
715 : 1 : fail_unless(numread == 0,
716 : : "Read %d bytes expected 0\n", numread);
717 : 1 : close(fd);
718 : : }
719 : 1 : END_TEST
720 : :
721 : 19 : Suite *util_suite(void)
722 : : {
723 : 19 : Suite *s = suite_create("util");
724 : :
725 : 19 : TCase *tc_util = tcase_create("util");
726 : :
727 : 19 : tcase_add_checked_fixture(tc_util,
728 : : leak_check_setup,
729 : : leak_check_teardown);
730 : 19 : tcase_add_test (tc_util, test_diff_string_lists);
731 : 19 : tcase_add_test (tc_util, test_sss_filter_sanitize);
732 : 19 : tcase_add_test (tc_util, test_size_t_overflow);
733 : 19 : tcase_add_test (tc_util, test_parse_args);
734 : 19 : tcase_add_test (tc_util, test_add_string_to_list);
735 : 19 : tcase_add_test (tc_util, test_string_in_list);
736 : 19 : tcase_set_timeout(tc_util, 60);
737 : :
738 : 19 : TCase *tc_utf8 = tcase_create("utf8");
739 : 19 : tcase_add_test (tc_utf8, test_utf8_lowercase);
740 : 19 : tcase_add_test (tc_utf8, test_utf8_talloc_lowercase);
741 : 19 : tcase_add_test (tc_utf8, test_utf8_talloc_str_lowercase);
742 : 19 : tcase_add_test (tc_utf8, test_utf8_caseeq);
743 : 19 : tcase_add_test (tc_utf8, test_utf8_check);
744 : :
745 : 19 : tcase_set_timeout(tc_utf8, 60);
746 : :
747 : 19 : TCase *tc_mh3 = tcase_create("murmurhash3");
748 : 19 : tcase_add_test (tc_mh3, test_murmurhash3_check);
749 : 19 : tcase_add_test (tc_mh3, test_murmurhash3_random);
750 : 19 : tcase_set_timeout(tc_mh3, 60);
751 : :
752 : 19 : TCase *tc_atomicio = tcase_create("atomicio");
753 : 19 : tcase_add_checked_fixture (tc_atomicio,
754 : : setup_atomicio,
755 : : teardown_atomicio);
756 : 19 : tcase_add_test(tc_atomicio, test_atomicio_read_from_file);
757 : 19 : tcase_add_test(tc_atomicio, test_atomicio_read_from_small_file);
758 : 19 : tcase_add_test(tc_atomicio, test_atomicio_read_from_large_file);
759 : 19 : tcase_add_test(tc_atomicio, test_atomicio_read_exact_sized_file);
760 : 19 : tcase_add_test(tc_atomicio, test_atomicio_read_from_empty_file);
761 : :
762 : 19 : suite_add_tcase (s, tc_util);
763 : 19 : suite_add_tcase (s, tc_utf8);
764 : 19 : suite_add_tcase (s, tc_mh3);
765 : 19 : suite_add_tcase (s, tc_atomicio);
766 : :
767 : 19 : return s;
768 : : }
769 : :
770 : 19 : int main(int argc, const char *argv[])
771 : : {
772 : : int opt;
773 : : int failure_count;
774 : : poptContext pc;
775 : 19 : Suite *s = util_suite();
776 : 19 : SRunner *sr = srunner_create (s);
777 : :
778 : 95 : struct poptOption long_options[] = {
779 : : POPT_AUTOHELP
780 : 76 : SSSD_MAIN_OPTS
781 : : POPT_TABLEEND
782 : : };
783 : :
784 : : /* Set debug level to invalid value so we can deside if -d 0 was used. */
785 : 19 : debug_level = SSSDBG_INVALID;
786 : :
787 : 19 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
788 [ - + ]: 19 : while((opt = poptGetNextOpt(pc)) != -1) {
789 : : switch(opt) {
790 : : default:
791 : 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
792 : : poptBadOption(pc, 0), poptStrerror(opt));
793 : 0 : poptPrintUsage(pc, stderr, 0);
794 : : return 1;
795 : : }
796 : : }
797 : 19 : poptFreeContext(pc);
798 : :
799 [ - + ]: 19 : DEBUG_INIT(debug_level);
800 : :
801 : 19 : tests_set_cwd();
802 : :
803 : 19 : srunner_run_all(sr, CK_ENV);
804 : 1 : failure_count = srunner_ntests_failed (sr);
805 : 1 : srunner_free (sr);
806 [ - + ]: 1 : if (failure_count == 0) {
807 : : return EXIT_SUCCESS;
808 : : }
809 : : return EXIT_FAILURE;
810 : : }
|