libndr: Avoid assigning duplicate versions to symbols
[amitay/samba.git] / lib / util / tests / util.c
1 /*
2  * Tests for strv_util
3  *
4  * Copyright Martin Schwenke <martin@meltin.net> 2016
5  * Copyright Christof Schmitt <cs@samba.org> 2018
6  * Copyright Swen Schillig <swen@linux.ibm.com> 2019
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <talloc.h>
23
24 #include "replace.h"
25 #include "system/filesys.h"
26
27 #include "libcli/util/ntstatus.h"
28 #include "torture/torture.h"
29 #include "lib/util/data_blob.h"
30 #include "torture/local/proto.h"
31
32 #include "lib/util/samba_util.h"
33 #include "lib/util/smb_strtox.h"
34
35 #include "limits.h"
36 #include "string.h"
37
38 struct test_trim_string_data {
39         const char *desc;
40         const char *in;
41         const char *front;
42         const char *back;
43         const char *out;
44         bool ret;
45 };
46
47 static const struct test_trim_string_data test_trim_string_data[] = {
48         {
49                 .desc  = "All NULL",
50                 .in    = NULL,
51                 .front = NULL,
52                 .back  = NULL,
53                 .out   = NULL,
54                 .ret   = false,
55         },
56         {
57                 .desc  = "Input NULL",
58                 .in    = NULL,
59                 .front = "abc",
60                 .back  = "123",
61                 .out   = NULL,
62                 .ret   = false,
63         },
64         {
65                 .desc  = "Trim NULL",
66                 .in    = "abc",
67                 .front = NULL,
68                 .back  = NULL,
69                 .out   = "abc",
70                 .ret   = false,
71         },
72         {
73                 .desc  = "Trim empty",
74                 .in    = "abc",
75                 .front = "",
76                 .back  = "",
77                 .out   = "abc",
78                 .ret   = false,
79         },
80         {
81                 .desc  = "Trim front, non-matching",
82                 .in    = "abc",
83                 .front = "x",
84                 .back  = "",
85                 .out   = "abc",
86                 .ret   = false,
87         },
88         {
89                 .desc  = "Trim front, matches back",
90                 .in    = "abc",
91                 .front = "c",
92                 .back  = "",
93                 .out   = "abc",
94                 .ret   = false,
95         },
96         {
97                 .desc  = "Trim front, partial-match",
98                 .in    = "abc",
99                 .front = "ac",
100                 .back  = "",
101                 .out   = "abc",
102                 .ret   = false,
103         },
104         {
105                 .desc  = "Trim front, too long",
106                 .in    = "aaa",
107                 .front = "aaaa",
108                 .back  = "",
109                 .out   = "aaa",
110                 .ret   = false,
111         },
112         {
113                 .desc  = "Trim front, 1 char, 1x",
114                 .in    = "abc",
115                 .front = "a",
116                 .back  = "",
117                 .out   = "bc",
118                 .ret   = true,
119         },
120         {
121                 .desc  = "Trim front, 1 char, 2x",
122                 .in    = "aabc",
123                 .front = "a",
124                 .back  = "",
125                 .out   = "bc",
126                 .ret   = true,
127         },
128         {
129                 .desc  = "Trim front, 1 char, 3x",
130                 .in    = "aaabc",
131                 .front = "a",
132                 .back  = "",
133                 .out   = "bc",
134                 .ret   = true,
135         },
136         {
137                 .desc  = "Trim front, 1 char, matches all",
138                 .in    = "aaa",
139                 .front = "a",
140                 .back  = "",
141                 .out   = "",
142                 .ret   = true,
143         },
144         {
145                 .desc  = "Trim front, 2 chars, 1x",
146                 .in    = "abc",
147                 .front = "ab",
148                 .back  = "",
149                 .out   = "c",
150                 .ret   = true,
151         },
152         {
153                 .desc  = "Trim front, 2 chars, 2x",
154                 .in    = "ababc",
155                 .front = "ab",
156                 .back  = "",
157                 .out   = "c",
158                 .ret   = true,
159         },
160         {
161                 .desc  = "Trim front, 3 chars, matches all",
162                 .in    = "abc",
163                 .front = "abc",
164                 .back  = "",
165                 .out   = "",
166                 .ret   = true,
167         },
168         {
169                 .desc  = "Trim back, non-matching",
170                 .in    = "abc",
171                 .front = "",
172                 .back  = "x",
173                 .out   = "abc",
174                 .ret   = false,
175         },
176         {
177                 .desc  = "Trim back, matches front",
178                 .in    = "abc",
179                 .front = "",
180                 .back  = "a",
181                 .out   = "abc",
182                 .ret   = false,
183         },
184         {
185                 .desc  = "Trim back, partial-match",
186                 .in    = "abc",
187                 .front = "",
188                 .back  = "xc",
189                 .out   = "abc",
190                 .ret   = false,
191         },
192         {
193                 .desc  = "Trim back, too long",
194                 .in    = "aaa",
195                 .front = "",
196                 .back  = "aaaa",
197                 .out   = "aaa",
198                 .ret   = false,
199         },
200         {
201                 .desc  = "Trim back, 1 char, 1x",
202                 .in    = "abc",
203                 .front = "",
204                 .back  = "c",
205                 .out   = "ab",
206                 .ret   = true,
207         },
208         {
209                 .desc  = "Trim back, 1 char, 2x",
210                 .in    = "abcc",
211                 .front = "",
212                 .back  = "c",
213                 .out   = "ab",
214                 .ret   = true,
215         },
216         {
217                 .desc  = "Trim back, 1 char, 3x",
218                 .in    = "abccc",
219                 .front = "",
220                 .back  = "c",
221                 .out   = "ab",
222                 .ret   = true,
223         },
224         {
225                 .desc  = "Trim back, 1 char, matches all",
226                 .in    = "aaa",
227                 .front = "",
228                 .back  = "a",
229                 .out   = "",
230                 .ret   = true,
231         },
232         {
233                 .desc  = "Trim back, 2 chars, 1x",
234                 .in    = "abc",
235                 .front = "",
236                 .back  = "bc",
237                 .out   = "a",
238                 .ret   = true,
239         },
240         {
241                 .desc  = "Trim back, 2 chars, 2x",
242                 .in    = "abcbc",
243                 .front = "",
244                 .back  = "bc",
245                 .out   = "a",
246                 .ret   = true,
247         },
248         {
249                 .desc  = "Trim back, 3 chars, matches all",
250                 .in    = "abc",
251                 .front = "",
252                 .back  = "abc",
253                 .out   = "",
254                 .ret   = true,
255         },
256         {
257                 .desc  = "Trim both, non-matching",
258                 .in    = "abc",
259                 .front = "x",
260                 .back  = "y",
261                 .out   = "abc",
262                 .ret   = false,
263         },
264         {
265                 .desc  = "Trim both, reversed",
266                 .in    = "abc",
267                 .front = "c",
268                 .back  = "a",
269                 .out   = "abc",
270                 .ret   = false,
271         },
272         {
273                 .desc  = "Trim both, 1 char, 1x",
274                 .in    = "abc",
275                 .front = "a",
276                 .back  = "c",
277                 .out   = "b",
278                 .ret   = true,
279         },
280         {
281                 .desc  = "Trim both, 1 char, 2x",
282                 .in    = "aabcc",
283                 .front = "a",
284                 .back  = "c",
285                 .out   = "b",
286                 .ret   = true,
287         },
288         {
289                 .desc  = "Trim both, 1 char, 3x",
290                 .in    = "aaabccc",
291                 .front = "a",
292                 .back  = "c",
293                 .out   = "b",
294                 .ret   = true,
295         },
296         {
297                 .desc  = "Trim both, 1 char, matches all",
298                 .in    = "aaabbb",
299                 .front = "a",
300                 .back  = "b",
301                 .out   = "",
302                 .ret   = true,
303         },
304         {
305                 .desc  = "Trim both, 2 chars, 1x",
306                 .in    = "abxbc",
307                 .front = "ab",
308                 .back  = "bc",
309                 .out   = "x",
310                 .ret   = true,
311         },
312         {
313                 .desc  = "Trim both, 2 chars, 2x",
314                 .in    = "ababxyzbcbc",
315                 .front = "ab",
316                 .back  = "bc",
317                 .out   = "xyz",
318                 .ret   = true,
319         },
320         {
321                 .desc  = "Trim both, 2 chars, front matches, back doesn't",
322                 .in    = "abcde",
323                 .front = "ab",
324                 .back  = "xy",
325                 .out   = "cde",
326                 .ret   = true,
327         },
328         {
329                 .desc  = "Trim both, 2 chars, back matches, front doesn't",
330                 .in    = "abcde",
331                 .front = "xy",
332                 .back  = "de",
333                 .out   = "abc",
334                 .ret   = true,
335         },
336         {
337                 .desc  = "Trim back, 3 chars, matches all",
338                 .in    = "abcxyz",
339                 .front = "abc",
340                 .back  = "xyz",
341                 .out   = "",
342                 .ret   = true,
343         },
344 };
345
346 static bool test_trim_string(struct torture_context *tctx)
347 {
348         int j;
349         for (j = 0; j < ARRAY_SIZE(test_trim_string_data); j++) {
350                 bool ret;
351                 const struct test_trim_string_data *d =
352                         &test_trim_string_data[j];
353                 char *str = talloc_strdup(tctx, d->in);
354                 torture_assert(tctx, d->in == NULL || str != NULL,
355                                "Out of memory");
356
357                 torture_comment(tctx, "%s\n", d->desc);
358                 ret = trim_string(str, d->front, d->back);
359                 torture_assert(tctx, ret == d->ret,
360                                "Incorrect return from trim_string()");
361                 if (d->out == NULL) {
362                         torture_assert(tctx, str == NULL, "Expected NULL");
363                 } else {
364                         torture_assert(tctx, str != NULL, "Expected non-NULL");
365                         torture_assert_str_equal(tctx, str, d->out,
366                                                  "Incorrect output");
367                 }
368                 TALLOC_FREE(str);
369         }
370
371         return true;
372 }
373
374 static bool test_directory_create_or_exist(struct torture_context *tctx)
375 {
376         char *path = NULL, *new_path = NULL, *file_path = NULL;
377         bool ret = true, b = true;
378         int fd;
379         NTSTATUS status;
380         const mode_t perms = 0741;
381
382         status = torture_temp_dir(tctx, "util_dir", &path);;
383         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
384                                         "Creating test directory failed.\n");
385
386         b = directory_create_or_exist(path, perms);
387         torture_assert_goto(tctx, b == true, ret, done,
388                             "directory_create_or_exist on "
389                             "existing directory failed.\n");
390
391         new_path = talloc_asprintf(tctx, "%s/%s", path, "dir");
392         torture_assert_goto(tctx, new_path != NULL, ret, done,
393                             "Could not allocate memory for directory path\n");
394
395         b = directory_exist(new_path);
396         torture_assert_goto(tctx, b == false, ret, done,
397                             "Check for non-existing directory failed.\n");
398
399         b = directory_create_or_exist(new_path, perms);
400         torture_assert_goto(tctx, b == true, ret, done,
401                             "directory_create_or_exist for "
402                             "new directory failed.\n");
403
404         b = directory_exist(new_path);
405         torture_assert_goto(tctx, b == true, ret, done,
406                             "Check for existing directory failed.\n");
407
408         b = file_check_permissions(new_path, geteuid(), perms, NULL);
409         torture_assert_goto(tctx, b == true, ret, done,
410                             "Permission check for directory failed.\n");
411
412         file_path = talloc_asprintf(tctx, "%s/%s", path, "file");
413         torture_assert_goto(tctx, file_path != NULL, ret, done,
414                             "Could not allocate memory for file path\n");
415         fd = creat(file_path, perms);
416         torture_assert_goto(tctx, fd != -1, ret, done,
417                             "Creating file failed.\n");
418         close(fd);
419
420         b = directory_create_or_exist(file_path, perms);
421         torture_assert_goto(tctx, b == false, ret, done,
422                             "directory_create_or_exist for "
423                             "existing file failed.\n");
424
425 done:
426         return ret;
427 }
428
429 static bool test_smb_strtoul_errno_check(struct torture_context *tctx)
430 {
431         const char *number = "123";
432         unsigned long int val = 0;
433         unsigned long long int vall = 0;
434         int err;
435
436         /* select an error code which is not set by the smb_strtoul routines */
437         errno = EAGAIN;
438         err = EAGAIN;
439         val = smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
440         torture_assert(tctx, errno == EAGAIN, "smb_strtoul: Expected EAGAIN");
441         torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0");
442         torture_assert(tctx, val == 123, "smb_strtoul: Expected value 123");
443
444         /* set err to an impossible value again before continuing */
445         err = EAGAIN;
446         vall = smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
447         torture_assert(tctx, errno == EAGAIN, "smb_strtoull: Expected EAGAIN");
448         torture_assert(tctx, err == 0, "smb_strtoul: Expected err = 0");
449         torture_assert(tctx, vall == 123, "smb_strtoul: Expected value 123");
450
451         return true;
452 }
453
454 static bool test_smb_strtoul_negative(struct torture_context *tctx)
455 {
456         const char *number = "-132";
457         const char *number2 = "132-";
458         unsigned long int val = 0;
459         unsigned long long int vall = 0;
460         int err;
461
462         err = 0;
463         smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
464         torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
465
466         err = 0;
467         smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
468         torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
469
470         /* it is allowed to have a "-" sign after a number,
471          * e.g. as part of a formular, however, it is not supposed to
472          * have an effect on the converted value.
473          */
474
475         err = 0;
476         val = smb_strtoul(number2, NULL, 0, &err, SMB_STR_STANDARD);
477         torture_assert(tctx, err == 0, "smb_strtoul: Expected no error");
478         torture_assert(tctx, val == 132, "smb_strtoul: Wrong value");
479
480         err = 0;
481         vall = smb_strtoull(number2, NULL, 0, &err, SMB_STR_STANDARD);
482         torture_assert(tctx, err == 0, "smb_strtoull: Expected no error");
483         torture_assert(tctx, vall == 132, "smb_strtoull: Wrong value");
484
485         return true;
486 }
487
488 static bool test_smb_strtoul_no_number(struct torture_context *tctx)
489 {
490         const char *number = "ghijk";
491         const char *blank = "";
492         int err;
493
494         err = 0;
495         smb_strtoul(number, NULL, 0, &err, SMB_STR_STANDARD);
496         torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
497
498         err = 0;
499         smb_strtoull(number, NULL, 0, &err, SMB_STR_STANDARD);
500         torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
501
502         err = 0;
503         smb_strtoul(blank, NULL, 0, &err, SMB_STR_STANDARD);
504         torture_assert(tctx, err == EINVAL, "smb_strtoul: Expected EINVAL");
505
506         err = 0;
507         smb_strtoull(blank, NULL, 0, &err, SMB_STR_STANDARD);
508         torture_assert(tctx, err == EINVAL, "smb_strtoull: Expected EINVAL");
509
510         return true;
511 }
512
513 static bool test_smb_strtoul_allow_negative(struct torture_context *tctx)
514 {
515         const char *number = "-1";
516         const char *number2 = "-1-1";
517         unsigned long res = 0;
518         unsigned long long res2 = 0;
519         char *end_ptr = NULL;
520         int err;
521
522         err = 0;
523         res = smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE);
524         torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
525         torture_assert(tctx, res == ULONG_MAX, "strtoul_err: Unexpected value");
526
527         err = 0;
528         res2 = smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NEGATIVE);
529         torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
530         torture_assert(tctx, res2 == ULLONG_MAX, "strtoull_err: Unexpected value");
531
532         err = 0;
533         smb_strtoul(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE);
534         torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
535         torture_assert(tctx, end_ptr[0] == '-', "strtoul_err: Unexpected end pointer");
536
537         err = 0;
538         smb_strtoull(number2, &end_ptr, 0, &err, SMB_STR_ALLOW_NEGATIVE);
539         torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
540         torture_assert(tctx, end_ptr[0] == '-', "strtoull_err: Unexpected end pointer");
541
542         return true;
543 }
544
545 static bool test_smb_strtoul_full_string(struct torture_context *tctx)
546 {
547         const char *number = "123 ";
548         const char *number2 = "123";
549         int err;
550
551         err = 0;
552         smb_strtoul(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
553         torture_assert(tctx, err == EINVAL, "strtoul_err: Expected EINVAL");
554
555         err = 0;
556         smb_strtoull(number, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
557         torture_assert(tctx, err == EINVAL, "strtoull_err: Expected EINVAL");
558
559         err = 0;
560         smb_strtoul(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
561         torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
562
563         err = 0;
564         smb_strtoull(number2, NULL, 0, &err, SMB_STR_FULL_STR_CONV);
565         torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
566
567         return true;
568 }
569
570 static bool test_smb_strtoul_allow_no_conversion(struct torture_context *tctx)
571 {
572         const char *number = "";
573         const char *number2 = "xyz";
574         unsigned long int n1 = 0;
575         unsigned long long int n2 = 0;
576         int err;
577
578         err = 0;
579         smb_strtoul(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
580         torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
581         torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value");
582
583         err = 0;
584         smb_strtoull(number, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
585         torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
586         torture_assert(tctx, n2 == 0, "strtoull_err: Unexpected value");
587
588         err = 0;
589         smb_strtoul(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
590         torture_assert(tctx, err == 0, "strtoul_err: Unexpected error");
591         torture_assert(tctx, n1 == 0, "strtoul_err: Unexpected value");
592
593         err = 0;
594         smb_strtoull(number2, NULL, 0, &err, SMB_STR_ALLOW_NO_CONVERSION);
595         torture_assert(tctx, err == 0, "strtoull_err: Unexpected error");
596         torture_assert(tctx, n2 == 0, "strtoull_err: Unexpected value");
597
598         return true;
599 }
600 struct torture_suite *torture_local_util(TALLOC_CTX *mem_ctx)
601 {
602         struct torture_suite *suite =
603                 torture_suite_create(mem_ctx, "util");
604
605         torture_suite_add_simple_test(suite,
606                                       "trim_string",
607                                       test_trim_string);
608         torture_suite_add_simple_test(suite,
609                                       "directory_create_or_exist",
610                                       test_directory_create_or_exist);
611         torture_suite_add_simple_test(suite,
612                                       "smb_strtoul(l) errno",
613                                       test_smb_strtoul_errno_check);
614         torture_suite_add_simple_test(suite,
615                                       "smb_strtoul(l) negative",
616                                       test_smb_strtoul_negative);
617         torture_suite_add_simple_test(suite,
618                                       "smb_strtoul(l) no number",
619                                       test_smb_strtoul_no_number);
620         torture_suite_add_simple_test(suite,
621                                       "smb_strtoul(l) allow_negative",
622                                       test_smb_strtoul_allow_negative);
623         torture_suite_add_simple_test(suite,
624                                       "smb_strtoul(l) full string conversion",
625                                       test_smb_strtoul_full_string);
626         torture_suite_add_simple_test(suite,
627                                       "smb_strtoul(l) allow no conversion",
628                                       test_smb_strtoul_allow_no_conversion);
629         return suite;
630 }