1240116Smarcel/*
2240116Smarcel * Automated Testing Framework (atf)
3240116Smarcel *
4240116Smarcel * Copyright (c) 2008 The NetBSD Foundation, Inc.
5240116Smarcel * All rights reserved.
6240116Smarcel *
7240116Smarcel * Redistribution and use in source and binary forms, with or without
8240116Smarcel * modification, are permitted provided that the following conditions
9240116Smarcel * are met:
10240116Smarcel * 1. Redistributions of source code must retain the above copyright
11240116Smarcel *    notice, this list of conditions and the following disclaimer.
12240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
13240116Smarcel *    notice, this list of conditions and the following disclaimer in the
14240116Smarcel *    documentation and/or other materials provided with the distribution.
15240116Smarcel *
16240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17240116Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18240116Smarcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19240116Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20240116Smarcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21240116Smarcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23240116Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24240116Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25240116Smarcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26240116Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27240116Smarcel * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28240116Smarcel */
29240116Smarcel
30240116Smarcel#include <stdarg.h>
31240116Smarcel#include <stdint.h>
32240116Smarcel#include <stdio.h>
33240116Smarcel#include <stdlib.h>
34240116Smarcel#include <string.h>
35240116Smarcel
36240116Smarcel#include <atf-c.h>
37240116Smarcel
38240116Smarcel#include "dynstr.h"
39240116Smarcel#include "test_helpers.h"
40240116Smarcel
41240116Smarcel/* ---------------------------------------------------------------------
42240116Smarcel * Tests for the "atf_dynstr" type.
43240116Smarcel * --------------------------------------------------------------------- */
44240116Smarcel
45240116Smarcel/*
46240116Smarcel * Constructors and destructors.
47240116Smarcel */
48240116Smarcel
49240116SmarcelATF_TC(init);
50240116SmarcelATF_TC_HEAD(init, tc)
51240116Smarcel{
52240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the empty constructor");
53240116Smarcel}
54240116SmarcelATF_TC_BODY(init, tc)
55240116Smarcel{
56240116Smarcel    atf_dynstr_t str;
57240116Smarcel
58240116Smarcel    RE(atf_dynstr_init(&str));
59240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0);
60240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0);
61240116Smarcel    atf_dynstr_fini(&str);
62240116Smarcel}
63240116Smarcel
64240116Smarcelstatic
65240116Smarcelvoid
66240116Smarcelinit_fmt(atf_dynstr_t *str, const char *fmt, ...)
67240116Smarcel{
68240116Smarcel    va_list ap;
69240116Smarcel
70240116Smarcel    va_start(ap, fmt);
71240116Smarcel    RE(atf_dynstr_init_ap(str, fmt, ap));
72240116Smarcel    va_end(ap);
73240116Smarcel}
74240116Smarcel
75240116SmarcelATF_TC(init_ap);
76240116SmarcelATF_TC_HEAD(init_ap, tc)
77240116Smarcel{
78240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the formatted constructor using "
79240116Smarcel                      "a va_list argument");
80240116Smarcel}
81240116SmarcelATF_TC_BODY(init_ap, tc)
82240116Smarcel{
83240116Smarcel    atf_dynstr_t str;
84240116Smarcel
85240116Smarcel    init_fmt(&str, "String 1");
86240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0);
87240116Smarcel    atf_dynstr_fini(&str);
88240116Smarcel
89240116Smarcel    init_fmt(&str, "String %d", 2);
90240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0);
91240116Smarcel    atf_dynstr_fini(&str);
92240116Smarcel
93240116Smarcel    init_fmt(&str, "%s %d", "String", 3);
94240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 3") == 0);
95240116Smarcel    atf_dynstr_fini(&str);
96240116Smarcel
97240116Smarcel    init_fmt(&str, "%s%s%s%s%s%s%s", "This ", "should ", "be ", "a ",
98240116Smarcel             "large ", "string ", "aaaabbbbccccdddd");
99240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str),
100240116Smarcel                     "This should be a large string "
101240116Smarcel                     "aaaabbbbccccdddd") == 0);
102240116Smarcel    atf_dynstr_fini(&str);
103240116Smarcel}
104240116Smarcel
105240116SmarcelATF_TC(init_fmt);
106240116SmarcelATF_TC_HEAD(init_fmt, tc)
107240116Smarcel{
108240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the formatted constructor using "
109240116Smarcel                      "a variable list of parameters");
110240116Smarcel}
111240116SmarcelATF_TC_BODY(init_fmt, tc)
112240116Smarcel{
113240116Smarcel    atf_dynstr_t str;
114240116Smarcel
115240116Smarcel    RE(atf_dynstr_init_fmt(&str, "String 1"));
116240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0);
117240116Smarcel    atf_dynstr_fini(&str);
118240116Smarcel
119240116Smarcel    RE(atf_dynstr_init_fmt(&str, "String %d", 2));
120240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0);
121240116Smarcel    atf_dynstr_fini(&str);
122240116Smarcel
123240116Smarcel    RE(atf_dynstr_init_fmt(&str, "%s %d", "String", 3));
124240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 3") == 0);
125240116Smarcel    atf_dynstr_fini(&str);
126240116Smarcel
127240116Smarcel    RE(atf_dynstr_init_fmt(&str, "%s%s%s%s%s%s%s", "This ", "should ",
128240116Smarcel                           "be ", "a ", "large ", "string ",
129240116Smarcel                           "aaaabbbbccccdddd"));
130240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str),
131240116Smarcel                     "This should be a large string "
132240116Smarcel                     "aaaabbbbccccdddd") == 0);
133240116Smarcel    atf_dynstr_fini(&str);
134240116Smarcel}
135240116Smarcel
136240116SmarcelATF_TC(init_raw);
137240116SmarcelATF_TC_HEAD(init_raw, tc)
138240116Smarcel{
139240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the construction of a string "
140240116Smarcel                      "using a raw memory pointer");
141240116Smarcel}
142240116SmarcelATF_TC_BODY(init_raw, tc)
143240116Smarcel{
144240116Smarcel    const char *src = "String 1, String 2";
145240116Smarcel    atf_dynstr_t str;
146240116Smarcel
147240116Smarcel    RE(atf_dynstr_init_raw(&str, src, 0));
148240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0);
149240116Smarcel    atf_dynstr_fini(&str);
150240116Smarcel
151240116Smarcel    RE(atf_dynstr_init_raw(&str, src, 8));
152240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0);
153240116Smarcel    atf_dynstr_fini(&str);
154240116Smarcel
155240116Smarcel    RE(atf_dynstr_init_raw(&str, src + 10, 8));
156240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0);
157240116Smarcel    atf_dynstr_fini(&str);
158240116Smarcel
159240116Smarcel    RE(atf_dynstr_init_raw(&str, "String\0Lost", 11));
160240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String") == 0);
161240116Smarcel    atf_dynstr_fini(&str);
162240116Smarcel
163240116Smarcel    {
164240116Smarcel        atf_error_t err = atf_dynstr_init_raw(&str, "NULL", SIZE_MAX - 1);
165240116Smarcel        ATF_REQUIRE(atf_is_error(err));
166240116Smarcel        ATF_REQUIRE(atf_error_is(err, "no_memory"));
167240116Smarcel        atf_error_free(err);
168240116Smarcel    }
169240116Smarcel}
170240116Smarcel
171240116SmarcelATF_TC(init_rep);
172240116SmarcelATF_TC_HEAD(init_rep, tc)
173240116Smarcel{
174240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the construction of a string by "
175240116Smarcel                      "repeating characters");
176240116Smarcel}
177240116SmarcelATF_TC_BODY(init_rep, tc)
178240116Smarcel{
179240116Smarcel    const size_t maxlen = 8192;
180240116Smarcel    char buf[maxlen + 1];
181240116Smarcel    size_t i;
182240116Smarcel
183240116Smarcel    buf[0] = '\0';
184240116Smarcel
185240116Smarcel    for (i = 0; i < maxlen; i++) {
186240116Smarcel        atf_dynstr_t str;
187240116Smarcel
188240116Smarcel        RE(atf_dynstr_init_rep(&str, i, 'a'));
189240116Smarcel
190240116Smarcel        if (strcmp(atf_dynstr_cstring(&str), buf) != 0) {
191240116Smarcel            fprintf(stderr, "Failed at iteration %zd\n", i);
192240116Smarcel            atf_tc_fail("Failed to construct dynstr by repeating %zd "
193240116Smarcel                        "times the '%c' character", i, 'a');
194240116Smarcel        }
195240116Smarcel
196240116Smarcel        atf_dynstr_fini(&str);
197240116Smarcel
198240116Smarcel        strcat(buf, "a");
199240116Smarcel    }
200240116Smarcel
201240116Smarcel    {
202240116Smarcel        atf_dynstr_t str;
203240116Smarcel        atf_error_t err;
204240116Smarcel
205240116Smarcel        err = atf_dynstr_init_rep(&str, SIZE_MAX, 'a');
206240116Smarcel        ATF_REQUIRE(atf_is_error(err));
207240116Smarcel        ATF_REQUIRE(atf_error_is(err, "no_memory"));
208240116Smarcel        atf_error_free(err);
209240116Smarcel
210240116Smarcel        err = atf_dynstr_init_rep(&str, SIZE_MAX - 1, 'a');
211240116Smarcel        ATF_REQUIRE(atf_is_error(err));
212240116Smarcel        ATF_REQUIRE(atf_error_is(err, "no_memory"));
213240116Smarcel        atf_error_free(err);
214240116Smarcel    }
215240116Smarcel}
216240116Smarcel
217240116SmarcelATF_TC(init_substr);
218240116SmarcelATF_TC_HEAD(init_substr, tc)
219240116Smarcel{
220240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the construction of a string "
221240116Smarcel                      "using a substring of another one");
222240116Smarcel}
223240116SmarcelATF_TC_BODY(init_substr, tc)
224240116Smarcel{
225240116Smarcel    atf_dynstr_t src;
226240116Smarcel    atf_dynstr_t str;
227240116Smarcel
228240116Smarcel    RE(atf_dynstr_init_fmt(&src, "Str 1, Str 2"));
229240116Smarcel
230240116Smarcel    RE(atf_dynstr_init_substr(&str, &src, 0, 0));
231240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0);
232240116Smarcel    atf_dynstr_fini(&str);
233240116Smarcel
234240116Smarcel    RE(atf_dynstr_init_substr(&str, &src, 0, atf_dynstr_npos));
235240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1, Str 2") == 0);
236240116Smarcel    atf_dynstr_fini(&str);
237240116Smarcel
238240116Smarcel    RE(atf_dynstr_init_substr(&str, &src, 0, 100));
239240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1, Str 2") == 0);
240240116Smarcel    atf_dynstr_fini(&str);
241240116Smarcel
242240116Smarcel    RE(atf_dynstr_init_substr(&str, &src, 0, 5));
243240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1") == 0);
244240116Smarcel    atf_dynstr_fini(&str);
245240116Smarcel
246240116Smarcel    RE(atf_dynstr_init_substr(&str, &src, 100, atf_dynstr_npos));
247240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0);
248240116Smarcel    atf_dynstr_fini(&str);
249240116Smarcel
250240116Smarcel    RE(atf_dynstr_init_substr(&str, &src, 7, atf_dynstr_npos));
251240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 2") == 0);
252240116Smarcel    atf_dynstr_fini(&str);
253240116Smarcel
254240116Smarcel    atf_dynstr_fini(&src);
255240116Smarcel}
256240116Smarcel
257240116SmarcelATF_TC(copy);
258240116SmarcelATF_TC_HEAD(copy, tc)
259240116Smarcel{
260240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the atf_dynstr_copy constructor");
261240116Smarcel}
262240116SmarcelATF_TC_BODY(copy, tc)
263240116Smarcel{
264240116Smarcel    atf_dynstr_t str, str2;
265240116Smarcel
266240116Smarcel    RE(atf_dynstr_init_fmt(&str, "Test string"));
267240116Smarcel    RE(atf_dynstr_copy(&str2, &str));
268240116Smarcel
269240116Smarcel    ATF_REQUIRE(atf_equal_dynstr_dynstr(&str, &str2));
270240116Smarcel
271240116Smarcel    RE(atf_dynstr_append_fmt(&str2, " non-shared text"));
272240116Smarcel
273240116Smarcel    ATF_REQUIRE(!atf_equal_dynstr_dynstr(&str, &str2));
274240116Smarcel
275240116Smarcel    atf_dynstr_fini(&str2);
276240116Smarcel    atf_dynstr_fini(&str);
277240116Smarcel}
278240116Smarcel
279240116SmarcelATF_TC(fini_disown);
280240116SmarcelATF_TC_HEAD(fini_disown, tc)
281240116Smarcel{
282240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks grabbing ownership of the "
283240116Smarcel                      "internal plain C string");
284240116Smarcel}
285240116SmarcelATF_TC_BODY(fini_disown, tc)
286240116Smarcel{
287240116Smarcel    const char *cstr;
288240116Smarcel    char *cstr2;
289240116Smarcel    atf_dynstr_t str;
290240116Smarcel
291240116Smarcel    RE(atf_dynstr_init_fmt(&str, "Test string 1"));
292240116Smarcel    cstr = atf_dynstr_cstring(&str);
293240116Smarcel    cstr2 = atf_dynstr_fini_disown(&str);
294240116Smarcel
295240116Smarcel    ATF_REQUIRE_EQ(cstr, cstr2);
296240116Smarcel    free(cstr2);
297240116Smarcel}
298240116Smarcel
299240116Smarcel/*
300240116Smarcel * Getters.
301240116Smarcel */
302240116Smarcel
303240116SmarcelATF_TC(cstring);
304240116SmarcelATF_TC_HEAD(cstring, tc)
305240116Smarcel{
306240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the method to obtain a plain C "
307240116Smarcel                      "string");
308240116Smarcel}
309240116SmarcelATF_TC_BODY(cstring, tc)
310240116Smarcel{
311240116Smarcel    const char *cstr;
312240116Smarcel    atf_dynstr_t str;
313240116Smarcel
314240116Smarcel    RE(atf_dynstr_init_fmt(&str, "Test string 1"));
315240116Smarcel    cstr = atf_dynstr_cstring(&str);
316240116Smarcel    ATF_REQUIRE(cstr != NULL);
317240116Smarcel    ATF_REQUIRE(strcmp(cstr, "Test string 1") == 0);
318240116Smarcel    atf_dynstr_fini(&str);
319240116Smarcel
320240116Smarcel    RE(atf_dynstr_init_fmt(&str, "Test string 2"));
321240116Smarcel    cstr = atf_dynstr_cstring(&str);
322240116Smarcel    ATF_REQUIRE(cstr != NULL);
323240116Smarcel    ATF_REQUIRE(strcmp(cstr, "Test string 2") == 0);
324240116Smarcel    atf_dynstr_fini(&str);
325240116Smarcel}
326240116Smarcel
327240116SmarcelATF_TC(length);
328240116SmarcelATF_TC_HEAD(length, tc)
329240116Smarcel{
330240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the method to obtain the length");
331240116Smarcel}
332240116SmarcelATF_TC_BODY(length, tc)
333240116Smarcel{
334240116Smarcel    size_t i;
335240116Smarcel
336240116Smarcel    for (i = 0; i < 8192; i++) {
337240116Smarcel        atf_dynstr_t str;
338240116Smarcel        RE(atf_dynstr_init_rep(&str, i, 'a'));
339240116Smarcel        ATF_REQUIRE_EQ(atf_dynstr_length(&str), i);
340240116Smarcel        atf_dynstr_fini(&str);
341240116Smarcel    }
342240116Smarcel}
343240116Smarcel
344240116SmarcelATF_TC(rfind_ch);
345240116SmarcelATF_TC_HEAD(rfind_ch, tc)
346240116Smarcel{
347240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the method to locate the first "
348240116Smarcel                      "occurrence of a character starting from the end");
349240116Smarcel}
350240116SmarcelATF_TC_BODY(rfind_ch, tc)
351240116Smarcel{
352240116Smarcel    atf_dynstr_t str;
353240116Smarcel
354240116Smarcel    RE(atf_dynstr_init_fmt(&str, "Foo1/Bar2/,.Baz"));
355240116Smarcel
356240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '\0'), atf_dynstr_npos);
357240116Smarcel
358240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '0'), atf_dynstr_npos);
359240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'b'), atf_dynstr_npos);
360240116Smarcel
361240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'F'), 0);
362240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '/'), 9);
363240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'a'), 13);
364240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'z'), 14);
365240116Smarcel
366240116Smarcel    atf_dynstr_fini(&str);
367240116Smarcel}
368240116Smarcel
369240116Smarcel/*
370240116Smarcel * Modifiers.
371240116Smarcel */
372240116Smarcel
373240116Smarcelstatic
374240116Smarcelvoid
375240116Smarcelcheck_append(atf_error_t (*append)(atf_dynstr_t *, const char *, ...))
376240116Smarcel{
377240116Smarcel    const size_t maxlen = 8192;
378240116Smarcel    char buf[maxlen + 1];
379240116Smarcel    size_t i;
380240116Smarcel    atf_dynstr_t str;
381240116Smarcel
382240116Smarcel    printf("Appending with plain string\n");
383240116Smarcel    buf[0] = '\0';
384240116Smarcel    RE(atf_dynstr_init(&str));
385240116Smarcel    for (i = 0; i < maxlen; i++) {
386240116Smarcel        if (strcmp(atf_dynstr_cstring(&str), buf) != 0) {
387240116Smarcel            fprintf(stderr, "Failed at iteration %zd\n", i);
388240116Smarcel            atf_tc_fail("Failed to append character at iteration %zd", i);
389240116Smarcel        }
390240116Smarcel
391240116Smarcel        RE(append(&str, "a"));
392240116Smarcel        strcat(buf, "a");
393240116Smarcel    }
394240116Smarcel    atf_dynstr_fini(&str);
395240116Smarcel
396240116Smarcel    printf("Appending with formatted string\n");
397240116Smarcel    buf[0] = '\0';
398240116Smarcel    RE(atf_dynstr_init(&str));
399240116Smarcel    for (i = 0; i < maxlen; i++) {
400240116Smarcel        if (strcmp(atf_dynstr_cstring(&str), buf) != 0) {
401240116Smarcel            fprintf(stderr, "Failed at iteration %zd\n", i);
402240116Smarcel            atf_tc_fail("Failed to append character at iteration %zd", i);
403240116Smarcel        }
404240116Smarcel
405240116Smarcel        RE(append(&str, "%s", "a"));
406240116Smarcel        strcat(buf, "a");
407240116Smarcel    }
408240116Smarcel    atf_dynstr_fini(&str);
409240116Smarcel}
410240116Smarcel
411240116Smarcelstatic
412240116Smarcelatf_error_t
413240116Smarcelappend_ap_aux(atf_dynstr_t *str, const char *fmt, ...)
414240116Smarcel{
415240116Smarcel    va_list ap;
416240116Smarcel    atf_error_t err;
417240116Smarcel
418240116Smarcel    va_start(ap, fmt);
419240116Smarcel    err = atf_dynstr_append_ap(str, fmt, ap);
420240116Smarcel    va_end(ap);
421240116Smarcel
422240116Smarcel    return err;
423240116Smarcel}
424240116Smarcel
425240116SmarcelATF_TC(append_ap);
426240116SmarcelATF_TC_HEAD(append_ap, tc)
427240116Smarcel{
428240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks that appending a string to "
429240116Smarcel                      "another one works");
430240116Smarcel}
431240116SmarcelATF_TC_BODY(append_ap, tc)
432240116Smarcel{
433240116Smarcel    check_append(append_ap_aux);
434240116Smarcel}
435240116Smarcel
436240116SmarcelATF_TC(append_fmt);
437240116SmarcelATF_TC_HEAD(append_fmt, tc)
438240116Smarcel{
439240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks that appending a string to "
440240116Smarcel                      "another one works");
441240116Smarcel}
442240116SmarcelATF_TC_BODY(append_fmt, tc)
443240116Smarcel{
444240116Smarcel    check_append(atf_dynstr_append_fmt);
445240116Smarcel}
446240116Smarcel
447240116SmarcelATF_TC(clear);
448240116SmarcelATF_TC_HEAD(clear, tc)
449240116Smarcel{
450240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks clearing a string");
451240116Smarcel}
452240116SmarcelATF_TC_BODY(clear, tc)
453240116Smarcel{
454240116Smarcel    atf_dynstr_t str;
455240116Smarcel
456240116Smarcel    printf("Clear an empty string\n");
457240116Smarcel    RE(atf_dynstr_init(&str));
458240116Smarcel    atf_dynstr_clear(&str);
459240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0);
460240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0);
461240116Smarcel    atf_dynstr_fini(&str);
462240116Smarcel
463240116Smarcel    printf("Clear a non-empty string\n");
464240116Smarcel    RE(atf_dynstr_init_fmt(&str, "Not empty"));
465240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_length(&str), strlen("Not empty"));
466240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Not empty") == 0);
467240116Smarcel    atf_dynstr_clear(&str);
468240116Smarcel    ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0);
469240116Smarcel    ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0);
470240116Smarcel    atf_dynstr_fini(&str);
471240116Smarcel}
472240116Smarcel
473240116Smarcelstatic
474240116Smarcelvoid
475240116Smarcelcheck_prepend(atf_error_t (*prepend)(atf_dynstr_t *, const char *, ...))
476240116Smarcel{
477240116Smarcel    const size_t maxlen = 8192;
478240116Smarcel    char buf[maxlen + 1];
479240116Smarcel    size_t i;
480240116Smarcel    atf_dynstr_t str;
481240116Smarcel
482240116Smarcel    printf("Prepending with plain string\n");
483240116Smarcel    buf[0] = '\0';
484240116Smarcel    RE(atf_dynstr_init(&str));
485240116Smarcel    for (i = 0; i < maxlen; i++) {
486240116Smarcel        if (strcmp(atf_dynstr_cstring(&str), buf) != 0) {
487240116Smarcel            fprintf(stderr, "Failed at iteration %zd\n", i);
488240116Smarcel            atf_tc_fail("Failed to prepend character at iteration %zd", i);
489240116Smarcel        }
490240116Smarcel
491240116Smarcel        memmove(buf + 1, buf, i + 1);
492240116Smarcel        if (i % 2 == 0) {
493240116Smarcel            RE(prepend(&str, "%s", "a"));
494240116Smarcel            buf[0] = 'a';
495240116Smarcel        } else {
496240116Smarcel            RE(prepend(&str, "%s", "b"));
497240116Smarcel            buf[0] = 'b';
498240116Smarcel        }
499240116Smarcel    }
500240116Smarcel    atf_dynstr_fini(&str);
501240116Smarcel
502240116Smarcel    printf("Prepending with formatted string\n");
503240116Smarcel    buf[0] = '\0';
504240116Smarcel    RE(atf_dynstr_init(&str));
505240116Smarcel    for (i = 0; i < maxlen; i++) {
506240116Smarcel        if (strcmp(atf_dynstr_cstring(&str), buf) != 0) {
507240116Smarcel            fprintf(stderr, "Failed at iteration %zd\n", i);
508240116Smarcel            atf_tc_fail("Failed to prepend character at iteration %zd", i);
509240116Smarcel        }
510240116Smarcel
511240116Smarcel        memmove(buf + 1, buf, i + 1);
512240116Smarcel        if (i % 2 == 0) {
513240116Smarcel            RE(prepend(&str, "%s", "a"));
514240116Smarcel            buf[0] = 'a';
515240116Smarcel        } else {
516240116Smarcel            RE(prepend(&str, "%s", "b"));
517240116Smarcel            buf[0] = 'b';
518240116Smarcel        }
519240116Smarcel    }
520240116Smarcel    atf_dynstr_fini(&str);
521240116Smarcel}
522240116Smarcel
523240116Smarcelstatic
524240116Smarcelatf_error_t
525240116Smarcelprepend_ap_aux(atf_dynstr_t *str, const char *fmt, ...)
526240116Smarcel{
527240116Smarcel    va_list ap;
528240116Smarcel    atf_error_t err;
529240116Smarcel
530240116Smarcel    va_start(ap, fmt);
531240116Smarcel    err = atf_dynstr_prepend_ap(str, fmt, ap);
532240116Smarcel    va_end(ap);
533240116Smarcel
534240116Smarcel    return err;
535240116Smarcel}
536240116Smarcel
537240116SmarcelATF_TC(prepend_ap);
538240116SmarcelATF_TC_HEAD(prepend_ap, tc)
539240116Smarcel{
540240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks that prepending a string to "
541240116Smarcel                      "another one works");
542240116Smarcel}
543240116SmarcelATF_TC_BODY(prepend_ap, tc)
544240116Smarcel{
545240116Smarcel    check_prepend(prepend_ap_aux);
546240116Smarcel}
547240116Smarcel
548240116SmarcelATF_TC(prepend_fmt);
549240116SmarcelATF_TC_HEAD(prepend_fmt, tc)
550240116Smarcel{
551240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks that prepending a string to "
552240116Smarcel                      "another one works");
553240116Smarcel}
554240116SmarcelATF_TC_BODY(prepend_fmt, tc)
555240116Smarcel{
556240116Smarcel    check_prepend(atf_dynstr_prepend_fmt);
557240116Smarcel}
558240116Smarcel
559240116Smarcel/*
560240116Smarcel * Operators.
561240116Smarcel */
562240116Smarcel
563240116SmarcelATF_TC(equal_cstring);
564240116SmarcelATF_TC_HEAD(equal_cstring, tc)
565240116Smarcel{
566240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the atf_equal_dynstr_cstring "
567240116Smarcel                      "function");
568240116Smarcel}
569240116SmarcelATF_TC_BODY(equal_cstring, tc)
570240116Smarcel{
571240116Smarcel    atf_dynstr_t str;
572240116Smarcel
573240116Smarcel    RE(atf_dynstr_init(&str));
574240116Smarcel    ATF_REQUIRE( atf_equal_dynstr_cstring(&str, ""));
575240116Smarcel    ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Test"));
576240116Smarcel    atf_dynstr_fini(&str);
577240116Smarcel
578240116Smarcel    RE(atf_dynstr_init_fmt(&str, "Test"));
579240116Smarcel    ATF_REQUIRE( atf_equal_dynstr_cstring(&str, "Test"));
580240116Smarcel    ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, ""));
581240116Smarcel    ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Tes"));
582240116Smarcel    ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Test "));
583240116Smarcel    atf_dynstr_fini(&str);
584240116Smarcel}
585240116Smarcel
586240116SmarcelATF_TC(equal_dynstr);
587240116SmarcelATF_TC_HEAD(equal_dynstr, tc)
588240116Smarcel{
589240116Smarcel    atf_tc_set_md_var(tc, "descr", "Checks the atf_equal_dynstr_dynstr "
590240116Smarcel                      "function");
591240116Smarcel}
592240116SmarcelATF_TC_BODY(equal_dynstr, tc)
593240116Smarcel{
594240116Smarcel    atf_dynstr_t str, str2;
595240116Smarcel
596240116Smarcel    RE(atf_dynstr_init(&str));
597240116Smarcel    RE(atf_dynstr_init_fmt(&str2, "Test"));
598240116Smarcel    ATF_REQUIRE( atf_equal_dynstr_dynstr(&str, &str));
599240116Smarcel    ATF_REQUIRE(!atf_equal_dynstr_dynstr(&str, &str2));
600240116Smarcel    atf_dynstr_fini(&str2);
601240116Smarcel    atf_dynstr_fini(&str);
602240116Smarcel}
603240116Smarcel
604240116Smarcel/* ---------------------------------------------------------------------
605240116Smarcel * Main.
606240116Smarcel * --------------------------------------------------------------------- */
607240116Smarcel
608240116SmarcelATF_TP_ADD_TCS(tp)
609240116Smarcel{
610240116Smarcel    /* Constructors and destructors. */
611240116Smarcel    ATF_TP_ADD_TC(tp, init);
612240116Smarcel    ATF_TP_ADD_TC(tp, init_ap);
613240116Smarcel    ATF_TP_ADD_TC(tp, init_fmt);
614240116Smarcel    ATF_TP_ADD_TC(tp, init_raw);
615240116Smarcel    ATF_TP_ADD_TC(tp, init_rep);
616240116Smarcel    ATF_TP_ADD_TC(tp, init_substr);
617240116Smarcel    ATF_TP_ADD_TC(tp, copy);
618240116Smarcel    ATF_TP_ADD_TC(tp, fini_disown);
619240116Smarcel
620240116Smarcel    /* Getters. */
621240116Smarcel    ATF_TP_ADD_TC(tp, cstring);
622240116Smarcel    ATF_TP_ADD_TC(tp, length);
623240116Smarcel    ATF_TP_ADD_TC(tp, rfind_ch);
624240116Smarcel
625240116Smarcel    /* Modifiers. */
626240116Smarcel    ATF_TP_ADD_TC(tp, append_ap);
627240116Smarcel    ATF_TP_ADD_TC(tp, append_fmt);
628240116Smarcel    ATF_TP_ADD_TC(tp, clear);
629240116Smarcel    ATF_TP_ADD_TC(tp, prepend_ap);
630240116Smarcel    ATF_TP_ADD_TC(tp, prepend_fmt);
631240116Smarcel
632240116Smarcel    /* Operators. */
633240116Smarcel    ATF_TP_ADD_TC(tp, equal_cstring);
634240116Smarcel    ATF_TP_ADD_TC(tp, equal_dynstr);
635240116Smarcel
636240116Smarcel    return atf_no_error();
637240116Smarcel}
638