1 #include <boost/test/unit_test.hpp>
3 #include "zypp/base/LogTools.h"
4 #include "zypp/base/String.h"
6 using boost::unit_test::test_suite;
7 using boost::unit_test::test_case;
8 using namespace boost::unit_test;
12 using namespace zypp::str;
14 #define RXspecial "\\^.[$()|*+?{"
16 BOOST_AUTO_TEST_CASE(str2rx)
20 for ( const char * ch = RXspecial; *ch; ++ch )
23 BOOST_CHECK_EQUAL( str::rxEscapeStr( s ), x );
27 BOOST_AUTO_TEST_CASE(glob2rx)
32 for ( const char * ch = RXspecial; *ch; ++ch )
36 BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "." );
37 else if ( *ch == '*' )
38 BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), ".*" );
39 else if ( *ch == '[' )
40 BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\[" ); // no closing ] so it is literal
41 else if ( *ch == '\\' )
42 BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\" ); // actually an input error as "\" is not a valid GLOB
46 BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), x );
49 std::string a( str::rxEscapeStr( RXspecial ) ); // all rx/glob special chars are literally (\-escaped)
50 BOOST_CHECK_EQUAL( str::rxEscapeGlob( a ), a ); // nothing more to escape.
52 // character class: contains "]["
53 BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[][]" ), "[][]" );
54 BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^][]" ), "[^][]" );
55 BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!][]" ), "[^][]" ); // glob allows ! and ^ to negate a cclass
57 // no character class: no closing ']' so take it literally (the ] would be member of the cclass, not the closing ])
58 BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[]" ), "\\[]" );
59 BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!]" ), "\\[!]" );
60 BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^]" ), "\\[\\^]" );
64 BOOST_AUTO_TEST_CASE(gsubTest)
67 string news = "new string";
69 BOOST_CHECK_EQUAL(gsub("test olds string",olds,news), "test new string string");
70 BOOST_CHECK_EQUAL(gsub("no string",olds,news),"no string");
71 BOOST_CHECK_EQUAL(gsub("oldsolds",olds,news),"new stringnew string");
74 BOOST_AUTO_TEST_CASE(replaceAllTest)
77 string news = "new string";
80 tests = "test olds string";
81 replaceAll(tests,olds,news);
82 BOOST_CHECK_EQUAL(tests, "test new string string");
85 replaceAll(tests,olds,news);
86 BOOST_CHECK_EQUAL(tests, "no string");
89 replaceAll(tests,olds,news);
90 BOOST_CHECK_EQUAL(tests, "new stringnew string");
93 BOOST_AUTO_TEST_CASE(testsplitEscaped)
95 string s( "simple non-escaped string" );
98 splitEscaped( s, std::back_inserter(v) );
99 BOOST_CHECK_EQUAL( v.size(), 3 );
100 BOOST_CHECK_EQUAL( v[0], "simple" );
101 BOOST_CHECK_EQUAL( v[1], "non-escaped" );
102 BOOST_CHECK_EQUAL( v[2], "string" );
105 s = string( "\"escaped sentence \"" );
106 splitEscaped( s, std::back_inserter(v) );
107 BOOST_CHECK_EQUAL( v.size(), 1 );
108 BOOST_CHECK_EQUAL( v[0], "escaped sentence " );
111 s = string( "\"escaped \\\\sent\\\"ence \\\\\"" );
112 splitEscaped( s, std::back_inserter(v) );
113 BOOST_CHECK_EQUAL( v.size(), 1 );
114 BOOST_CHECK_EQUAL( v[0], "escaped \\sent\"ence \\" );
117 s = string( "escaped sentence\\ with\\ space" );
118 splitEscaped( s, std::back_inserter(v) );
119 BOOST_CHECK_EQUAL( v.size(), 2 );
120 BOOST_CHECK_EQUAL( v[0], "escaped" );
121 BOOST_CHECK_EQUAL( v[1], "sentence with space" );
125 s = "some line \"\" foo\\ a foo\\\\ b";
126 str::splitEscaped( s, std::back_inserter(v) );
127 BOOST_CHECK_EQUAL( v.size(), 6 );
128 BOOST_CHECK_EQUAL( v[0], "some" );
129 BOOST_CHECK_EQUAL( v[1], "line" );
130 BOOST_CHECK_EQUAL( v[2], "" );
131 BOOST_CHECK_EQUAL( v[3], "foo a" );
132 BOOST_CHECK_EQUAL( v[4], "foo\\" );
133 BOOST_CHECK_EQUAL( v[5], "b" );
134 BOOST_CHECK_EQUAL( s, str::joinEscaped( v.begin(), v.end() ) );
136 // split - join using alternate sepchar
137 s = str::joinEscaped( v.begin(), v.end(), 'o' );
139 str::splitEscaped( s, std::back_inserter(v), "o" );
140 BOOST_CHECK_EQUAL( v.size(), 6 );
141 BOOST_CHECK_EQUAL( v[0], "some" );
142 BOOST_CHECK_EQUAL( v[1], "line" );
143 BOOST_CHECK_EQUAL( v[2], "" );
144 BOOST_CHECK_EQUAL( v[3], "foo a" );
145 BOOST_CHECK_EQUAL( v[4], "foo\\" );
146 BOOST_CHECK_EQUAL( v[5], "b" );
147 BOOST_CHECK_EQUAL( s, str::joinEscaped( v.begin(), v.end(), 'o' ) );
150 BOOST_AUTO_TEST_CASE(bnc_909772)
152 // While \-escaping processes single-quote, double-quote, backslash and sepchar[ ]
153 // deescaping failed to process the quotes correctly.
155 std::vector<std::string> v;
159 v.push_back("'\" \\");
160 v.push_back("\\'\\\"\\ \\\\");
161 s = str::joinEscaped( v.begin(), v.end() );
162 BOOST_CHECK_EQUAL( s, "\"\"" " " "\\'\\\"\\ \\\\" " " "\\\\\\'\\\\\\\"\\\\\\ \\\\\\\\" );
165 s += "'" "\\\\\" \\ \\\\" "'\\ single"; // single quote: all literal, no ' inside
168 s += "\"" "\\'\\\" \\ \\\\" "\"\\ double";// double quote: all literal except \\ \"
171 splitEscaped( s, std::back_inserter(v) );
172 BOOST_CHECK_EQUAL( v.size(), 5 );
173 BOOST_CHECK_EQUAL( v[0], "" );
174 BOOST_CHECK_EQUAL( v[1], "'\" \\" );
175 BOOST_CHECK_EQUAL( v[2], "\\'\\\"\\ \\\\" );
176 BOOST_CHECK_EQUAL( v[3], "\\\\\" \\ \\\\ single" );
177 BOOST_CHECK_EQUAL( v[4], "\\'\" \\ \\ double" );
180 BOOST_AUTO_TEST_CASE(testsplitEscapedWithEmpty)
182 string s( "simple:non-escaped:string" );
185 BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3);
186 BOOST_CHECK_EQUAL(v.size(), 3);
189 s = "non-escaped:with::spaces:";
190 BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 5);
191 BOOST_CHECK_EQUAL(v.size(), 5);
195 BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3);
196 BOOST_CHECK_EQUAL(v.size(), 3);
199 s = ":escaped::with\\:spaces";
200 BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 4);
201 BOOST_CHECK_EQUAL(v.size(), 4);
204 BOOST_AUTO_TEST_CASE(test_escape)
206 string badass = "bad|ass\\|worse";
207 string escaped = str::escape(badass, '|');
209 BOOST_CHECK_EQUAL( escaped, "bad\\|ass\\\\\\|worse" );
212 BOOST_AUTO_TEST_CASE(conversions)
214 BOOST_CHECK_EQUAL(str::numstring(42), "42");
215 BOOST_CHECK_EQUAL(str::numstring(42, 6), " 42");
216 BOOST_CHECK_EQUAL(str::numstring(42, -6), "42 ");
218 BOOST_CHECK_EQUAL(str::hexstring(42), "0x0000002a");
219 BOOST_CHECK_EQUAL(str::hexstring(42, 6), "0x002a");
220 BOOST_CHECK_EQUAL(str::hexstring(42, -6), "0x2a ");
222 BOOST_CHECK_EQUAL(str::octstring(42), "00052");
223 BOOST_CHECK_EQUAL(str::octstring(42, 6), "000052");
224 BOOST_CHECK_EQUAL(str::octstring(42, -6), "052 ");
226 BOOST_CHECK_EQUAL(str::strtonum<int>("42"), 42);
228 BOOST_CHECK_EQUAL(str::toLower("This IS A TeST"), "this is a test");
229 BOOST_CHECK_EQUAL(str::toUpper("This IS A TeST"), "THIS IS A TEST");
230 BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0);
232 BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0);
233 BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0);
236 BOOST_AUTO_TEST_CASE(conversions_to_bool)
238 // true iff true-string {1,on,yes,true}
239 BOOST_CHECK_EQUAL( str::strToTrue("1"), true );
240 BOOST_CHECK_EQUAL( str::strToTrue("42"), true );
241 BOOST_CHECK_EQUAL( str::strToTrue("ON"), true );
242 BOOST_CHECK_EQUAL( str::strToTrue("YES"), true );
243 BOOST_CHECK_EQUAL( str::strToTrue("TRUE"), true );
244 BOOST_CHECK_EQUAL( str::strToTrue("0"), false );
245 BOOST_CHECK_EQUAL( str::strToTrue("OFF"), false );
246 BOOST_CHECK_EQUAL( str::strToTrue("NO"), false );
247 BOOST_CHECK_EQUAL( str::strToTrue("FALSE"), false );
248 BOOST_CHECK_EQUAL( str::strToTrue(""), false );
249 BOOST_CHECK_EQUAL( str::strToTrue("foo"), false );
251 // false iff false-string {0,off,no,false}
252 BOOST_CHECK_EQUAL( str::strToFalse("1"), true );
253 BOOST_CHECK_EQUAL( str::strToFalse("42"), true );
254 BOOST_CHECK_EQUAL( str::strToFalse("ON"), true );
255 BOOST_CHECK_EQUAL( str::strToFalse("YES"), true );
256 BOOST_CHECK_EQUAL( str::strToFalse("TRUE"), true );
257 BOOST_CHECK_EQUAL( str::strToFalse("0"), false );
258 BOOST_CHECK_EQUAL( str::strToFalse("OFF"), false );
259 BOOST_CHECK_EQUAL( str::strToFalse("NO"), false );
260 BOOST_CHECK_EQUAL( str::strToFalse("FALSE"), false );
261 BOOST_CHECK_EQUAL( str::strToFalse(""), true );
262 BOOST_CHECK_EQUAL( str::strToFalse("foo"), true );
264 // true iff true-string
265 BOOST_CHECK_EQUAL( str::strToBool("TRUE", false), true );
266 BOOST_CHECK_EQUAL( str::strToBool("FALSE", false), false );
267 BOOST_CHECK_EQUAL( str::strToBool("", false), false );
268 BOOST_CHECK_EQUAL( str::strToBool("foo", false), false );
270 // false iff false-string
271 BOOST_CHECK_EQUAL( str::strToBool("TRUE", true), true );
272 BOOST_CHECK_EQUAL( str::strToBool("FALSE", true), false );
273 BOOST_CHECK_EQUAL( str::strToBool("", true), true );
274 BOOST_CHECK_EQUAL( str::strToBool("foo", true), true );
276 // true/false iff true/false-string, else unchanged
278 ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("TRUE", ret), true );
279 ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("FALSE", ret), false );
280 ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("", ret), true );
281 ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("foo", ret), true );
283 ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("TRUE", ret), true );
284 ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("FALSE", ret), false );
285 ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("", ret), false );
286 ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("foo", ret), false );
289 BOOST_AUTO_TEST_CASE(operations)
291 BOOST_CHECK_EQUAL(str::ltrim(" \t f \t ffo \t "), "f \t ffo \t ");
292 BOOST_CHECK_EQUAL(str::rtrim(" \t f \t ffo \t "), " \t f \t ffo");
293 BOOST_CHECK_EQUAL(str::trim(" \t f \t ffo \t "), "f \t ffo");
297 string tostrip(" Oh! la la ");
298 string word( str::stripFirstWord(tostrip, true) ); // ltrim first
299 BOOST_CHECK_EQUAL(word, "Oh!");
300 BOOST_CHECK_EQUAL(tostrip, "la la ");
303 string tostrip(" Oh! la la ");
304 string word( str::stripFirstWord(tostrip, false) ); // no ltrim first
305 BOOST_CHECK_EQUAL(word, "");
306 BOOST_CHECK_EQUAL(tostrip, "Oh! la la ");
311 string tostrip(" Oh! la la ");
312 string word( str::stripLastWord(tostrip, true) ); // rtrim first
313 BOOST_CHECK_EQUAL(word, "la");
314 BOOST_CHECK_EQUAL(tostrip, " Oh! la");
317 string tostrip(" Oh! la la ");
318 string word( str::stripLastWord(tostrip, false) ); // no rtrim first
319 BOOST_CHECK_EQUAL(word, "");
320 BOOST_CHECK_EQUAL(tostrip, " Oh! la la");
324 BOOST_AUTO_TEST_CASE(prefix_suffix)
326 BOOST_CHECK( str::hasPrefix("abcXabcYabc", "abcX") );
327 BOOST_CHECK( str::hasSuffix("abcXabcYabc", "Yabc") );
329 BOOST_CHECK_EQUAL( str::stripPrefix("abcXabcYabc", "abcX"), "abcYabc" );
330 BOOST_CHECK_EQUAL( str::stripSuffix("abcXabcYabc", "Yabc"), "abcXabc" );
332 BOOST_CHECK( ! str::hasPrefix("abcXabcYabc", "ac") );
333 BOOST_CHECK( ! str::hasSuffix("abcXabcYabc", "ac") );
335 BOOST_CHECK_EQUAL( str::stripPrefix("abcXabcYabc", "ac"), "abcXabcYabc" );
336 BOOST_CHECK_EQUAL( str::stripSuffix("abcXabcYabc", "ac"), "abcXabcYabc" );
338 BOOST_CHECK( str::startsWith("abcXabcYabc", "abc") );
339 BOOST_CHECK( str::endsWith("abcXabcYabc", "abc") );
341 BOOST_CHECK( str::contains("abcXabcYabc", "XabcY") );
342 BOOST_CHECK( ! str::contains("abcXabcYabc", "xabcy") );
343 BOOST_CHECK( str::containsCI("abcXabcYabc", "xabcy") );
345 BOOST_CHECK_EQUAL( str::commonPrefix("", ""), 0 );
346 BOOST_CHECK_EQUAL( str::commonPrefix("a", ""), 0 );
347 BOOST_CHECK_EQUAL( str::commonPrefix("", "b"), 0 );
348 BOOST_CHECK_EQUAL( str::commonPrefix("a", "b"), 0 );
349 BOOST_CHECK_EQUAL( str::commonPrefix("c", "c"), 1 );
350 BOOST_CHECK_EQUAL( str::commonPrefix("ca", "cb"), 1 );
353 BOOST_AUTO_TEST_CASE(hexencode_hexdecode)
357 for ( unsigned i = 1; i < 256; ++i )
360 std::string e( str::hexencode( o ) );
361 // encoded contains nothing but [%a-zA-Z0-9]
362 for ( unsigned i = 0; i < 255; ++i )
365 BOOST_CHECK( ch == '%'
366 || ( 'a' <= ch && ch <= 'z' )
367 || ( 'A' <= ch && ch <= 'Z' )
368 || ( '0' <= ch && ch <= '9' ) );
371 std::string d( str::hexdecode( e ) );
372 // decoded equals original
373 BOOST_CHECK( o == d );
375 // Test %XX is decoded for hexdigits only
376 const char *const dig = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
377 for ( const char * d1 = dig; *d1; ++d1 )
378 for ( const char * d2 = dig; *d2; ++d2 )
380 std::string eu( "%" );
381 eu += *d1; eu += *d2;
382 std::string el( str::toLower(eu) );
384 std::string u( str::hexdecode( eu ) );
385 std::string l( str::hexdecode( el ) );
387 if ( *d1 <= 'F' && *d2 <= 'F' )
389 BOOST_CHECK_EQUAL( u, l ); // no matter if upper or lower case hexdigit
390 BOOST_CHECK_EQUAL( u.size(), 1 ); // size 1 == decoded
394 BOOST_CHECK_EQUAL( u, eu ); // no hexdigits remain unchanged
395 BOOST_CHECK_EQUAL( l, el );