1/**
2 * @file string_manip_tests.cpp
3 *
4 * @remark Copyright 2003 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author John Levon
8 * @author Philippe Elie
9 */
10
11#include <stdlib.h>
12
13#include <algorithm>
14#include <iterator>
15#include <iostream>
16#include <utility>
17
18#include "string_manip.h"
19
20using namespace std;
21
22template <typename Input, typename Output>
23struct input_output {
24	Input input;
25	Output output;
26};
27
28
29template <typename Input, typename Output, typename Result>
30static void check_result(char const * fct_name, Input const & input,
31		  Output const & output, Result const & result)
32{
33	if (result != output) {
34		cerr << fct_name << ": \n"
35		     << "for:\n\"" << input << "\"\n"
36		     << "expect:\n\"" << output << "\"\n"
37		     << "found:\n\"" << result << "\"\n";
38		exit(EXIT_FAILURE);
39	}
40}
41
42
43static input_output<char const*, char const*> expect_erase[] =
44{
45	{ "", "" },
46	{ ";;;", "" },
47	{ "ab;;;cd", "cd" },
48	{ ";;;cd", "cd" },
49	{ "ab;;;", "" },
50	{ 0, 0 }
51};
52
53static void erase_to_last_of_tests()
54{
55	input_output<char const *, char const*> const * cur;
56	for (cur = expect_erase; cur->input; ++cur) {
57		string result = erase_to_last_of(cur->input, ';');
58		check_result("erase_to_last_of()", cur->input, cur->output,
59			     result);
60	}
61}
62
63
64static input_output<char const *, pair<string, string> > expect_split[] =
65{
66#define MAKE_PAIR(a, b)  make_pair(string(a), string(b))
67	{ "ab;cd", MAKE_PAIR("ab", "cd") },
68	{ ";cd",   MAKE_PAIR("",   "cd") },
69	{ "ab;",   MAKE_PAIR("ab", "")   },
70	{ "b;d",   MAKE_PAIR("b",  "d")  },
71	{ ";d",    MAKE_PAIR("",   "d")  },
72	{ "a;",    MAKE_PAIR("a",  "")   },
73	{ ";",     MAKE_PAIR("",   "")   },
74	{ "",      MAKE_PAIR("",   "")   },
75	{ 0,       MAKE_PAIR("",   "")   }
76#undef MAKE_PAIR
77};
78
79static void split_tests()
80{
81	input_output<char const *, pair<string, string> > const * cur;
82	for (cur = expect_split; cur->input; ++cur) {
83		string temp = cur->input;
84		string result = split(temp, ';');
85		check_result("split()", cur->input, cur->output.first, temp);
86		check_result("split()", cur->input, cur->output.second, result);
87	}
88}
89
90static input_output<char const *, pair<string, bool> > expect_is_prefix[] =
91{
92#define MAKE_PAIR(a, b)  make_pair(string(a), b)
93	{ "abcd", MAKE_PAIR("abc", true) },
94	{ "abcd", MAKE_PAIR("ac", false) },
95	{ "babcd", MAKE_PAIR("abc", false) },
96	// these invoke undefined behavior from is_prefix, we keep them
97	// for the record.
98//	{ "babcd", MAKE_PAIR("", false) },
99//	{ "", MAKE_PAIR("", false) },
100	{ 0, MAKE_PAIR("", true) }
101#undef MAKE_PAIR
102};
103
104static void is_prefix_tests()
105{
106	input_output<char const *, pair<string, bool> > const * cur;
107	for (cur = expect_is_prefix; cur->input; ++cur) {
108		bool result = is_prefix(cur->input, cur->output.first);
109		if (result != cur->output.second) {
110			cerr << "is_prefix(" << cur->input << ", "
111			     << cur->output.first << ") "
112			     << "return " << result << endl;
113			exit(EXIT_FAILURE);
114		}
115	}
116}
117
118
119static const size_t max_token = 8;
120static input_output<char const *, char const *[max_token]> expect_separate_token[] =
121{
122	{ "aa", { "aa" } },
123	{ "a\\c", { "a\\c" } },
124	{ "a\\\\c", { "a\\\\c" } },
125	{ "a\\\\c\\", { "a\\\\c\\" } },
126	{ "ab;cd;ef;gh", { "ab", "cd", "ef", "gh" } },
127	{ "ab\\;cd", { "ab;cd" } },
128	{ "a;a", { "a", "a" } },
129	{ ";a", { "", "a" } },
130	{ ";", { "", "" } },
131	{ ";;", { "", "", "" } },
132	{ 0, { 0, } }
133};
134
135
136static void separate_token_tests()
137{
138	input_output<char const *, char const *[max_token]> const * cur;
139	for (cur = expect_separate_token; cur->input; ++cur) {
140		vector<string> result = separate_token(cur->input, ';');
141		if (result.size() > max_token) {
142			cerr << "separate_token(): too many token\n"
143			     << "input:\n"
144			     << '"' << cur->input << "\"\n"
145			     << "output\n";
146			copy(result.begin(), result.end(),
147			     ostream_iterator<string>(cerr, "\n"));
148			exit(EXIT_FAILURE);
149		}
150		for (size_t i = 0; i < result.size(); ++i) {
151			if (result[i] != cur->output[i]) {
152				cerr << "separate_token():\n"
153				     << "input:\n"
154				     << cur->input << endl;
155				cerr << "expect:\n";
156				for (size_t i = 0; i < max_token; ++i) {
157					if (!cur->output[i])
158						break;
159					cerr << cur->output[i] << endl;
160				}
161				cerr << "output:\n";
162				copy(result.begin(), result.end(),
163				     ostream_iterator<string>(cerr, "\n"));
164				exit(EXIT_FAILURE);
165			}
166		}
167	}
168}
169
170
171static input_output<char const *, char const *> expect_rtrim[] =
172{
173	{ "abc", "abc" },
174	{ "abc  ", "abc" },
175	{ " abc  ", " abc" },
176	{ " abc \t \t", " abc" },
177	{ " ", "" },
178	{ "\t \t", "" },
179	{ "", "" },
180	{ 0, 0 }
181};
182
183static void rtrim_tests()
184{
185	input_output<char const *, char const*> const * cur;
186	for (cur = expect_rtrim; cur->input; ++cur) {
187		string result = rtrim(cur->input);
188		check_result("rtrim()", cur->input, cur->output, result);
189	}
190}
191
192
193static input_output<char const *, char const *> expect_ltrim[] =
194{
195	{ "abc", "abc" },
196	{ "abc ", "abc " },
197	{ " abc ", "abc " },
198	{ "\t  \tabc ", "abc " },
199	{ " ", "" },
200	{ "\t \t", "" },
201	{ "", "" },
202	{ 0, 0 }
203};
204
205static void ltrim_tests()
206{
207	input_output<char const *, char const*> const * cur;
208	for (cur = expect_ltrim; cur->input; ++cur) {
209		string result = ltrim(cur->input);
210		check_result("ltrim()", cur->input, cur->output, result);
211	}
212}
213
214
215static input_output<char const *, char const *> expect_trim[] =
216{
217	{ "abc", "abc" },
218	{ "abc ", "abc" },
219	{ " abc ", "abc" },
220	{ "\t  \tabc \t", "abc" },
221	{ " ", "" },
222	{ "\t \t", "" },
223	{ "", "" },
224	{ 0, 0 }
225};
226
227static void trim_tests()
228{
229	input_output<char const *, char const*> const * cur;
230	for (cur = expect_trim; cur->input; ++cur) {
231		string result = trim(cur->input);
232		check_result("trim()", cur->input, cur->output, result);
233	}
234}
235
236
237static input_output<double, char const *> expect_format_percent[] =
238{
239	{ 2.2,        " 2.2000" },
240	{ 0,          "      0" },
241	{ 100.00,     "100.000" },
242	{ 99.99999,   "100.000" },
243	{ 0.00000344, "3.4e-06" },
244	// FIXME, must be 3.e-124 but output is 3.4e-124
245//	{ 0.34e-123,  "3.e-124" },
246	{ -1.0, 0 }
247};
248
249static void format_percent_tests()
250{
251	input_output<double, char const*> const * cur;
252	for (cur = expect_format_percent; cur->input != -1.0; ++cur) {
253		string result = format_percent(cur->input, percent_int_width,
254		      percent_fract_width);
255		check_result("format_percent()", cur->input, cur->output,
256			     result);
257	}
258}
259
260
261static input_output<unsigned int, char const *> expect_from_str_to_uint[] =
262{
263	{ 123, "123" },
264	{ 33, "33" },
265	{ 0, "0" },
266	{ 0, 0 }
267};
268
269static void tostr_tests()
270{
271	input_output<unsigned int, char const *> const * cur;
272	for (cur = expect_from_str_to_uint; cur->output; ++cur) {
273		string result = op_lexical_cast<string>(cur->input);
274		check_result("op_lexical_cast()", cur->input,
275		     cur->output, result);
276	}
277}
278
279static void touint_tests()
280{
281	// reversed input/output of the previous tests
282	input_output<unsigned int, char const *> const * cur;
283	for (cur = expect_from_str_to_uint; cur->output; ++cur) {
284		unsigned int result =
285			op_lexical_cast<unsigned int>(cur->output);
286		check_result("op_lexical_cast()", cur->output, cur->input,
287		     result);
288	}
289}
290
291
292static input_output<char const*, bool> expect_from_str_to_bool[] =
293{
294	{ "0", false },
295	{ "1", true },
296	{ 0, 0 }
297};
298
299static void tobool_tests()
300{
301	input_output<char const *, bool> const * cur;
302	for (cur = expect_from_str_to_bool; cur->input; ++cur) {
303		bool result = op_lexical_cast<bool>(cur->input);
304		check_result("op_lexical_cast()", cur->input, cur->output,
305		     result);
306	}
307}
308
309// FIXME: more op_lexical_cast<> tests
310
311int main()
312{
313	erase_to_last_of_tests();
314	tostr_tests();
315	touint_tests();
316	tobool_tests();
317	split_tests();
318	is_prefix_tests();
319	separate_token_tests();
320	rtrim_tests();
321	ltrim_tests();
322	trim_tests();
323	format_percent_tests();
324	return EXIT_SUCCESS;
325}
326