1273929Sjmmv/* Copyright (c) 2008 The NetBSD Foundation, Inc.
2240116Smarcel * All rights reserved.
3240116Smarcel *
4240116Smarcel * Redistribution and use in source and binary forms, with or without
5240116Smarcel * modification, are permitted provided that the following conditions
6240116Smarcel * are met:
7240116Smarcel * 1. Redistributions of source code must retain the above copyright
8240116Smarcel *    notice, this list of conditions and the following disclaimer.
9240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
10240116Smarcel *    notice, this list of conditions and the following disclaimer in the
11240116Smarcel *    documentation and/or other materials provided with the distribution.
12240116Smarcel *
13240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14240116Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15240116Smarcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16240116Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17240116Smarcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18240116Smarcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20240116Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21240116Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22240116Smarcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23240116Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24273929Sjmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
25240116Smarcel
26273929Sjmmv#include "atf-c/detail/text.h"
27273929Sjmmv
28240116Smarcel#include <stdio.h>
29240116Smarcel#include <stdlib.h>
30240116Smarcel#include <string.h>
31240116Smarcel
32240116Smarcel#include <atf-c.h>
33240116Smarcel
34273929Sjmmv#include "atf-c/detail/sanity.h"
35273929Sjmmv#include "atf-c/detail/test_helpers.h"
36240116Smarcel
37240116Smarcel/* ---------------------------------------------------------------------
38240116Smarcel * Auxiliary functions.
39240116Smarcel * --------------------------------------------------------------------- */
40240116Smarcel
41240116Smarcel#define REQUIRE_ERROR(exp) \
42240116Smarcel    do { \
43240116Smarcel        atf_error_t err = exp; \
44240116Smarcel        ATF_REQUIRE(atf_is_error(err)); \
45240116Smarcel        atf_error_free(err); \
46240116Smarcel    } while (0)
47240116Smarcel
48240116Smarcelstatic
49240116Smarcelsize_t
50240116Smarcelarray_size(const char *words[])
51240116Smarcel{
52240116Smarcel    size_t count;
53240116Smarcel    const char **word;
54240116Smarcel
55240116Smarcel    count = 0;
56240116Smarcel    for (word = words; *word != NULL; word++)
57240116Smarcel        count++;
58240116Smarcel
59240116Smarcel    return count;
60240116Smarcel}
61240116Smarcel
62240116Smarcelstatic
63240116Smarcelvoid
64240116Smarcelcheck_split(const char *str, const char *delim, const char *words[])
65240116Smarcel{
66240116Smarcel    atf_list_t list;
67240116Smarcel    const char **word;
68240116Smarcel    size_t i;
69240116Smarcel
70240116Smarcel    printf("Splitting '%s' with delimiter '%s'\n", str, delim);
71240116Smarcel    CE(atf_text_split(str, delim, &list));
72240116Smarcel
73240116Smarcel    printf("Expecting %zd words\n", array_size(words));
74240116Smarcel    ATF_CHECK_EQ(atf_list_size(&list), array_size(words));
75240116Smarcel
76240116Smarcel    for (word = words, i = 0; *word != NULL; word++, i++) {
77240116Smarcel        printf("Word at position %zd should be '%s'\n", i, words[i]);
78240116Smarcel        ATF_CHECK_STREQ((const char *)atf_list_index_c(&list, i), words[i]);
79240116Smarcel    }
80240116Smarcel
81240116Smarcel    atf_list_fini(&list);
82240116Smarcel}
83240116Smarcel
84240116Smarcelstatic
85240116Smarcelatf_error_t
86240116Smarcelword_acum(const char *word, void *data)
87240116Smarcel{
88240116Smarcel    char *acum = data;
89240116Smarcel
90240116Smarcel    strcat(acum, word);
91240116Smarcel
92240116Smarcel    return atf_no_error();
93240116Smarcel}
94240116Smarcel
95240116Smarcelstatic
96240116Smarcelatf_error_t
97240116Smarcelword_count(const char *word ATF_DEFS_ATTRIBUTE_UNUSED, void *data)
98240116Smarcel{
99240116Smarcel    size_t *counter = data;
100240116Smarcel
101240116Smarcel    (*counter)++;
102240116Smarcel
103240116Smarcel    return atf_no_error();
104240116Smarcel}
105240116Smarcel
106240116Smarcelstruct fail_at {
107240116Smarcel    int failpos;
108240116Smarcel    int curpos;
109240116Smarcel};
110240116Smarcel
111240116Smarcelstatic
112240116Smarcelatf_error_t
113240116Smarcelword_fail_at(const char *word ATF_DEFS_ATTRIBUTE_UNUSED, void *data)
114240116Smarcel{
115240116Smarcel    struct fail_at *fa = data;
116240116Smarcel    atf_error_t err;
117240116Smarcel
118240116Smarcel    if (fa->failpos == fa->curpos)
119240116Smarcel        err = atf_no_memory_error(); /* Just a random error. */
120240116Smarcel    else {
121240116Smarcel        fa->curpos++;
122240116Smarcel        err = atf_no_error();
123240116Smarcel    }
124240116Smarcel
125240116Smarcel    return err;
126240116Smarcel}
127240116Smarcel
128240116Smarcel/* ---------------------------------------------------------------------
129240116Smarcel * Test cases for the free functions.
130240116Smarcel * --------------------------------------------------------------------- */
131240116Smarcel
132240116SmarcelATF_TC(for_each_word);
133240116SmarcelATF_TC_HEAD(for_each_word, tc)
134240116Smarcel{
135240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the atf_text_for_each_word"
136240116Smarcel                      "function");
137240116Smarcel}
138240116SmarcelATF_TC_BODY(for_each_word, tc)
139240116Smarcel{
140240116Smarcel    size_t cnt;
141240116Smarcel    char acum[1024];
142240116Smarcel
143240116Smarcel    cnt = 0;
144240116Smarcel    strcpy(acum, "");
145240116Smarcel    RE(atf_text_for_each_word("1 2 3", " ", word_count, &cnt));
146240116Smarcel    RE(atf_text_for_each_word("1 2 3", " ", word_acum, acum));
147240116Smarcel    ATF_REQUIRE(cnt == 3);
148240116Smarcel    ATF_REQUIRE(strcmp(acum, "123") == 0);
149240116Smarcel
150240116Smarcel    cnt = 0;
151240116Smarcel    strcpy(acum, "");
152240116Smarcel    RE(atf_text_for_each_word("1 2 3", ".", word_count, &cnt));
153240116Smarcel    RE(atf_text_for_each_word("1 2 3", ".", word_acum, acum));
154240116Smarcel    ATF_REQUIRE(cnt == 1);
155240116Smarcel    ATF_REQUIRE(strcmp(acum, "1 2 3") == 0);
156240116Smarcel
157240116Smarcel    cnt = 0;
158240116Smarcel    strcpy(acum, "");
159240116Smarcel    RE(atf_text_for_each_word("1 2 3 4 5", " ", word_count, &cnt));
160240116Smarcel    RE(atf_text_for_each_word("1 2 3 4 5", " ", word_acum, acum));
161240116Smarcel    ATF_REQUIRE(cnt == 5);
162240116Smarcel    ATF_REQUIRE(strcmp(acum, "12345") == 0);
163240116Smarcel
164240116Smarcel    cnt = 0;
165240116Smarcel    strcpy(acum, "");
166240116Smarcel    RE(atf_text_for_each_word("1 2.3.4 5", " .", word_count, &cnt));
167240116Smarcel    RE(atf_text_for_each_word("1 2.3.4 5", " .", word_acum, acum));
168240116Smarcel    ATF_REQUIRE(cnt == 5);
169240116Smarcel    ATF_REQUIRE(strcmp(acum, "12345") == 0);
170240116Smarcel
171240116Smarcel    {
172240116Smarcel        struct fail_at fa;
173240116Smarcel        fa.failpos = 3;
174240116Smarcel        fa.curpos = 0;
175240116Smarcel        atf_error_t err = atf_text_for_each_word("a b c d e", " ",
176240116Smarcel                                                 word_fail_at, &fa);
177240116Smarcel        ATF_REQUIRE(atf_is_error(err));
178240116Smarcel        ATF_REQUIRE(atf_error_is(err, "no_memory"));
179240116Smarcel        ATF_REQUIRE(fa.curpos == 3);
180240116Smarcel        atf_error_free(err);
181240116Smarcel    }
182240116Smarcel}
183240116Smarcel
184240116SmarcelATF_TC(format);
185240116SmarcelATF_TC_HEAD(format, tc)
186240116Smarcel{
187240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the construction of free-form "
188240116Smarcel                      "strings using a variable parameters list");
189240116Smarcel}
190240116SmarcelATF_TC_BODY(format, tc)
191240116Smarcel{
192240116Smarcel    char *str;
193240116Smarcel    atf_error_t err;
194240116Smarcel
195240116Smarcel    err = atf_text_format(&str, "%s %s %d", "Test", "string", 1);
196240116Smarcel    ATF_REQUIRE(!atf_is_error(err));
197240116Smarcel    ATF_REQUIRE(strcmp(str, "Test string 1") == 0);
198240116Smarcel    free(str);
199240116Smarcel}
200240116Smarcel
201240116Smarcelstatic
202240116Smarcelvoid
203240116Smarcelformat_ap(char **dest, const char *fmt, ...)
204240116Smarcel{
205240116Smarcel    va_list ap;
206240116Smarcel    atf_error_t err;
207240116Smarcel
208240116Smarcel    va_start(ap, fmt);
209240116Smarcel    err = atf_text_format_ap(dest, fmt, ap);
210240116Smarcel    va_end(ap);
211240116Smarcel
212240116Smarcel    ATF_REQUIRE(!atf_is_error(err));
213240116Smarcel}
214240116Smarcel
215240116SmarcelATF_TC(format_ap);
216240116SmarcelATF_TC_HEAD(format_ap, tc)
217240116Smarcel{
218240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the construction of free-form "
219240116Smarcel                      "strings using a va_list argument");
220240116Smarcel}
221240116SmarcelATF_TC_BODY(format_ap, tc)
222240116Smarcel{
223240116Smarcel    char *str;
224240116Smarcel
225240116Smarcel    format_ap(&str, "%s %s %d", "Test", "string", 1);
226240116Smarcel    ATF_REQUIRE(strcmp(str, "Test string 1") == 0);
227240116Smarcel    free(str);
228240116Smarcel}
229240116Smarcel
230240116SmarcelATF_TC(split);
231240116SmarcelATF_TC_HEAD(split, tc)
232240116Smarcel{
233240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the split function");
234240116Smarcel}
235240116SmarcelATF_TC_BODY(split, tc)
236240116Smarcel{
237240116Smarcel    {
238240116Smarcel        const char *words[] = { NULL };
239240116Smarcel        check_split("", " ", words);
240240116Smarcel    }
241240116Smarcel
242240116Smarcel    {
243240116Smarcel        const char *words[] = { NULL };
244240116Smarcel        check_split(" ", " ", words);
245240116Smarcel    }
246240116Smarcel
247240116Smarcel    {
248240116Smarcel        const char *words[] = { NULL };
249240116Smarcel        check_split("    ", " ", words);
250240116Smarcel    }
251240116Smarcel
252240116Smarcel    {
253240116Smarcel        const char *words[] = { "a", "b", NULL };
254240116Smarcel        check_split("a b", " ", words);
255240116Smarcel    }
256240116Smarcel
257240116Smarcel    {
258240116Smarcel        const char *words[] = { "a", "b", "c", "d", NULL };
259240116Smarcel        check_split("a b c d", " ", words);
260240116Smarcel    }
261240116Smarcel
262240116Smarcel    {
263240116Smarcel        const char *words[] = { "foo", "bar", NULL };
264240116Smarcel        check_split("foo bar", " ", words);
265240116Smarcel    }
266240116Smarcel
267240116Smarcel    {
268240116Smarcel        const char *words[] = { "foo", "bar", "baz", "foobar", NULL };
269240116Smarcel        check_split("foo bar baz foobar", " ", words);
270240116Smarcel    }
271240116Smarcel
272240116Smarcel    {
273240116Smarcel        const char *words[] = { "foo", "bar", NULL };
274240116Smarcel        check_split(" foo bar", " ", words);
275240116Smarcel    }
276240116Smarcel
277240116Smarcel    {
278240116Smarcel        const char *words[] = { "foo", "bar", NULL };
279240116Smarcel        check_split("foo  bar", " ", words);
280240116Smarcel    }
281240116Smarcel
282240116Smarcel    {
283240116Smarcel        const char *words[] = { "foo", "bar", NULL };
284240116Smarcel        check_split("foo bar ", " ", words);
285240116Smarcel    }
286240116Smarcel
287240116Smarcel    {
288240116Smarcel        const char *words[] = { "foo", "bar", NULL };
289240116Smarcel        check_split("  foo  bar  ", " ", words);
290240116Smarcel    }
291240116Smarcel}
292240116Smarcel
293240116SmarcelATF_TC(split_delims);
294240116SmarcelATF_TC_HEAD(split_delims, tc)
295240116Smarcel{
296240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the split function using "
297240116Smarcel                      "different delimiters");
298240116Smarcel}
299240116SmarcelATF_TC_BODY(split_delims, tc)
300240116Smarcel{
301240116Smarcel
302240116Smarcel    {
303240116Smarcel        const char *words[] = { NULL };
304240116Smarcel        check_split("", "/", words);
305240116Smarcel    }
306240116Smarcel
307240116Smarcel    {
308240116Smarcel        const char *words[] = { " ", NULL };
309240116Smarcel        check_split(" ", "/", words);
310240116Smarcel    }
311240116Smarcel
312240116Smarcel    {
313240116Smarcel        const char *words[] = { "    ", NULL };
314240116Smarcel        check_split("    ", "/", words);
315240116Smarcel    }
316240116Smarcel
317240116Smarcel    {
318240116Smarcel        const char *words[] = { "a", "b", NULL };
319240116Smarcel        check_split("a/b", "/", words);
320240116Smarcel    }
321240116Smarcel
322240116Smarcel    {
323240116Smarcel        const char *words[] = { "a", "bcd", "ef", NULL };
324240116Smarcel        check_split("aLONGDELIMbcdLONGDELIMef", "LONGDELIM", words);
325240116Smarcel    }
326240116Smarcel}
327240116Smarcel
328240116SmarcelATF_TC(to_bool);
329240116SmarcelATF_TC_HEAD(to_bool, tc)
330240116Smarcel{
331240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the atf_text_to_bool function");
332240116Smarcel}
333240116SmarcelATF_TC_BODY(to_bool, tc)
334240116Smarcel{
335240116Smarcel    bool b;
336240116Smarcel
337240116Smarcel    RE(atf_text_to_bool("true", &b)); ATF_REQUIRE(b);
338240116Smarcel    RE(atf_text_to_bool("TRUE", &b)); ATF_REQUIRE(b);
339240116Smarcel    RE(atf_text_to_bool("yes", &b)); ATF_REQUIRE(b);
340240116Smarcel    RE(atf_text_to_bool("YES", &b)); ATF_REQUIRE(b);
341240116Smarcel
342240116Smarcel    RE(atf_text_to_bool("false", &b)); ATF_REQUIRE(!b);
343240116Smarcel    RE(atf_text_to_bool("FALSE", &b)); ATF_REQUIRE(!b);
344240116Smarcel    RE(atf_text_to_bool("no", &b)); ATF_REQUIRE(!b);
345240116Smarcel    RE(atf_text_to_bool("NO", &b)); ATF_REQUIRE(!b);
346240116Smarcel
347240116Smarcel    b = false;
348240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("", &b));
349240116Smarcel    ATF_REQUIRE(!b);
350240116Smarcel    b = true;
351240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("", &b));
352240116Smarcel    ATF_REQUIRE(b);
353240116Smarcel
354240116Smarcel    b = false;
355240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("tru", &b));
356240116Smarcel    ATF_REQUIRE(!b);
357240116Smarcel    b = true;
358240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("tru", &b));
359240116Smarcel    ATF_REQUIRE(b);
360240116Smarcel
361240116Smarcel    b = false;
362240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("true2", &b));
363240116Smarcel    ATF_REQUIRE(!b);
364240116Smarcel    b = true;
365240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("true2", &b));
366240116Smarcel    ATF_REQUIRE(b);
367240116Smarcel
368240116Smarcel    b = false;
369240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("fals", &b));
370240116Smarcel    ATF_REQUIRE(!b);
371240116Smarcel    b = true;
372240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("fals", &b));
373240116Smarcel    ATF_REQUIRE(b);
374240116Smarcel
375240116Smarcel    b = false;
376240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("false2", &b));
377240116Smarcel    ATF_REQUIRE(!b);
378240116Smarcel    b = true;
379240116Smarcel    REQUIRE_ERROR(atf_text_to_bool("false2", &b));
380240116Smarcel    ATF_REQUIRE(b);
381240116Smarcel}
382240116Smarcel
383240116SmarcelATF_TC(to_long);
384240116SmarcelATF_TC_HEAD(to_long, tc)
385240116Smarcel{
386240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the atf_text_to_long function");
387240116Smarcel}
388240116SmarcelATF_TC_BODY(to_long, tc)
389240116Smarcel{
390240116Smarcel    long l;
391240116Smarcel
392240116Smarcel    RE(atf_text_to_long("0", &l)); ATF_REQUIRE_EQ(l, 0);
393240116Smarcel    RE(atf_text_to_long("-5", &l)); ATF_REQUIRE_EQ(l, -5);
394240116Smarcel    RE(atf_text_to_long("5", &l)); ATF_REQUIRE_EQ(l, 5);
395240116Smarcel    RE(atf_text_to_long("123456789", &l)); ATF_REQUIRE_EQ(l, 123456789);
396240116Smarcel
397240116Smarcel    l = 1212;
398240116Smarcel    REQUIRE_ERROR(atf_text_to_long("", &l));
399240116Smarcel    ATF_REQUIRE_EQ(l, 1212);
400240116Smarcel    REQUIRE_ERROR(atf_text_to_long("foo", &l));
401240116Smarcel    ATF_REQUIRE_EQ(l, 1212);
402240116Smarcel    REQUIRE_ERROR(atf_text_to_long("1234x", &l));
403240116Smarcel    ATF_REQUIRE_EQ(l, 1212);
404240116Smarcel}
405240116Smarcel
406240116Smarcel/* ---------------------------------------------------------------------
407240116Smarcel * Main.
408240116Smarcel * --------------------------------------------------------------------- */
409240116Smarcel
410240116SmarcelATF_TP_ADD_TCS(tp)
411240116Smarcel{
412240116Smarcel    ATF_TP_ADD_TC(tp, for_each_word);
413240116Smarcel    ATF_TP_ADD_TC(tp, format);
414240116Smarcel    ATF_TP_ADD_TC(tp, format_ap);
415240116Smarcel    ATF_TP_ADD_TC(tp, split);
416240116Smarcel    ATF_TP_ADD_TC(tp, split_delims);
417240116Smarcel    ATF_TP_ADD_TC(tp, to_bool);
418240116Smarcel    ATF_TP_ADD_TC(tp, to_long);
419240116Smarcel
420240116Smarcel    return atf_no_error();
421240116Smarcel}
422