1//
2// Automated Testing Framework (atf)
3//
4// Copyright (c) 2007 The NetBSD Foundation, Inc.
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
10// 1. Redistributions of source code must retain the above copyright
11//    notice, this list of conditions and the following disclaimer.
12// 2. Redistributions in binary form must reproduce the above copyright
13//    notice, this list of conditions and the following disclaimer in the
14//    documentation and/or other materials provided with the distribution.
15//
16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29
30#include <cstring>
31#include <set>
32#include <vector>
33
34#include "../macros.hpp"
35
36#include "text.hpp"
37
38// ------------------------------------------------------------------------
39// Test cases for the free functions.
40// ------------------------------------------------------------------------
41
42ATF_TEST_CASE(duplicate);
43ATF_TEST_CASE_HEAD(duplicate)
44{
45    set_md_var("descr", "Tests the duplicate function");
46}
47ATF_TEST_CASE_BODY(duplicate)
48{
49    using atf::text::duplicate;
50
51    const char* orig = "foo";
52
53    char* copy = duplicate(orig);
54    ATF_REQUIRE_EQ(std::strlen(copy), 3);
55    ATF_REQUIRE(std::strcmp(copy, "foo") == 0);
56
57    std::strcpy(copy, "bar");
58    ATF_REQUIRE(std::strcmp(copy, "bar") == 0);
59    ATF_REQUIRE(std::strcmp(orig, "foo") == 0);
60}
61
62ATF_TEST_CASE(join);
63ATF_TEST_CASE_HEAD(join)
64{
65    set_md_var("descr", "Tests the join function");
66}
67ATF_TEST_CASE_BODY(join)
68{
69    using atf::text::join;
70
71    // First set of tests using a non-sorted collection, std::vector.
72    {
73        std::vector< std::string > words;
74        std::string str;
75
76        words.clear();
77        str = join(words, ",");
78        ATF_REQUIRE_EQ(str, "");
79
80        words.clear();
81        words.push_back("");
82        str = join(words, ",");
83        ATF_REQUIRE_EQ(str, "");
84
85        words.clear();
86        words.push_back("");
87        words.push_back("");
88        str = join(words, ",");
89        ATF_REQUIRE_EQ(str, ",");
90
91        words.clear();
92        words.push_back("foo");
93        words.push_back("");
94        words.push_back("baz");
95        str = join(words, ",");
96        ATF_REQUIRE_EQ(str, "foo,,baz");
97
98        words.clear();
99        words.push_back("foo");
100        words.push_back("bar");
101        words.push_back("baz");
102        str = join(words, ",");
103        ATF_REQUIRE_EQ(str, "foo,bar,baz");
104    }
105
106    // Second set of tests using a sorted collection, std::set.
107    {
108        std::set< std::string > words;
109        std::string str;
110
111        words.clear();
112        str = join(words, ",");
113        ATF_REQUIRE_EQ(str, "");
114
115        words.clear();
116        words.insert("");
117        str = join(words, ",");
118        ATF_REQUIRE_EQ(str, "");
119
120        words.clear();
121        words.insert("foo");
122        words.insert("");
123        words.insert("baz");
124        str = join(words, ",");
125        ATF_REQUIRE_EQ(str, ",baz,foo");
126
127        words.clear();
128        words.insert("foo");
129        words.insert("bar");
130        words.insert("baz");
131        str = join(words, ",");
132        ATF_REQUIRE_EQ(str, "bar,baz,foo");
133    }
134}
135
136ATF_TEST_CASE(match);
137ATF_TEST_CASE_HEAD(match)
138{
139    set_md_var("descr", "Tests the match function");
140}
141ATF_TEST_CASE_BODY(match)
142{
143    using atf::text::match;
144
145    ATF_REQUIRE_THROW(std::runtime_error, match("", "["));
146
147    ATF_REQUIRE(match("", ""));
148    ATF_REQUIRE(!match("foo", ""));
149
150    ATF_REQUIRE(match("", ".*"));
151    ATF_REQUIRE(match("", "[a-z]*"));
152
153    ATF_REQUIRE(match("hello", "hello"));
154    ATF_REQUIRE(match("hello", "[a-z]+"));
155    ATF_REQUIRE(match("hello", "^[a-z]+$"));
156
157    ATF_REQUIRE(!match("hello", "helooo"));
158    ATF_REQUIRE(!match("hello", "[a-z]+5"));
159    ATF_REQUIRE(!match("hello", "^ [a-z]+$"));
160}
161
162ATF_TEST_CASE(split);
163ATF_TEST_CASE_HEAD(split)
164{
165    set_md_var("descr", "Tests the split function");
166}
167ATF_TEST_CASE_BODY(split)
168{
169    using atf::text::split;
170
171    std::vector< std::string > words;
172
173    words = split("", " ");
174    ATF_REQUIRE_EQ(words.size(), 0);
175
176    words = split(" ", " ");
177    ATF_REQUIRE_EQ(words.size(), 0);
178
179    words = split("    ", " ");
180    ATF_REQUIRE_EQ(words.size(), 0);
181
182    words = split("a b", " ");
183    ATF_REQUIRE_EQ(words.size(), 2);
184    ATF_REQUIRE_EQ(words[0], "a");
185    ATF_REQUIRE_EQ(words[1], "b");
186
187    words = split("a b c d", " ");
188    ATF_REQUIRE_EQ(words.size(), 4);
189    ATF_REQUIRE_EQ(words[0], "a");
190    ATF_REQUIRE_EQ(words[1], "b");
191    ATF_REQUIRE_EQ(words[2], "c");
192    ATF_REQUIRE_EQ(words[3], "d");
193
194    words = split("foo bar", " ");
195    ATF_REQUIRE_EQ(words.size(), 2);
196    ATF_REQUIRE_EQ(words[0], "foo");
197    ATF_REQUIRE_EQ(words[1], "bar");
198
199    words = split("foo bar baz foobar", " ");
200    ATF_REQUIRE_EQ(words.size(), 4);
201    ATF_REQUIRE_EQ(words[0], "foo");
202    ATF_REQUIRE_EQ(words[1], "bar");
203    ATF_REQUIRE_EQ(words[2], "baz");
204    ATF_REQUIRE_EQ(words[3], "foobar");
205
206    words = split(" foo bar", " ");
207    ATF_REQUIRE_EQ(words.size(), 2);
208    ATF_REQUIRE_EQ(words[0], "foo");
209    ATF_REQUIRE_EQ(words[1], "bar");
210
211    words = split("foo  bar", " ");
212    ATF_REQUIRE_EQ(words.size(), 2);
213    ATF_REQUIRE_EQ(words[0], "foo");
214    ATF_REQUIRE_EQ(words[1], "bar");
215
216    words = split("foo bar ", " ");
217    ATF_REQUIRE_EQ(words.size(), 2);
218    ATF_REQUIRE_EQ(words[0], "foo");
219    ATF_REQUIRE_EQ(words[1], "bar");
220
221    words = split("  foo  bar  ", " ");
222    ATF_REQUIRE_EQ(words.size(), 2);
223    ATF_REQUIRE_EQ(words[0], "foo");
224    ATF_REQUIRE_EQ(words[1], "bar");
225}
226
227ATF_TEST_CASE(split_delims);
228ATF_TEST_CASE_HEAD(split_delims)
229{
230    set_md_var("descr", "Tests the split function using different delimiters");
231}
232ATF_TEST_CASE_BODY(split_delims)
233{
234    using atf::text::split;
235
236    std::vector< std::string > words;
237
238    words = split("", "/");
239    ATF_REQUIRE_EQ(words.size(), 0);
240
241    words = split(" ", "/");
242    ATF_REQUIRE_EQ(words.size(), 1);
243    ATF_REQUIRE_EQ(words[0], " ");
244
245    words = split("    ", "/");
246    ATF_REQUIRE_EQ(words.size(), 1);
247    ATF_REQUIRE_EQ(words[0], "    ");
248
249    words = split("a/b", "/");
250    ATF_REQUIRE_EQ(words.size(), 2);
251    ATF_REQUIRE_EQ(words[0], "a");
252    ATF_REQUIRE_EQ(words[1], "b");
253
254    words = split("aLONGDELIMbcdLONGDELIMef", "LONGDELIM");
255    ATF_REQUIRE_EQ(words.size(), 3);
256    ATF_REQUIRE_EQ(words[0], "a");
257    ATF_REQUIRE_EQ(words[1], "bcd");
258    ATF_REQUIRE_EQ(words[2], "ef");
259}
260
261ATF_TEST_CASE(trim);
262ATF_TEST_CASE_HEAD(trim)
263{
264    set_md_var("descr", "Tests the trim function");
265}
266ATF_TEST_CASE_BODY(trim)
267{
268    using atf::text::trim;
269
270    ATF_REQUIRE_EQ(trim(""), "");
271    ATF_REQUIRE_EQ(trim(" "), "");
272    ATF_REQUIRE_EQ(trim("\t"), "");
273
274    ATF_REQUIRE_EQ(trim(" foo"), "foo");
275    ATF_REQUIRE_EQ(trim("\t foo"), "foo");
276    ATF_REQUIRE_EQ(trim(" \tfoo"), "foo");
277    ATF_REQUIRE_EQ(trim("foo\t "), "foo");
278    ATF_REQUIRE_EQ(trim("foo \t"), "foo");
279
280    ATF_REQUIRE_EQ(trim("foo bar"), "foo bar");
281    ATF_REQUIRE_EQ(trim("\t foo bar"), "foo bar");
282    ATF_REQUIRE_EQ(trim(" \tfoo bar"), "foo bar");
283    ATF_REQUIRE_EQ(trim("foo bar\t "), "foo bar");
284    ATF_REQUIRE_EQ(trim("foo bar \t"), "foo bar");
285}
286
287ATF_TEST_CASE(to_bool);
288ATF_TEST_CASE_HEAD(to_bool)
289{
290    set_md_var("descr", "Tests the to_string function");
291}
292ATF_TEST_CASE_BODY(to_bool)
293{
294    using atf::text::to_bool;
295
296    ATF_REQUIRE(to_bool("true"));
297    ATF_REQUIRE(to_bool("TRUE"));
298    ATF_REQUIRE(to_bool("yes"));
299    ATF_REQUIRE(to_bool("YES"));
300
301    ATF_REQUIRE(!to_bool("false"));
302    ATF_REQUIRE(!to_bool("FALSE"));
303    ATF_REQUIRE(!to_bool("no"));
304    ATF_REQUIRE(!to_bool("NO"));
305
306    ATF_REQUIRE_THROW(std::runtime_error, to_bool(""));
307    ATF_REQUIRE_THROW(std::runtime_error, to_bool("tru"));
308    ATF_REQUIRE_THROW(std::runtime_error, to_bool("true2"));
309    ATF_REQUIRE_THROW(std::runtime_error, to_bool("fals"));
310    ATF_REQUIRE_THROW(std::runtime_error, to_bool("false2"));
311}
312
313ATF_TEST_CASE(to_bytes);
314ATF_TEST_CASE_HEAD(to_bytes)
315{
316    set_md_var("descr", "Tests the to_bytes function");
317}
318ATF_TEST_CASE_BODY(to_bytes)
319{
320    using atf::text::to_bytes;
321
322    ATF_REQUIRE_EQ(0, to_bytes("0"));
323    ATF_REQUIRE_EQ(12345, to_bytes("12345"));
324    ATF_REQUIRE_EQ(2 * 1024, to_bytes("2k"));
325    ATF_REQUIRE_EQ(4 * 1024 * 1024, to_bytes("4m"));
326    ATF_REQUIRE_EQ(int64_t(8) * 1024 * 1024 * 1024, to_bytes("8g"));
327    ATF_REQUIRE_EQ(int64_t(16) * 1024 * 1024 * 1024 * 1024, to_bytes("16t"));
328
329    ATF_REQUIRE_THROW_RE(std::runtime_error, "Empty", to_bytes(""));
330    ATF_REQUIRE_THROW_RE(std::runtime_error, "Unknown size unit 'd'",
331                         to_bytes("12d"));
332    ATF_REQUIRE_THROW(std::runtime_error, to_bytes(" "));
333    ATF_REQUIRE_THROW(std::runtime_error, to_bytes(" k"));
334}
335
336ATF_TEST_CASE(to_string);
337ATF_TEST_CASE_HEAD(to_string)
338{
339    set_md_var("descr", "Tests the to_string function");
340}
341ATF_TEST_CASE_BODY(to_string)
342{
343    using atf::text::to_string;
344
345    ATF_REQUIRE_EQ(to_string('a'), "a");
346    ATF_REQUIRE_EQ(to_string("a"), "a");
347    ATF_REQUIRE_EQ(to_string(5), "5");
348}
349
350ATF_TEST_CASE(to_type);
351ATF_TEST_CASE_HEAD(to_type)
352{
353    set_md_var("descr", "Tests the to_type function");
354}
355ATF_TEST_CASE_BODY(to_type)
356{
357    using atf::text::to_type;
358
359    ATF_REQUIRE_EQ(to_type< int >("0"), 0);
360    ATF_REQUIRE_EQ(to_type< int >("1234"), 1234);
361    ATF_REQUIRE_THROW(std::runtime_error, to_type< int >("   "));
362    ATF_REQUIRE_THROW(std::runtime_error, to_type< int >("0 a"));
363    ATF_REQUIRE_THROW(std::runtime_error, to_type< int >("a"));
364
365    ATF_REQUIRE_EQ(to_type< float >("0.5"), 0.5);
366    ATF_REQUIRE_EQ(to_type< float >("1234.5"), 1234.5);
367    ATF_REQUIRE_THROW(std::runtime_error, to_type< float >("0.5 a"));
368    ATF_REQUIRE_THROW(std::runtime_error, to_type< float >("a"));
369
370    ATF_REQUIRE_EQ(to_type< std::string >("a"), "a");
371}
372
373// ------------------------------------------------------------------------
374// Main.
375// ------------------------------------------------------------------------
376
377ATF_INIT_TEST_CASES(tcs)
378{
379    // Add the test cases for the free functions.
380    ATF_ADD_TEST_CASE(tcs, duplicate);
381    ATF_ADD_TEST_CASE(tcs, join);
382    ATF_ADD_TEST_CASE(tcs, match);
383    ATF_ADD_TEST_CASE(tcs, split);
384    ATF_ADD_TEST_CASE(tcs, split_delims);
385    ATF_ADD_TEST_CASE(tcs, trim);
386    ATF_ADD_TEST_CASE(tcs, to_bool);
387    ATF_ADD_TEST_CASE(tcs, to_bytes);
388    ATF_ADD_TEST_CASE(tcs, to_string);
389    ATF_ADD_TEST_CASE(tcs, to_type);
390}
391