1 /*
2  * ProFTPD - FTP server testsuite
3  * Copyright (c) 2008-2017 The ProFTPD Project team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18  *
19  * As a special exemption, The ProFTPD Project team and other respective
20  * copyright holders give permission to link this program with OpenSSL, and
21  * distribute the resulting executable, without including the source code for
22  * OpenSSL in the source distribution.
23  */
24 
25 /* String API tests. */
26 
27 #include "tests.h"
28 
29 static pool *p = NULL;
30 
set_up(void)31 static void set_up(void) {
32   if (p == NULL) {
33     p = make_sub_pool(NULL);
34   }
35 }
36 
tear_down(void)37 static void tear_down(void) {
38   if (p) {
39     destroy_pool(p);
40     p = NULL;
41   }
42 }
43 
START_TEST(sstrncpy_test)44 START_TEST (sstrncpy_test) {
45   char *ok, *dst;
46   size_t len, sz = 32;
47   int res;
48 
49   len = 0;
50   res = sstrncpy(NULL, NULL, len);
51   fail_unless(res == -1, "Failed to handle null arguments");
52 
53   dst = "";
54   res = sstrncpy(dst, "foo", 0);
55   fail_unless(res == 0, "Failed to handle zero length");
56 
57   dst = pcalloc(p, sz);
58   memset(dst, 'A', sz);
59 
60   len = 1;
61   res = sstrncpy(dst, NULL, len);
62   fail_unless(res == -1, "Failed to handle null arguments");
63 
64   ok = "Therefore, all progress depends on the unreasonable man";
65 
66   mark_point();
67   res = sstrncpy(ok, ok, 1);
68   fail_unless(res == 1, "Expected result 1, got %d", len, res);
69 
70   mark_point();
71   memset(dst, 'A', sz);
72   len = 1;
73 
74   res = sstrncpy(dst, ok, len);
75   fail_unless((size_t) res <= len, "Expected result %d, got %d", len, res);
76   fail_unless(strlen(dst) == (len - 1), "Expected len %u, got len %u", len - 1,
77     strlen(dst));
78   fail_unless(dst[len-1] == '\0', "Expected NUL, got '%c'", dst[len-1]);
79 
80   memset(dst, 'A', sz);
81   len = 7;
82 
83   res = sstrncpy(dst, ok, len);
84   fail_unless((size_t) res <= len, "Expected result %d, got %d", len, res);
85   fail_unless(strlen(dst) == (len - 1), "Expected len %u, got len %u", len - 1,
86     strlen(dst));
87   fail_unless(dst[len-1] == '\0', "Expected NUL, got '%c'", dst[len-1]);
88 
89   memset(dst, 'A', sz);
90   len = sz;
91 
92   res = sstrncpy(dst, ok, len);
93   fail_unless((size_t) res <= len, "Expected result %d, got %d", len, res);
94   fail_unless(strlen(dst) == (len - 1), "Expected len %u, got len %u", len - 1,
95     strlen(dst));
96   fail_unless(dst[len-1] == '\0', "Expected NUL, got '%c'", dst[len-1]);
97 
98   memset(dst, 'A', sz);
99   len = sz;
100 
101   res = sstrncpy(dst, "", len);
102   fail_unless((size_t) res <= len, "Expected result %d, got %d", len, res);
103   fail_unless(strlen(dst) == 0, "Expected len %u, got len %u", 0, strlen(dst));
104   fail_unless(*dst == '\0', "Expected NUL, got '%c'", *dst);
105 }
106 END_TEST
107 
START_TEST(sstrcat_test)108 START_TEST (sstrcat_test) {
109   register unsigned int i;
110   char c = 'A', src[1024], dst[1024], *res;
111 
112   res = sstrcat(dst, src, 0);
113   fail_unless(res == NULL, "Non-null result for zero-length strcat");
114 
115   src[0] = 'f';
116   src[1] = '\0';
117   dst[0] = 'e';
118   dst[1] = '\0';
119   res = sstrcat(dst, src, 1);
120   fail_unless(res == dst, "Returned wrong destination buffer");
121 
122   /* In this case, we told sstrcat() that dst is len 1, which means that
123    * sstrcat() should set dst[0] to NUL.
124    */
125   fail_unless(dst[0] == 0, "Failed to terminate destination buffer");
126 
127   src[0] = 'f';
128   src[1] = '\0';
129   dst[0] = 'e';
130   dst[1] = '\0';
131   res = sstrcat(dst, src, 2);
132   fail_unless(res == dst, "Returned wrong destination buffer");
133 
134   /* In this case, we told sstrcat() that dst is len 2, which means that
135    * sstrcat() should preserve the value at 0, and set dst[1] to NUL.
136    */
137   fail_unless(dst[0] == 'e',
138     "Failed to preserve destination buffer (expected '%c' at index 0, "
139     "got '%c')", 'e', dst[0]);
140 
141   fail_unless(dst[1] == 0, "Failed to terminate destination buffer");
142 
143   mark_point();
144   src[0] = 'f';
145   src[1] = '\0';
146   dst[0] = 'e';
147   dst[1] = '\0';
148   res = sstrcat(dst, src, 3);
149   fail_unless(res == dst, "Returned wrong destination buffer");
150 
151   mark_point();
152   fail_unless(dst[0] == 'e',
153     "Failed to preserve destination buffer (expected '%c' at index 0, "
154     "got '%c')", 'e', dst[0]);
155 
156   mark_point();
157   fail_unless(dst[1] == 'f',
158     "Failed to copy source buffer (expected '%c' at index 1, got '%c')",
159     'f', dst[1]);
160 
161   mark_point();
162   fail_unless(dst[2] == 0, "Failed to terminate destination buffer");
163 
164   mark_point();
165   memset(src, c, sizeof(src)-1);
166 
167   /* Note: we need to NUL-terminate the source buffer, for e.g. strlcat(3)
168    * implementations.  Failure to do so can yield SIGABRT/SIGSEGV problems
169    * during e.g. unit tests.
170    */
171   src[sizeof(src)-1] = '\0';
172   dst[0] = '\0';
173 
174   mark_point();
175   res = sstrcat(dst, src, sizeof(dst));
176 
177   mark_point();
178   fail_unless(res == dst, "Returned wrong destination buffer");
179 
180   mark_point();
181   fail_unless(dst[sizeof(dst)-1] == 0,
182     "Failed to terminate destination buffer");
183 
184   mark_point();
185   fail_unless(strlen(dst) == (sizeof(dst)-1),
186     "Failed to copy all the data (expected len %u, got len %u)",
187     sizeof(dst)-1, strlen(dst));
188 
189   mark_point();
190   for (i = 0; i < sizeof(dst)-1; i++) {
191     fail_unless(dst[i] == c, "Copied wrong value (expected '%c', got '%c')",
192       c, dst[i]);
193   }
194 }
195 END_TEST
196 
START_TEST(sreplace_test)197 START_TEST (sreplace_test) {
198   const char *res;
199   char *fmt = NULL, *ok;
200 
201   res = sreplace(NULL, NULL, 0);
202   fail_unless(res == NULL, "Failed to handle invalid arguments");
203   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
204 
205   res = sreplace(NULL, "", 0);
206   fail_unless(res == NULL, "Failed to handle invalid arguments");
207   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
208 
209   res = sreplace(p, NULL, 0);
210   fail_unless(res == NULL, "Failed to handle invalid arguments");
211   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
212 
213   fmt = "%a";
214   res = sreplace(p, fmt, "foo", NULL);
215   fail_unless(strcmp(res, fmt) == 0, "Expected '%s', got '%s'", fmt, res);
216 
217   fmt = "foo %a";
218   res = sreplace(p, fmt, "%b", NULL);
219   fail_unless(strcmp(res, fmt) == 0, "Expected '%s', got '%s'", fmt, res);
220 
221   fmt = "foo %a";
222   ok = "foo bar";
223   res = sreplace(p, fmt, "%a", "bar", NULL);
224   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
225 
226   fmt = "foo %a %a";
227   ok = "foo bar bar";
228   res = sreplace(p, fmt, "%a", "bar", NULL);
229   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
230 
231   fmt = "foo %a %a %a %a %a %a %a %a";
232   ok = "foo bar bar bar bar bar bar bar bar";
233   res = sreplace(p, fmt, "%a", "bar", NULL);
234   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
235 
236   /* sreplace() will not handle more than 8 occurrences of the same escape
237    * sequence in the same line.  Make sure this happens.
238    */
239   fmt = "foo %a %a %a %a %a %a %a %a %a";
240   ok = "foo bar bar bar bar bar bar bar bar bar";
241   res = sreplace(p, fmt, "%a", "bar", NULL);
242   fail_unless(strcmp(res, fmt) == 0, "Expected '%s', got '%s'", fmt, res);
243 }
244 END_TEST
245 
START_TEST(sreplace_enospc_test)246 START_TEST (sreplace_enospc_test) {
247   const char *res;
248   char *fmt = NULL;
249   size_t bufsz = 8192;
250 
251   fmt = palloc(p, bufsz + 1);
252   memset(fmt, ' ', bufsz);
253   fmt[bufsz-2] = '%';
254   fmt[bufsz-1] = 'a';
255   fmt[bufsz] = '\0';
256 
257   res = sreplace(p, fmt, "%a", "foo", NULL);
258   fail_unless(res == NULL, "Failed to reject too-long buffer");
259   fail_unless(errno == ENOSPC, "Failed to set errno to ENOSPC");
260 }
261 END_TEST
262 
START_TEST(sreplace_bug3614_test)263 START_TEST (sreplace_bug3614_test) {
264   const char *res;
265   char *fmt = NULL, *ok;
266 
267   fmt = "%a %b %c %d %e %f %g %h %i %j %k %l %m "
268         "%n %o %p %q %r %s %t %u %v %w %x %y %z "
269         "%A %B %C %D %E %F %G %H %I %J %K %L %M "
270         "%N %O %P %Q %R %S %T %U %V %W %X %Y %Z "
271         "%0 %1 %2 %3 %4 %5 %6 %7 %8 %9 "
272         "%{a} %{b} %{c} %{d} %{e} %{f} %{g} %{h} %{i} %{j} %{k} %{l} %{m} "
273         "%{n} %{o} %{p} %{q} %{r} %{s} %{t} %{u} %{v} %{w} %{x} %{y} %{z} "
274         "%{A} %{B} %{C} %{D} %{E} %{F} %{G} %{H} %{I} %{J} %{K} %{L} %{M} "
275         "%{N} %{O} %{P} %{Q} %{R} %{S} %{T} %{U} %{V} %{W} %{X} %{Y} %{Z} "
276         "%{aa} %{bb} %{cc} %{dd} %{ee} %{ff} %{gg} %{hh} %{ii} %{jj} "
277         "%{kk} %{ll} %{mm} %{nn} %{oo} %{pp} %{qq} %{rr} %{ss} %{tt} "
278         "%{uu} %{vv} %{ww} %{xx} %{yy} %{zz}";
279 
280   /* We put a limit on the maximum number of replacements that sreplace()
281    * will perform on a given string, per Bug#3614.
282    */
283   ok = "bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar %{oo} %{pp} %{qq} %{rr} %{ss} %{tt} %{uu} %{vv} %{ww} %{xx} %{yy} %{zz}";
284 
285   res = sreplace(p, fmt,
286     "%a", "bar", "%b", "bar", "%c", "bar", "%d", "bar", "%e", "bar",
287     "%f", "bar", "%g", "bar", "%h", "bar", "%i", "bar", "%j", "bar",
288     "%k", "bar", "%l", "bar", "%m", "bar", "%n", "bar", "%o", "bar",
289     "%p", "bar", "%q", "bar", "%r", "bar", "%s", "bar", "%t", "bar",
290     "%u", "bar", "%v", "bar", "%w", "bar", "%x", "bar", "%y", "bar",
291     "%z", "bar",
292     "%A", "bar", "%B", "bar", "%C", "bar", "%D", "bar", "%E", "bar",
293     "%F", "bar", "%G", "bar", "%H", "bar", "%I", "bar", "%J", "bar",
294     "%K", "bar", "%L", "bar", "%M", "bar", "%N", "bar", "%O", "bar",
295     "%P", "bar", "%Q", "bar", "%R", "bar", "%S", "bar", "%T", "bar",
296     "%U", "bar", "%V", "bar", "%W", "bar", "%X", "bar", "%Y", "bar",
297     "%Z", "bar",
298     "%0", "bar", "%1", "bar", "%2", "bar", "%3", "bar", "%4", "bar",
299     "%5", "bar", "%6", "bar", "%7", "bar", "%8", "bar", "%9", "bar",
300     "%{a}", "bar", "%{b}", "bar", "%{c}", "bar", "%{d}", "bar", "%{e}", "bar",
301     "%{f}", "bar", "%{g}", "bar", "%{h}", "bar", "%{i}", "bar", "%{j}", "bar",
302     "%{k}", "bar", "%{l}", "bar", "%{m}", "bar", "%{n}", "bar", "%{o}", "bar",
303     "%{p}", "bar", "%{q}", "bar", "%{r}", "bar", "%{s}", "bar", "%{t}", "bar",
304     "%{u}", "bar", "%{v}", "bar", "%{w}", "bar", "%{x}", "bar", "%{y}", "bar",
305     "%{z}", "bar",
306     "%{A}", "bar", "%{B}", "bar", "%{C}", "bar", "%{D}", "bar", "%{E}", "bar",
307     "%{F}", "bar", "%{G}", "bar", "%{H}", "bar", "%{I}", "bar", "%{J}", "bar",
308     "%{K}", "bar", "%{L}", "bar", "%{M}", "bar", "%{N}", "bar", "%{O}", "bar",
309     "%{P}", "bar", "%{Q}", "bar", "%{R}", "bar", "%{S}", "bar", "%{T}", "bar",
310     "%{U}", "bar", "%{V}", "bar", "%{W}", "bar", "%{X}", "bar", "%{Y}", "bar",
311     "%{Z}", "bar",
312     "%{aa}", "bar", "%{bb}", "bar", "%{cc}", "bar", "%{dd}", "bar",
313     "%{ee}", "bar", "%{ff}", "bar", "%{gg}", "bar", "%{hh}", "bar",
314     "%{ii}", "bar", "%{jj}", "bar", "%{kk}", "bar", "%{ll}", "bar",
315     "%{mm}", "bar", "%{nn}", "bar", "%{oo}", "bar", "%{pp}", "bar",
316     "%{qq}", "bar", "%{rr}", "bar", "%{ss}", "bar", "%{tt}", "bar",
317     "%{uu}", "bar", "%{vv}", "bar", "%{ww}", "bar", "%{xx}", "bar",
318     "%{yy}", "bar", "%{zz}", "bar",
319     NULL);
320   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
321 }
322 END_TEST
323 
START_TEST(str_replace_test)324 START_TEST (str_replace_test) {
325   const char *res;
326   char *fmt = NULL, *ok;
327   int max_replace = PR_STR_MAX_REPLACEMENTS;
328 
329   res = pr_str_replace(NULL, max_replace, NULL, 0);
330   fail_unless(res == NULL, "Failed to handle invalid arguments");
331   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
332 
333   res = pr_str_replace(NULL, max_replace, "", 0);
334   fail_unless(res == NULL, "Failed to handle invalid arguments");
335   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
336 
337   res = pr_str_replace(p, max_replace, NULL, 0);
338   fail_unless(res == NULL, "Failed to handle invalid arguments");
339   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
340 
341   fmt = "%a";
342   res = pr_str_replace(p, max_replace, fmt, "foo", NULL);
343   fail_unless(strcmp(res, fmt) == 0, "Expected '%s', got '%s'", fmt, res);
344 
345   fmt = "foo %a";
346   res = pr_str_replace(p, max_replace, fmt, "%b", NULL);
347   fail_unless(strcmp(res, fmt) == 0, "Expected '%s', got '%s'", fmt, res);
348 
349   fmt = "foo %a";
350   ok = "foo bar";
351   res = pr_str_replace(p, max_replace, fmt, "%a", "bar", NULL);
352   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
353 
354   fmt = "foo %a %a";
355   ok = "foo bar bar";
356   res = pr_str_replace(p, max_replace, fmt, "%a", "bar", NULL);
357   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
358 
359   fmt = "foo %a %a %a %a %a %a %a %a";
360   ok = "foo bar bar bar bar bar bar bar bar";
361   res = pr_str_replace(p, max_replace, fmt, "%a", "bar", NULL);
362   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
363 
364   fmt = "foo %a %a %a %a %a %a %a %a %a";
365   ok = "foo bar bar bar bar bar bar bar bar bar";
366   res = pr_str_replace(p, max_replace, fmt, "%a", "bar", NULL);
367   fail_unless(res == NULL, "Failed to handle too many replacements");
368   fail_unless(errno == E2BIG, "Failed to set errno to E2BIG");
369 }
370 END_TEST
371 
START_TEST(pdircat_test)372 START_TEST (pdircat_test) {
373   char *res, *ok;
374 
375   res = pdircat(NULL, 0);
376   fail_unless(res == NULL, "Failed to handle null arguments");
377   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
378 
379   res = pdircat(p, 0);
380   fail_unless(res != NULL,
381     "Failed to handle empty arguments (expected '', got '%s')", res);
382   fail_unless(strcmp(res, "") == 0, "Expected '%s', got '%s'", "", res);
383 
384   /* Comments in the pdircat() function suggest that an empty string
385    * should be treated as a leading slash.  However, that never got
386    * implemented.  Is this a bug, or just an artifact?  I doubt that it
387    * is causing problems at present.
388    */
389   res = pdircat(p, "", NULL);
390   ok = "";
391   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
392 
393   res = pdircat(p, "foo", "bar", NULL);
394   ok = "foo/bar";
395   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
396 
397   res = pdircat(p, "", "foo", "bar", NULL);
398   ok = "foo/bar";
399   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
400 
401   res = pdircat(p, "/", "/foo/", "/bar/", NULL);
402   ok = "/foo/bar/";
403   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
404 
405   /* Sadly, pdircat() only handles single leading/trailing slashes, not
406    * an arbitrary number of leading/trailing slashes.
407    */
408   res = pdircat(p, "//", "//foo//", "//bar//", NULL);
409   ok = "///foo///bar//";
410   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
411 }
412 END_TEST
413 
START_TEST(pstrcat_test)414 START_TEST (pstrcat_test) {
415   char *res, *ok;
416 
417   res = pstrcat(NULL, 0);
418   fail_unless(res == NULL, "Failed to handle null arguments");
419   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
420 
421   res = pstrcat(p, 0);
422   fail_unless(res != NULL,
423     "Failed to handle empty arguments (expected '', got '%s')", res);
424   fail_unless(strcmp(res, "") == 0, "Expected '%s', got '%s'", "", res);
425 
426   res = pstrcat(p, "", NULL);
427   ok = "";
428   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
429 
430   res = pstrcat(p, "foo", "bar", NULL);
431   ok = "foobar";
432   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
433 
434   res = pstrcat(p, "", "foo", "bar", NULL);
435   ok = "foobar";
436   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
437 
438   res = pstrcat(p, "/", "/foo/", "/bar/", NULL);
439   ok = "//foo//bar/";
440   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
441 
442   res = pdircat(p, "//", "//foo//", NULL, "//bar//", NULL);
443   ok = "///foo//";
444   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
445 }
446 END_TEST
447 
START_TEST(pstrdup_test)448 START_TEST (pstrdup_test) {
449   char *res, *ok;
450 
451   res = pstrdup(NULL, NULL);
452   fail_unless(res == NULL, "Failed to handle null arguments");
453   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
454 
455   res = pstrdup(p, NULL);
456   fail_unless(res == NULL, "Failed to handle null arguments");
457   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
458 
459   res = pstrdup(NULL, "");
460   fail_unless(res == NULL, "Failed to handle null arguments");
461   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
462 
463   res = pstrdup(p, "foo");
464   ok = "foo";
465   fail_unless(strlen(res) == strlen(ok), "Expected len %u, got len %u",
466     strlen(ok), strlen(res));
467   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
468 }
469 END_TEST
470 
START_TEST(pstrndup_test)471 START_TEST (pstrndup_test) {
472   char *res, *ok;
473 
474   res = pstrndup(NULL, NULL, 0);
475   fail_unless(res == NULL, "Failed to handle null arguments");
476   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
477 
478   res = pstrndup(p, NULL, 0);
479   fail_unless(res == NULL, "Failed to handle null arguments");
480   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
481 
482   res = pstrndup(NULL, "", 0);
483   fail_unless(res == NULL, "Failed to handle null arguments");
484   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
485 
486   res = pstrndup(p, "foo", 0);
487   ok = "";
488   fail_unless(strlen(res) == strlen(ok), "Expected len %u, got len %u",
489     strlen(ok), strlen(res));
490   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
491 
492   res = pstrndup(p, "foo", 1);
493   ok = "f";
494   fail_unless(strlen(res) == strlen(ok), "Expected len %u, got len %u",
495     strlen(ok), strlen(res));
496   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
497 
498   res = pstrndup(p, "foo", 10);
499   ok = "foo";
500   fail_unless(strlen(res) == strlen(ok), "Expected len %u, got len %u",
501     strlen(ok), strlen(res));
502   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
503 }
504 END_TEST
505 
START_TEST(strip_test)506 START_TEST (strip_test) {
507   const char *ok, *res, *str;
508 
509   res = pr_str_strip(NULL, NULL);
510   fail_unless(res == NULL, "Failed to handle null arguments");
511   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
512 
513   res = pr_str_strip(p, NULL);
514   fail_unless(res == NULL, "Failed to handle null str argument");
515   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
516 
517   res = pr_str_strip(NULL, "foo");
518   fail_unless(res == NULL, "Failed to handle null pool argument");
519   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
520 
521   str = pstrdup(p, "foo");
522   res = pr_str_strip(p, str);
523   fail_unless(res != NULL, "Failed to strip '%s': %s", str, strerror(errno));
524 
525   ok = "foo";
526   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
527 
528   str = pstrdup(p, " \n \t foo");
529   res = pr_str_strip(p, str);
530   fail_unless(res != NULL, "Failed to strip '%s': %s", str, strerror(errno));
531 
532   ok = "foo";
533   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
534 
535   str = pstrdup(p, "foo  \n \t \r");
536   res = pr_str_strip(p, str);
537   fail_unless(res != NULL, "Failed to strip '%s': %s", str, strerror(errno));
538 
539   ok = "foo";
540   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
541 
542   str = pstrdup(p, "\r \n\n\t    foo  \n \t \r");
543   res = pr_str_strip(p, str);
544   fail_unless(res != NULL, "Failed to strip '%s': %s", str, strerror(errno));
545 
546   ok = "foo";
547   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
548 }
549 END_TEST
550 
START_TEST(strip_end_test)551 START_TEST (strip_end_test) {
552   char *ch, *ok, *res, *str;
553 
554   res = pr_str_strip_end(NULL, NULL);
555   fail_unless(res == NULL, "Failed to handle null arguments");
556   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
557 
558   str = pstrdup(p, "foo");
559 
560   res = pr_str_strip_end(str, NULL);
561   fail_unless(res == NULL, "Failed to handle null char argument");
562   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
563 
564   ch = "\r\n";
565 
566   res = pr_str_strip_end(NULL, ch);
567   fail_unless(res == NULL, "Failed to handle null str argument");
568   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
569 
570   res = pr_str_strip_end(str, ch);
571   fail_unless(res != NULL, "Failed to strip '%s' from end of '%s': %s",
572     ch, str, strerror(errno));
573 
574   ok = "foo";
575   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
576 
577   str = pstrdup(p, "foo\r\n");
578   res = pr_str_strip_end(str, ch);
579   fail_unless(res != NULL, "Failed to strip '%s' from end of '%s': %s",
580     ch, str, strerror(errno));
581 
582   ok = "foo";
583   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
584 
585   str = pstrdup(p, "foo\r\n\r\n\r\n");
586   res = pr_str_strip_end(str, ch);
587   fail_unless(res != NULL, "Failed to strip '%s' from end of '%s': %s",
588     ch, str, strerror(errno));
589 
590   ok = "foo";
591   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
592 }
593 END_TEST
594 
START_TEST(get_token_test)595 START_TEST (get_token_test) {
596   char *ok, *res, *str;
597 
598   res = pr_str_get_token(NULL, NULL);
599   fail_unless(res == NULL, "Failed to handle null arguments");
600   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
601 
602   str = NULL;
603   res = pr_str_get_token(&str, NULL);
604   fail_unless(res == NULL, "Failed to handle null str argument");
605   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
606 
607   str = pstrdup(p, "foo,bar,baz");
608   res = pr_str_get_token(&str, NULL);
609   fail_unless(res == NULL, "Failed to handle null sep argument");
610   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
611 
612   res = pr_str_get_token(&str, ",");
613   fail_unless(res != NULL, "Failed to get token from '%s': %s", str,
614     strerror(errno));
615 
616   ok = "foo";
617   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
618 
619   res = pr_str_get_token(&str, ",");
620   fail_unless(res != NULL, "Failed to get token from '%s': %s", str,
621     strerror(errno));
622 
623   ok = "bar";
624   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
625 
626   res = pr_str_get_token(&str, ",");
627   fail_unless(res != NULL, "Failed to get token from '%s': %s", str,
628     strerror(errno));
629 
630   ok = "baz";
631   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
632 
633   res = pr_str_get_token(&str, ",");
634   fail_unless(res == NULL, "Unexpectedly got token '%s'", res);
635 }
636 END_TEST
637 
START_TEST(get_token2_test)638 START_TEST (get_token2_test) {
639   char *ok, *res, *str;
640   size_t len = 0, ok_len;
641 
642   res = pr_str_get_token2(NULL, NULL, NULL);
643   fail_unless(res == NULL, "Failed to handle null arguments");
644   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
645 
646   str = NULL;
647   res = pr_str_get_token2(&str, NULL, NULL);
648   fail_unless(res == NULL, "Failed to handle null str argument");
649   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
650 
651   str = pstrdup(p, "foo,bar,bazz");
652   res = pr_str_get_token2(&str, NULL, NULL);
653   fail_unless(res == NULL, "Failed to handle null sep argument");
654   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
655 
656   res = pr_str_get_token2(&str, ",", &len);
657   fail_unless(res != NULL, "Failed to get token from '%s': %s", str,
658     strerror(errno));
659 
660   ok = "foo";
661   ok_len = 3;
662   fail_unless(len == ok_len, "Expected len %lu, got %lu",
663     (unsigned long) ok_len, (unsigned long) len);
664   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
665 
666   res = pr_str_get_token2(&str, ",", &len);
667   fail_unless(res != NULL, "Failed to get token from '%s': %s", str,
668     strerror(errno));
669 
670   ok = "bar";
671   ok_len = 3;
672   fail_unless(len == ok_len, "Expected len %lu, got %lu",
673     (unsigned long) ok_len, (unsigned long) len);
674   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
675 
676   res = pr_str_get_token2(&str, ",", &len);
677   fail_unless(res != NULL, "Failed to get token from '%s': %s", str,
678     strerror(errno));
679 
680   ok = "bazz";
681   ok_len = 4;
682   fail_unless(len == ok_len, "Expected len %lu, got %lu",
683     (unsigned long) ok_len, (unsigned long) len);
684   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
685 
686   res = pr_str_get_token2(&str, ",", &len);
687 
688   ok_len = 0;
689   fail_unless(len == ok_len, "Expected len %lu, got %lu",
690     (unsigned long) ok_len, (unsigned long) len);
691   fail_unless(res == NULL, "Unexpectedly got token '%s'", res);
692 }
693 END_TEST
694 
START_TEST(get_word_test)695 START_TEST (get_word_test) {
696   char *ok, *res, *str;
697 
698   res = pr_str_get_word(NULL, 0);
699   fail_unless(res == NULL, "Failed to handle null arguments");
700   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
701 
702   str = NULL;
703   res = pr_str_get_word(&str, 0);
704   fail_unless(res == NULL, "Failed to handle null str argument");
705   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
706 
707   str = pstrdup(p, "  ");
708   res = pr_str_get_word(&str, 0);
709   fail_unless(res == NULL, "Failed to handle whitespace argument");
710 
711   str = pstrdup(p, " foo");
712   res = pr_str_get_word(&str, PR_STR_FL_PRESERVE_WHITESPACE);
713   fail_unless(res != NULL, "Failed to handle whitespace argument: %s",
714     strerror(errno));
715 
716   ok = "";
717   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
718 
719   res = pr_str_get_word(&str, PR_STR_FL_PRESERVE_WHITESPACE);
720   fail_unless(res != NULL, "Failed to handle whitespace argument: %s",
721     strerror(errno));
722 
723   ok = "foo";
724   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
725 
726   str = pstrdup(p, "  # foo");
727   res = pr_str_get_word(&str, 0);
728   fail_unless(res == NULL, "Failed to handle commented argument");
729 
730   res = pr_str_get_word(&str, PR_STR_FL_PRESERVE_COMMENTS);
731   fail_unless(res != NULL, "Failed to handle commented argument: %s",
732     strerror(errno));
733 
734   ok = "#";
735   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
736 
737   res = pr_str_get_word(&str, PR_STR_FL_PRESERVE_COMMENTS);
738   fail_unless(res != NULL, "Failed to handle commented argument: %s",
739     strerror(errno));
740 
741   ok = "foo";
742   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
743 
744   /* Test multiple embedded quotes. */
745   str = pstrdup(p, "foo \"bar baz\" qux \"quz norf\"");
746   res = pr_str_get_word(&str, 0);
747   fail_unless(res != NULL, "Failed to handle quoted argument: %s",
748     strerror(errno));
749 
750   ok = "foo";
751   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
752 
753   res = pr_str_get_word(&str, 0);
754   fail_unless(res != NULL, "Failed to handle quoted argument: %s",
755     strerror(errno));
756 
757   ok = "bar baz";
758   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
759 
760   res = pr_str_get_word(&str, 0);
761   fail_unless(res != NULL, "Failed to handle quoted argument: %s",
762     strerror(errno));
763 
764   ok = "qux";
765   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
766 
767   res = pr_str_get_word(&str, 0);
768   fail_unless(res != NULL, "Failed to handle quoted argument: %s",
769     strerror(errno));
770 
771   ok = "quz norf";
772   fail_unless(strcmp(res, ok) == 0, "Expected '%s', got '%s'", ok, res);
773 }
774 END_TEST
775 
START_TEST(get_word_utf8_test)776 START_TEST (get_word_utf8_test) {
777   const char *path;
778   FILE *fh;
779 
780   /* Test UT8 spaces. Note that in order to do this, I had to use
781    * some other tool (Perl) to emit the desired UTF8 characters to
782    * a file; we then read in the bytes to parse from that file.  Some
783    * compilers (e.g. gcc), in conjunction with the terminal/editor I'm
784    * using, don't like using the '\uNNNN' syntax for encoding UTF8 in C
785    * source code.
786    */
787 
788   path = "api/etc/str/utf8-space.txt";
789   fh = fopen(path, "r");
790   if (fh != NULL) {
791     char *ok, *res, *str;
792     size_t nread = 0, sz;
793 
794     sz = 256;
795     str = pcalloc(p, sz);
796 
797     nread = fread(str, sizeof(char), sz-1, fh);
798     fail_if(ferror(fh), "Error reading '%s': %s", path, strerror(errno));
799     fail_unless(nread > 0, "Expected >0 bytes read, got 0");
800 
801     res = pr_str_get_word(&str, 0);
802       fail_unless(res != NULL, "Failed to handle UTF8 argument: %s",
803       strerror(errno));
804 
805     ok = "foo";
806     fail_if(strcmp(res, ok) == 0, "Did NOT expect '%s'", ok);
807 
808     fclose(fh);
809   }
810 }
811 END_TEST
812 
START_TEST(is_boolean_test)813 START_TEST (is_boolean_test) {
814   int res;
815 
816   res = pr_str_is_boolean(NULL);
817   fail_unless(res == -1, "Failed to handle null argument");
818   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
819     errno);
820 
821   res = pr_str_is_boolean("on");
822   fail_unless(res == TRUE, "Expected TRUE, got FALSE");
823 
824   res = pr_str_is_boolean("Yes");
825   fail_unless(res == TRUE, "Expected TRUE, got FALSE");
826 
827   res = pr_str_is_boolean("TrUe");
828   fail_unless(res == TRUE, "Expected TRUE, got FALSE");
829 
830   res = pr_str_is_boolean("1");
831   fail_unless(res == TRUE, "Expected TRUE, got FALSE");
832 
833   res = pr_str_is_boolean("oFF");
834   fail_unless(res == FALSE, "Expected FALSE, got TRUE");
835 
836   res = pr_str_is_boolean("no");
837   fail_unless(res == FALSE, "Expected FALSE, got TRUE");
838 
839   res = pr_str_is_boolean("false");
840   fail_unless(res == FALSE, "Expected FALSE, got TRUE");
841 
842   res = pr_str_is_boolean("0");
843   fail_unless(res == FALSE, "Expected FALSE, got TRUE");
844 
845   res = pr_str_is_boolean("foo");
846   fail_unless(res == -1, "Failed to handle null argument");
847   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
848     errno);
849 }
850 END_TEST
851 
START_TEST(is_fnmatch_test)852 START_TEST (is_fnmatch_test) {
853   int res;
854   char *str;
855 
856   res = pr_str_is_fnmatch(NULL);
857   fail_unless(res == FALSE, "Expected false for NULL");
858 
859   str = "foo";
860   res = pr_str_is_fnmatch(str);
861   fail_if(res != FALSE, "Expected false for string '%s'", str);
862 
863   str = "foo?";
864   res = pr_str_is_fnmatch(str);
865   fail_if(res != TRUE, "Expected true for string '%s'", str);
866 
867   str = "foo*";
868   res = pr_str_is_fnmatch(str);
869   fail_if(res != TRUE, "Expected true for string '%s'", str);
870 
871   str = "foo[";
872   res = pr_str_is_fnmatch(str);
873   fail_if(res != FALSE, "Expected false for string '%s'", str);
874 
875   str = "foo]";
876   res = pr_str_is_fnmatch(str);
877   fail_if(res != FALSE, "Expected false for string '%s'", str);
878 
879   str = "foo[]";
880   res = pr_str_is_fnmatch(str);
881   fail_if(res != TRUE, "Expected true for string '%s'", str);
882 
883   /* Now the fun cases using the escape character. */
884 
885   str = "f\\oo";
886   res = pr_str_is_fnmatch(str);
887   fail_if(res != FALSE, "Expected false for string '%s'", str);
888 
889   str = "foo\\";
890   res = pr_str_is_fnmatch(str);
891   fail_if(res != FALSE, "Expected false for string '%s'", str);
892 
893   str = "foo\\?";
894   res = pr_str_is_fnmatch(str);
895   fail_if(res != FALSE, "Expected false for string '%s'", str);
896 
897   str = "foo\\??";
898   res = pr_str_is_fnmatch(str);
899   fail_if(res != TRUE, "Expected true for string '%s'", str);
900 }
901 END_TEST
902 
START_TEST(get_nbytes_test)903 START_TEST (get_nbytes_test) {
904   char *str, *units;
905   off_t nbytes;
906   int res;
907 
908   res = pr_str_get_nbytes(NULL, NULL, NULL);
909   fail_unless(res == -1, "Failed to handle null arguments");
910   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
911 
912   str = NULL;
913   res = pr_str_get_nbytes(str, NULL, NULL);
914   fail_unless(res == -1, "Failed to handle null str argument");
915   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
916 
917   str = "1";
918   units = "f";
919   res = pr_str_get_nbytes(str, units, NULL);
920   fail_unless(res == -1, "Failed to handle bad suffix argument");
921   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
922 
923   str = "a";
924   units = "";
925   res = pr_str_get_nbytes(str, units, NULL);
926   fail_unless(res == -1, "Failed to handle invalid str argument");
927   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
928 
929   str = "1 1";
930   units = "";
931   res = pr_str_get_nbytes(str, units, NULL);
932   fail_unless(res == -1, "Failed to handle invalid str argument");
933   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
934 
935   str = "1.1";
936   units = "";
937   res = pr_str_get_nbytes(str, units, NULL);
938   fail_unless(res == -1, "Failed to handle invalid str argument");
939   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
940 
941   str = "-1";
942   units = "";
943   res = pr_str_get_nbytes(str, units, NULL);
944   fail_unless(res == -1, "Failed to handle invalid str argument");
945   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
946 
947   /* XXX Test good suffix: B, KB, MB, GB, TB */
948 
949   str = "1";
950   units = "";
951   res = pr_str_get_nbytes(str, units, &nbytes);
952   fail_unless(res == 0, "Expected result 0, got %d: %s", res, strerror(errno));
953   fail_unless(nbytes == 1, "Expected nbytes = 1, got %" PR_LU,
954     (pr_off_t) nbytes);
955 
956   str = "1";
957   units = "B";
958   res = pr_str_get_nbytes(str, units, &nbytes);
959   fail_unless(res == 0, "Expected result 0, got %d: %s", res, strerror(errno));
960   fail_unless(nbytes == 1,
961     "Expected nbytes = 1, got %" PR_LU, (pr_off_t) nbytes);
962 
963   str = "1";
964   units = "KB";
965   res = pr_str_get_nbytes(str, units, &nbytes);
966   fail_unless(res == 0, "Expected result 0, got %d: %s", res, strerror(errno));
967   fail_unless(nbytes == 1024UL,
968     "Expected nbytes = 1024, got %" PR_LU, (pr_off_t) nbytes);
969 
970   str = "1";
971   units = "MB";
972   res = pr_str_get_nbytes(str, units, &nbytes);
973   fail_unless(res == 0, "Expected result 0, got %d: %s", res, strerror(errno));
974   fail_unless(nbytes == 1048576UL,
975     "Expected nbytes = 1048576, got %" PR_LU, (pr_off_t) nbytes);
976 
977   str = "1";
978   units = "GB";
979   res = pr_str_get_nbytes(str, units, &nbytes);
980   fail_unless(res == 0, "Expected result 0, got %d: %s", res, strerror(errno));
981   fail_unless(nbytes == 1073741824UL,
982     "Expected nbytes = 1073741824, got %" PR_LU, (pr_off_t) nbytes);
983 
984   str = "1";
985   units = "TB";
986   res = pr_str_get_nbytes(str, units, &nbytes);
987   fail_unless(res == 0, "Expected result 0, got %d: %s", res, strerror(errno));
988   fail_unless(nbytes == 1099511627776UL,
989     "Expected nbytes = 1099511627776, got %" PR_LU, (pr_off_t) nbytes);
990 
991   /* This should definitely trigger the ERANGE error. */
992   str = "1099511627776";
993   units = "TB";
994   res = pr_str_get_nbytes(str, units, &nbytes);
995   fail_unless(res == -1, "Expected ERANGE failure, succeeded unexpectedly");
996   fail_unless(errno == ERANGE, "Expected %s [%d], got %s [%d]",
997     strerror(ERANGE), ERANGE, strerror(errno), errno);
998 }
999 END_TEST
1000 
START_TEST(get_duration_test)1001 START_TEST (get_duration_test) {
1002   char *str;
1003   int duration, expected;
1004   int res;
1005 
1006   res = pr_str_get_duration(NULL, NULL);
1007   fail_unless(res == -1, "Failed to handle null arguments");
1008   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1009 
1010   str = "";
1011   res = pr_str_get_duration(str, NULL);
1012   fail_unless(res == -1,
1013     "Failed to handle badly formatted string '%s'", str);
1014   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1015 
1016   str = "-1:-1:-1";
1017   res = pr_str_get_duration(str, NULL);
1018   fail_unless(res == -1,
1019     "Failed to handle badly formatted string '%s'", str);
1020   fail_unless(errno == ERANGE, "Failed to set errno to ERANGE");
1021 
1022   str = "a:b:c";
1023   res = pr_str_get_duration(str, NULL);
1024   fail_unless(res == -1,
1025     "Failed to handle badly formatted string '%s'", str);
1026   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1027 
1028   str = "111:222:333";
1029   res = pr_str_get_duration(str, NULL);
1030   fail_unless(res == -1,
1031     "Failed to handle badly formatted string '%s'", str);
1032   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1033 
1034   /* Test well-formatted hh::mm::ss strings. */
1035 
1036   str = "00:00:00";
1037   expected = 0;
1038   res = pr_str_get_duration(str, &duration);
1039   fail_unless(res == 0,
1040     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1041   fail_unless(duration == expected,
1042     "Expected duration %d secs, got %d", expected, duration);
1043 
1044   str = "01:02:03";
1045   expected = 3723;
1046   res = pr_str_get_duration(str, &duration);
1047   fail_unless(res == 0,
1048     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1049   fail_unless(duration == expected,
1050     "Expected duration %d secs, got %d", expected, duration);
1051 
1052   str = "99:99:99";
1053   expected = 362439;
1054   res = pr_str_get_duration(str, &duration);
1055   fail_unless(res == 0,
1056     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1057   fail_unless(duration == expected,
1058     "Expected duration %d secs, got %d", expected, duration);
1059 
1060   /* Test bad suffixes: -1h, -1hr, 9999foo, etc */
1061 
1062   str = "-1h";
1063   res = pr_str_get_duration(str, NULL);
1064   fail_unless(res == -1,
1065     "Failed to handle badly formatted suffix string '%s'", str);
1066   fail_unless(errno == ERANGE, "Failed to set errno to ERANGE");
1067 
1068   str = "-1hr";
1069   res = pr_str_get_duration(str, NULL);
1070   fail_unless(res == -1,
1071     "Failed to handle badly formatted suffix string '%s'", str);
1072   fail_unless(errno == ERANGE, "Failed to set errno to ERANGE");
1073 
1074   str = "99foo";
1075   res = pr_str_get_duration(str, NULL);
1076   fail_unless(res == -1,
1077     "Failed to handle badly formatted suffix string '%s'", str);
1078   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1079 
1080   str = "foo";
1081   res = pr_str_get_duration(str, NULL);
1082   fail_unless(res == -1,
1083     "Failed to handle badly formatted suffix string '%s'", str);
1084   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1085 
1086   /* Test good suffices: "H"/"h"/"hr", "M"/"m"/"min", "S"/"s"/"sec" */
1087 
1088   str = "76H";
1089   expected = 273600;
1090   res = pr_str_get_duration(str, &duration);
1091   fail_unless(res == 0,
1092     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1093   fail_unless(duration == expected,
1094     "Expected duration %d secs, got %d", expected, duration);
1095 
1096   str = "76h";
1097   expected = 273600;
1098   res = pr_str_get_duration(str, &duration);
1099   fail_unless(res == 0,
1100     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1101   fail_unless(duration == expected,
1102     "Expected duration %d secs, got %d", expected, duration);
1103 
1104   str = "76Hr";
1105   expected = 273600;
1106   res = pr_str_get_duration(str, &duration);
1107   fail_unless(res == 0,
1108     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1109   fail_unless(duration == expected,
1110     "Expected duration %d secs, got %d", expected, duration);
1111 
1112   str = "888M";
1113   expected = 53280;
1114   res = pr_str_get_duration(str, &duration);
1115   fail_unless(res == 0,
1116     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1117   fail_unless(duration == expected,
1118     "Expected duration %d secs, got %d", expected, duration);
1119 
1120   str = "888m";
1121   expected = 53280;
1122   res = pr_str_get_duration(str, &duration);
1123   fail_unless(res == 0,
1124     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1125   fail_unless(duration == expected,
1126     "Expected duration %d secs, got %d", expected, duration);
1127 
1128   str = "888MiN";
1129   expected = 53280;
1130   res = pr_str_get_duration(str, &duration);
1131   fail_unless(res == 0,
1132     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1133   fail_unless(duration == expected,
1134     "Expected duration %d secs, got %d", expected, duration);
1135 
1136   str = "999S";
1137   expected = 999;
1138   res = pr_str_get_duration(str, &duration);
1139   fail_unless(res == 0,
1140     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1141   fail_unless(duration == expected,
1142     "Expected duration %d secs, got %d", expected, duration);
1143 
1144   str = "999s";
1145   expected = 999;
1146   res = pr_str_get_duration(str, &duration);
1147   fail_unless(res == 0,
1148     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1149   fail_unless(duration == expected,
1150     "Expected duration %d secs, got %d", expected, duration);
1151 
1152   str = "999sEc";
1153   expected = 999;
1154   res = pr_str_get_duration(str, &duration);
1155   fail_unless(res == 0,
1156     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1157   fail_unless(duration == expected,
1158     "Expected duration %d secs, got %d", expected, duration);
1159 
1160   str = "0h";
1161   expected = 0;
1162   res = pr_str_get_duration(str, &duration);
1163   fail_unless(res == 0,
1164     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1165   fail_unless(duration == expected,
1166     "Expected duration %d secs, got %d", expected, duration);
1167 
1168   str = "0M";
1169   expected = 0;
1170   res = pr_str_get_duration(str, &duration);
1171   fail_unless(res == 0,
1172     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1173   fail_unless(duration == expected,
1174     "Expected duration %d secs, got %d", expected, duration);
1175 
1176   str = "0sec";
1177   expected = 0;
1178   res = pr_str_get_duration(str, &duration);
1179   fail_unless(res == 0,
1180     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1181   fail_unless(duration == expected,
1182     "Expected duration %d secs, got %d", expected, duration);
1183 
1184   str = "17";
1185   expected = 17;
1186   res = pr_str_get_duration(str, &duration);
1187   fail_unless(res == 0,
1188     "Failed to parse well-formed time string '%s': %s", str, strerror(errno));
1189   fail_unless(duration == expected,
1190     "Expected duration %d secs, got %d", expected, duration);
1191 
1192   str = "-1";
1193   res = pr_str_get_duration(str, NULL);
1194   fail_unless(res == -1,
1195     "Failed to handle badly formatted suffix string '%s'", str);
1196   fail_unless(errno == ERANGE, "Failed to set errno to ERANGE");
1197 }
1198 END_TEST
1199 
START_TEST(strnrstr_test)1200 START_TEST (strnrstr_test) {
1201   int res, flags = 0;
1202   const char *s = NULL, *suffix = NULL;
1203 
1204   res = pr_strnrstr(NULL, 0, NULL, 0, flags);
1205   fail_unless(res == -1, "Failed to handle null arguments");
1206   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1207 
1208   res = pr_strnrstr(NULL, 0, "", 0, flags);
1209   fail_unless(res == -1, "Failed to handle null s");
1210   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1211 
1212   res = pr_strnrstr("", 0, NULL, 0, flags);
1213   fail_unless(res == -1, "Failed to handle null suffix");
1214   fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");
1215 
1216   s = suffix = "";
1217   res = pr_strnrstr(s, 0, suffix, 0, flags);
1218   fail_unless(res == TRUE, "Expected true, got false");
1219 
1220   s = "";
1221   suffix = "s";
1222   res = pr_strnrstr(s, 0, suffix, 0, flags);
1223   fail_unless(res == FALSE, "Expected false, got true");
1224 
1225   s = "food";
1226   suffix = "ood";
1227   res = pr_strnrstr(s, 0, suffix, 0, flags);
1228   fail_unless(res == TRUE, "Expected true, got false");
1229 
1230   s = "food";
1231   suffix = "ood";
1232   res = pr_strnrstr(s, 4, suffix, 3, flags);
1233   fail_unless(res == TRUE, "Expected true, got false");
1234 
1235   s = "FOOD";
1236   suffix = "ood";
1237   res = pr_strnrstr(s, 4, suffix, 3, flags);
1238   fail_unless(res == FALSE, "Expected false, got true");
1239 
1240   flags = PR_STR_FL_IGNORE_CASE;
1241   s = "FOOD";
1242   suffix = "ood";
1243   res = pr_strnrstr(s, 4, suffix, 3, flags);
1244   fail_unless(res == TRUE, "Expected true, got false");
1245 }
1246 END_TEST
1247 
START_TEST(bin2hex_test)1248 START_TEST (bin2hex_test) {
1249   char *expected, *res;
1250   const unsigned char *str;
1251 
1252   res = pr_str_bin2hex(NULL, NULL, 0, 0);
1253   fail_unless(res == NULL, "Failed to handle null arguments");
1254   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1255     strerror(errno), errno);
1256 
1257   res = pr_str_bin2hex(p, NULL, 0, 0);
1258   fail_unless(res == NULL, "Failed to handle null data argument");
1259   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1260     strerror(errno), errno);
1261 
1262   /* Empty string. */
1263   str = (const unsigned char *) "foobar";
1264   expected = "";
1265   res = pr_str_bin2hex(p, (const unsigned char *) str, 0, 0);
1266   fail_unless(res != NULL, "Failed to hexify '%s': %s", str, strerror(errno));
1267   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'",
1268     expected, res);
1269 
1270   /* default (lowercase) */
1271   expected = "666f6f626172";
1272   res = pr_str_bin2hex(p, str, strlen((char *) str), 0);
1273   fail_unless(res != NULL, "Failed to hexify '%s': %s", str, strerror(errno));
1274   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'",
1275     expected, res);
1276 
1277   /* lowercase */
1278   expected = "666f6f626172";
1279   res = pr_str_bin2hex(p, str, strlen((char *) str), 0);
1280   fail_unless(res != NULL, "Failed to hexify '%s': %s", str, strerror(errno));
1281   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'",
1282     expected, res);
1283 
1284   /* uppercase */
1285   expected = "666F6F626172";
1286   res = pr_str_bin2hex(p, str, strlen((char *) str), PR_STR_FL_HEX_USE_UC);
1287   fail_unless(res != NULL, "Failed to hexify '%s': %s", str, strerror(errno));
1288   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'",
1289     expected, res);
1290 }
1291 END_TEST
1292 
START_TEST(hex2bin_test)1293 START_TEST (hex2bin_test) {
1294   unsigned char *expected, *res;
1295   const unsigned char *hex;
1296   size_t expected_len, hex_len, len;
1297 
1298   res = pr_str_hex2bin(NULL, NULL, 0, NULL);
1299   fail_unless(res == NULL, "Failed to handle null arguments");
1300   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1301     strerror(errno), errno);
1302 
1303   res = pr_str_hex2bin(p, NULL, 0, 0);
1304   fail_unless(res == NULL, "Failed to handle null data argument");
1305   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1306     strerror(errno), errno);
1307 
1308   /* Empty string. */
1309   hex = (const unsigned char *) "";
1310   hex_len = strlen((char *) hex);
1311   expected = (unsigned char *) "";
1312   res = pr_str_hex2bin(p, hex, hex_len, &len);
1313   fail_unless(res != NULL, "Failed to unhexify '%s': %s", hex, strerror(errno));
1314   fail_unless(strcmp((const char *) res, (const char *) expected) == 0,
1315     "Expected '%s', got '%s'", expected, res);
1316 
1317   hex = (const unsigned char *) "112233";
1318   hex_len = strlen((char *) hex);
1319   expected_len = 3;
1320   expected = palloc(p, expected_len);
1321   expected[0] = 17;
1322   expected[1] = 34;
1323   expected[2] = 51;
1324 
1325   res = pr_str_hex2bin(p, (const unsigned char *) hex, hex_len, &len);
1326   fail_unless(res != NULL, "Failed to unhexify '%s': %s", hex, strerror(errno));
1327   fail_unless(len == expected_len, "Expected len %lu, got %lu",
1328     (unsigned long) expected_len, len);
1329   fail_unless(memcmp(res, expected, len) == 0,
1330     "Did not receive expected unhexified data");
1331 
1332   /* lowercase */
1333   hex = (const unsigned char *) "666f6f626172";
1334   hex_len = strlen((char *) hex);
1335   expected_len = 6;
1336   expected = palloc(p, expected_len);
1337   expected[0] = 'f';
1338   expected[1] = 'o';
1339   expected[2] = 'o';
1340   expected[3] = 'b';
1341   expected[4] = 'a';
1342   expected[5] = 'r';
1343 
1344   res = pr_str_hex2bin(p, (const unsigned char *) hex, hex_len, &len);
1345   fail_unless(res != NULL, "Failed to unhexify '%s': %s", hex, strerror(errno));
1346   fail_unless(len == expected_len, "Expected len %lu, got %lu",
1347     (unsigned long) expected_len, len);
1348   fail_unless(memcmp(res, expected, len) == 0,
1349     "Did not receive expected unhexified data");
1350 
1351   /* uppercase */
1352   hex = (const unsigned char *) "666F6F626172";
1353   hex_len = strlen((char *) hex);
1354 
1355   res = pr_str_hex2bin(p, (const unsigned char *) hex, hex_len, &len);
1356   fail_unless(res != NULL, "Failed to unhexify '%s': %s", hex, strerror(errno));
1357   fail_unless(len == expected_len, "Expected len %lu, got %lu",
1358     (unsigned long) expected_len, len);
1359   fail_unless(memcmp(res, expected, len) == 0,
1360     "Did not receive expected unhexified data");
1361 
1362   /* Handle known not-hex data properly. */
1363   hex = (const unsigned char *) "Hello, World!\n";
1364   hex_len = strlen((char *) hex);
1365   res = pr_str_hex2bin(p, hex, hex_len, &len);
1366   fail_unless(res == NULL, "Successfully unhexified '%s' unexpectedly", hex);
1367   fail_unless(errno == ERANGE, "Expected ERANGE (%d), got %s (%d)", ERANGE,
1368     strerror(errno), errno);
1369 }
1370 END_TEST
1371 
START_TEST(levenshtein_test)1372 START_TEST (levenshtein_test) {
1373   int res, expected, flags = 0;
1374   const char *a, *b;
1375 
1376   mark_point();
1377   res = pr_str_levenshtein(NULL, NULL, NULL, 0, 0, 0, 0, flags);
1378   fail_unless(res < 0, "Failed to handle null pool");
1379   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1380     strerror(errno), errno);
1381 
1382   mark_point();
1383   res = pr_str_levenshtein(p, NULL, NULL, 0, 0, 0, 0, flags);
1384   fail_unless(res < 0, "Failed to handle null a string");
1385   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1386     strerror(errno), errno);
1387 
1388   a = "foo";
1389 
1390   mark_point();
1391   res = pr_str_levenshtein(p, a, NULL, 0, 0, 0, 0, flags);
1392   fail_unless(res < 0, "Failed to handle null b string");
1393   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1394     strerror(errno), errno);
1395 
1396   expected = 0;
1397   b = "Foo";
1398 
1399   mark_point();
1400   res = pr_str_levenshtein(p, a, b, 0, 0, 0, 0, flags);
1401   fail_if(res < 0,
1402     "Failed to compute Levenshtein distance from '%s' to '%s': %s", a, b,
1403     strerror(errno));
1404   fail_unless(expected == res, "Expected distance %d, got %d", expected, res);
1405 
1406   expected = 3;
1407   b = "Foo";
1408   res = pr_str_levenshtein(p, a, b, 0, 1, 1, 1, flags);
1409   fail_if(res < 0,
1410     "Failed to compute Levenshtein distance from '%s' to '%s': %s", a, b,
1411     strerror(errno));
1412   fail_unless(expected == res, "Expected distance %d, got %d", expected, res);
1413 
1414   flags = PR_STR_FL_IGNORE_CASE;
1415   expected = 2;
1416   b = "Foo";
1417   res = pr_str_levenshtein(p, a, b, 0, 1, 1, 1, flags);
1418   fail_if(res < 0,
1419     "Failed to compute Levenshtein distance from '%s' to '%s': %s", a, b,
1420     strerror(errno));
1421   fail_unless(expected == res, "Expected distance %d, got %d", expected, res);
1422 }
1423 END_TEST
1424 
START_TEST(similars_test)1425 START_TEST (similars_test) {
1426   array_header *res, *candidates;
1427   const char *s, **similars, *expected;
1428 
1429   mark_point();
1430   res = pr_str_get_similars(NULL, NULL, NULL, 0, 0);
1431   fail_unless(res == NULL, "Failed to handle null pool");
1432   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1433     strerror(errno), errno);
1434 
1435   mark_point();
1436   res = pr_str_get_similars(p, NULL, NULL, 0, 0);
1437   fail_unless(res == NULL, "Failed to handle null string");
1438   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1439     strerror(errno), errno);
1440 
1441   s = "foo";
1442 
1443   mark_point();
1444   res = pr_str_get_similars(p, s, NULL, 0, 0);
1445   fail_unless(res == NULL, "Failed to handle null candidates");
1446   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1447     strerror(errno), errno);
1448 
1449   candidates = make_array(p, 5, sizeof(const char *));
1450 
1451   mark_point();
1452   res = pr_str_get_similars(p, s, candidates, 0, 0);
1453   fail_unless(res == NULL, "Failed to handle empty candidates");
1454   fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1455     strerror(errno), errno);
1456 
1457   *((const char **) push_array(candidates)) = pstrdup(p, "fools");
1458   *((const char **) push_array(candidates)) = pstrdup(p, "odd");
1459   *((const char **) push_array(candidates)) = pstrdup(p, "bar");
1460   *((const char **) push_array(candidates)) = pstrdup(p, "FOO");
1461 
1462   mark_point();
1463   res = pr_str_get_similars(p, s, candidates, 0, 0);
1464   fail_unless(res != NULL, "Failed to find similar strings to '%s': %s", s,
1465     strerror(errno));
1466   fail_unless(res->nelts > 0, "Expected >0 similar strings, got %u",
1467     res->nelts);
1468 
1469   mark_point();
1470   similars = (const char **) res->elts;
1471 
1472   /*
1473    * Note: expected distances are as follows:
1474    *
1475    * Candidate       Case-Sensitive      Case-Insensitive
1476    * fools                 0                     0
1477    * odd                   5                     5
1478    * bar                   5                     5
1479    * FOO                   5                     0
1480    */
1481 
1482   expected = "fools";
1483 
1484   fail_unless(strcmp(similars[0], expected) == 0,
1485     "Expected similar '%s', got '%s'", expected, similars[0]);
1486 
1487   fail_unless(strcmp(similars[1], expected) != 0,
1488     "Unexpectedly got similar '%s'", similars[1]);
1489 
1490   mark_point();
1491   res = pr_str_get_similars(p, s, candidates, 0, PR_STR_FL_IGNORE_CASE);
1492   fail_unless(res != NULL, "Failed to find similar strings to '%s': %s", s,
1493     strerror(errno));
1494   fail_unless(res->nelts > 0, "Expected >0 similar strings, got %u",
1495     res->nelts);
1496 
1497   mark_point();
1498   similars = (const char **) res->elts;
1499 
1500   /*
1501    * similars[0] and similars[1] should be "FOO" and "fools", but
1502    * not necessarily in that order
1503    */
1504   expected = "FOO";
1505   if (strcmp(similars[0], expected) != 0) {
1506     expected = similars[0];
1507     similars[0] = similars[1];
1508     similars[1] = expected;
1509     expected = "FOO";
1510   }
1511 
1512   fail_unless(strcmp(similars[0], expected) == 0,
1513     "Expected similar '%s', got '%s'", expected, similars[0]);
1514 
1515   expected = "fools";
1516 
1517   fail_unless(strcmp(similars[1], expected) == 0,
1518     "Expected similar '%s', got '%s'", expected, similars[1]);
1519 }
1520 END_TEST
1521 
START_TEST(str2uid_test)1522 START_TEST (str2uid_test) {
1523   int res;
1524 
1525   res = pr_str2uid(NULL, NULL);
1526   fail_unless(res == -1, "Failed to handle null arguments");
1527 }
1528 END_TEST
1529 
START_TEST(str2gid_test)1530 START_TEST (str2gid_test) {
1531   int res;
1532 
1533   res = pr_str2gid(NULL, NULL);
1534   fail_unless(res == -1, "Failed to handle null arguments");
1535 }
1536 END_TEST
1537 
START_TEST(uid2str_test)1538 START_TEST (uid2str_test) {
1539   const char *res;
1540 
1541   res = pr_uid2str(NULL, (uid_t) 1);
1542   fail_unless(strcmp(res, "1") == 0, "Expected '1', got '%s'", res);
1543 
1544   res = pr_uid2str(NULL, (uid_t) -1);
1545   fail_unless(strcmp(res, "-1") == 0, "Expected '-1', got '%s'", res);
1546 }
1547 END_TEST
1548 
START_TEST(gid2str_test)1549 START_TEST (gid2str_test) {
1550   const char *res;
1551 
1552   res = pr_gid2str(NULL, (gid_t) 1);
1553   fail_unless(strcmp(res, "1") == 0, "Expected '1', got '%s'", res);
1554 
1555   res = pr_gid2str(NULL, (gid_t) -1);
1556   fail_unless(strcmp(res, "-1") == 0, "Expected '-1', got '%s'", res);
1557 }
1558 END_TEST
1559 
START_TEST(str_quote_test)1560 START_TEST (str_quote_test) {
1561   const char *res;
1562   char *expected, *path;
1563 
1564   res = pr_str_quote(NULL, NULL);
1565   fail_unless(res == NULL, "Failed to handle null arguments");
1566   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1567     strerror(errno), errno);
1568 
1569   res = pr_str_quote(p, NULL);
1570   fail_unless(res == NULL, "Failed to handle null path argument");
1571   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1572     strerror(errno), errno);
1573 
1574   path = "/tmp/";
1575   expected = path;
1576   res = pr_str_quote(p, path);
1577   fail_unless(res != NULL, "Failed to quote '%s': %s", path, strerror(errno));
1578   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1579     res);
1580 
1581   path = "/\"tmp\"/";
1582   expected = "/\"\"tmp\"\"/";
1583   res = pr_str_quote(p, path);
1584   fail_unless(res != NULL, "Failed to quote '%s': %s", path, strerror(errno));
1585   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1586     res);
1587 }
1588 END_TEST
1589 
START_TEST(quote_dir_test)1590 START_TEST (quote_dir_test) {
1591   const char *res;
1592   char *expected, *path;
1593 
1594   res = quote_dir(NULL, NULL);
1595   fail_unless(res == NULL, "Failed to handle null arguments");
1596   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1597     strerror(errno), errno);
1598 
1599   res = quote_dir(p, NULL);
1600   fail_unless(res == NULL, "Failed to handle null path argument");
1601   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1602     strerror(errno), errno);
1603 
1604   path = "/tmp/";
1605   expected = path;
1606   res = quote_dir(p, path);
1607   fail_unless(res != NULL, "Failed to quote '%s': %s", path, strerror(errno));
1608   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1609     res);
1610 
1611   path = "/\"tmp\"/";
1612   expected = "/\"\"tmp\"\"/";
1613   res = quote_dir(p, path);
1614   fail_unless(res != NULL, "Failed to quote '%s': %s", path, strerror(errno));
1615   fail_unless(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1616     res);
1617 }
1618 END_TEST
1619 
START_TEST(text_to_array_test)1620 START_TEST (text_to_array_test) {
1621   register unsigned int i;
1622   array_header *res;
1623   const char *text;
1624 
1625   mark_point();
1626   res = pr_str_text_to_array(NULL, NULL, ',');
1627   fail_unless(res == NULL, "Failed to handle null pool");
1628   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1629     strerror(errno), errno);
1630 
1631   mark_point();
1632   res = pr_str_text_to_array(p, NULL, ',');
1633   fail_unless(res == NULL, "Failed to handle null text");
1634   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1635     strerror(errno), errno);
1636 
1637   text = "";
1638 
1639   mark_point();
1640   res = pr_str_text_to_array(p, text, ',');
1641   fail_unless(res != NULL, "Failed to handle text '%s': %s", text,
1642     strerror(errno));
1643   fail_unless(res->nelts == 0, "Expected 0 items, got %u", res->nelts);
1644 
1645   text = ",";
1646 
1647   mark_point();
1648   res = pr_str_text_to_array(p, text, ',');
1649   fail_unless(res != NULL, "Failed to handle text '%s': %s", text,
1650     strerror(errno));
1651   fail_unless(res->nelts == 0, "Expected 0 items, got %u", res->nelts);
1652 
1653   text = ",,,";
1654 
1655   mark_point();
1656   res = pr_str_text_to_array(p, text, ',');
1657   fail_unless(res != NULL, "Failed to handle text '%s': %s", text,
1658     strerror(errno));
1659   fail_unless(res->nelts == 0, "Expected 0 items, got %u", res->nelts);
1660 
1661   text = "foo";
1662 
1663   mark_point();
1664   res = pr_str_text_to_array(p, text, ',');
1665   fail_unless(res != NULL, "Failed to handle text '%s': %s", text,
1666     strerror(errno));
1667   fail_unless(res->nelts == 1, "Expected 1 item, got %u", res->nelts);
1668 
1669   text = "foo,foo,foo";
1670 
1671   mark_point();
1672   res = pr_str_text_to_array(p, text, ',');
1673   fail_unless(res != NULL, "Failed to handle text '%s': %s", text,
1674     strerror(errno));
1675   fail_unless(res->nelts == 3, "Expected 3 items, got %u", res->nelts);
1676   for (i = 0; i < res->nelts; i++) {
1677     char *item, *expected;
1678 
1679     item = ((char **) res->elts)[i];
1680     fail_unless(item != NULL, "Expected item at index %u, got null", i);
1681 
1682     expected = "foo";
1683     fail_unless(strcmp(item, expected) == 0,
1684       "Expected '%s' at index %u, got '%s'", expected, i, item);
1685   }
1686 
1687   text = "foo,foo,foo,";
1688 
1689   mark_point();
1690   res = pr_str_text_to_array(p, text, ',');
1691   fail_unless(res != NULL, "Failed to handle text '%s': %s", text,
1692     strerror(errno));
1693   fail_unless(res->nelts == 3, "Expected 3 items, got %u", res->nelts);
1694   for (i = 0; i < res->nelts; i++) {
1695     char *item, *expected;
1696 
1697     item = ((char **) res->elts)[i];
1698     fail_unless(item != NULL, "Expected item at index %u, got null", i);
1699 
1700     if (i == 3) {
1701       expected = "";
1702 
1703     } else {
1704       expected = "foo";
1705     }
1706 
1707     fail_unless(strcmp(item, expected) == 0,
1708       "Expected '%s' at index %u, got '%s'", expected, i, item);
1709   }
1710 
1711   text = "foo|foo|foo";
1712 
1713   mark_point();
1714   res = pr_str_text_to_array(p, text, '|');
1715   fail_unless(res != NULL, "Failed to handle text '%s': %s", text,
1716     strerror(errno));
1717   fail_unless(res->nelts == 3, "Expected 3 items, got %u", res->nelts);
1718   for (i = 0; i < res->nelts; i++) {
1719     char *item, *expected;
1720 
1721     item = ((char **) res->elts)[i];
1722     fail_unless(item != NULL, "Expected item at index %u, got null", i);
1723 
1724     expected = "foo";
1725     fail_unless(strcmp(item, expected) == 0,
1726       "Expected '%s' at index %u, got '%s'", expected, i, item);
1727   }
1728 }
1729 END_TEST
1730 
tests_get_str_suite(void)1731 Suite *tests_get_str_suite(void) {
1732   Suite *suite;
1733   TCase *testcase;
1734 
1735   suite = suite_create("str");
1736 
1737   testcase = tcase_create("base");
1738   tcase_add_checked_fixture(testcase, set_up, tear_down);
1739 
1740   tcase_add_test(testcase, sstrncpy_test);
1741   tcase_add_test(testcase, sstrcat_test);
1742   tcase_add_test(testcase, sreplace_test);
1743   tcase_add_test(testcase, sreplace_enospc_test);
1744   tcase_add_test(testcase, sreplace_bug3614_test);
1745   tcase_add_test(testcase, str_replace_test);
1746   tcase_add_test(testcase, pdircat_test);
1747   tcase_add_test(testcase, pstrcat_test);
1748   tcase_add_test(testcase, pstrdup_test);
1749   tcase_add_test(testcase, pstrndup_test);
1750   tcase_add_test(testcase, strip_test);
1751   tcase_add_test(testcase, strip_end_test);
1752   tcase_add_test(testcase, get_token_test);
1753   tcase_add_test(testcase, get_token2_test);
1754   tcase_add_test(testcase, get_word_test);
1755   tcase_add_test(testcase, get_word_utf8_test);
1756   tcase_add_test(testcase, is_boolean_test);
1757   tcase_add_test(testcase, is_fnmatch_test);
1758   tcase_add_test(testcase, get_nbytes_test);
1759   tcase_add_test(testcase, get_duration_test);
1760   tcase_add_test(testcase, bin2hex_test);
1761   tcase_add_test(testcase, hex2bin_test);
1762   tcase_add_test(testcase, levenshtein_test);
1763   tcase_add_test(testcase, similars_test);
1764   tcase_add_test(testcase, strnrstr_test);
1765   tcase_add_test(testcase, str2uid_test);
1766   tcase_add_test(testcase, str2gid_test);
1767   tcase_add_test(testcase, uid2str_test);
1768   tcase_add_test(testcase, gid2str_test);
1769   tcase_add_test(testcase, str_quote_test);
1770   tcase_add_test(testcase, quote_dir_test);
1771   tcase_add_test(testcase, text_to_array_test);
1772 
1773   suite_add_tcase(suite, testcase);
1774   return suite;
1775 }
1776