-#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/unit_test.hpp>
#include "zypp/base/LogTools.h"
#include "zypp/base/String.h"
using namespace zypp;
using namespace zypp::str;
+#define RXspecial "\\^.[$()|*+?{"
+
+BOOST_AUTO_TEST_CASE(str2rx)
+{
+ char s[] = "c";
+ char x[] = "\\c";
+ for ( const char * ch = RXspecial; *ch; ++ch )
+ {
+ s[0] = x[1] = *ch;
+ BOOST_CHECK_EQUAL( str::rxEscapeStr( s ), x );
+ }
+}
+
+BOOST_AUTO_TEST_CASE(glob2rx)
+{
+ {
+ char s[] = "c";
+ char x[] = "\\c";
+ for ( const char * ch = RXspecial; *ch; ++ch )
+ {
+ s[0] = x[1] = *ch;
+ if ( *ch == '?' )
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "." );
+ else if ( *ch == '*' )
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), ".*" );
+ else if ( *ch == '[' )
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\[" ); // no closing ] so it is literal
+ else if ( *ch == '\\' )
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\" ); // actually an input error as "\" is not a valid GLOB
+ else
+ {
+ s[0] = x[1] = *ch;
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), x );
+ }
+ }
+ std::string a( str::rxEscapeStr( RXspecial ) ); // all rx/glob special chars are literally (\-escaped)
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( a ), a ); // nothing more to escape.
+
+ // character class: contains "]["
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[][]" ), "[][]" );
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^][]" ), "[^][]" );
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!][]" ), "[^][]" ); // glob allows ! and ^ to negate a cclass
+
+ // no character class: no closing ']' so take it literally (the ] would be member of the cclass, not the closing ])
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[]" ), "\\[]" );
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!]" ), "\\[!]" );
+ BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^]" ), "\\[\\^]" );
+ }
+}
+
BOOST_AUTO_TEST_CASE(gsubTest)
{
string olds = "olds";
string s( "simple non-escaped string" );
vector<string> v;
- insert_iterator<vector<string> > ii (v,v.end());
- splitEscaped( s, ii );
+ splitEscaped( s, std::back_inserter(v) );
BOOST_CHECK_EQUAL( v.size(), 3 );
+ BOOST_CHECK_EQUAL( v[0], "simple" );
+ BOOST_CHECK_EQUAL( v[1], "non-escaped" );
+ BOOST_CHECK_EQUAL( v[2], "string" );
v.clear();
s = string( "\"escaped sentence \"" );
- ii = insert_iterator<vector<string> >( v, v.end() );
- splitEscaped( s, ii );
+ splitEscaped( s, std::back_inserter(v) );
BOOST_CHECK_EQUAL( v.size(), 1 );
- BOOST_CHECK_EQUAL( v.front(), string( "escaped sentence " ) );
+ BOOST_CHECK_EQUAL( v[0], "escaped sentence " );
v.clear();
s = string( "\"escaped \\\\sent\\\"ence \\\\\"" );
- ii = insert_iterator<vector<string> >( v, v.end() );
- splitEscaped( s, ii );
+ splitEscaped( s, std::back_inserter(v) );
BOOST_CHECK_EQUAL( v.size(), 1 );
- BOOST_CHECK_EQUAL( v.front(), string( "escaped \\sent\"ence \\" ) );
-
+ BOOST_CHECK_EQUAL( v[0], "escaped \\sent\"ence \\" );
v.clear();
s = string( "escaped sentence\\ with\\ space" );
- ii = insert_iterator<vector<string> >( v, v.end() );
- splitEscaped( s, ii );
+ splitEscaped( s, std::back_inserter(v) );
BOOST_CHECK_EQUAL( v.size(), 2 );
- BOOST_CHECK_EQUAL( v[1], string( "sentence with space" ) );
+ BOOST_CHECK_EQUAL( v[0], "escaped" );
+ BOOST_CHECK_EQUAL( v[1], "sentence with space" );
// split - join
v.clear();
s = "some line \"\" foo\\ a foo\\\\ b";
str::splitEscaped( s, std::back_inserter(v) );
+ BOOST_CHECK_EQUAL( v.size(), 6 );
+ BOOST_CHECK_EQUAL( v[0], "some" );
+ BOOST_CHECK_EQUAL( v[1], "line" );
+ BOOST_CHECK_EQUAL( v[2], "" );
+ BOOST_CHECK_EQUAL( v[3], "foo a" );
+ BOOST_CHECK_EQUAL( v[4], "foo\\" );
+ BOOST_CHECK_EQUAL( v[5], "b" );
BOOST_CHECK_EQUAL( s, str::joinEscaped( v.begin(), v.end() ) );
// split - join using alternate sepchar
s = str::joinEscaped( v.begin(), v.end(), 'o' );
v.clear();
str::splitEscaped( s, std::back_inserter(v), "o" );
+ BOOST_CHECK_EQUAL( v.size(), 6 );
+ BOOST_CHECK_EQUAL( v[0], "some" );
+ BOOST_CHECK_EQUAL( v[1], "line" );
+ BOOST_CHECK_EQUAL( v[2], "" );
+ BOOST_CHECK_EQUAL( v[3], "foo a" );
+ BOOST_CHECK_EQUAL( v[4], "foo\\" );
+ BOOST_CHECK_EQUAL( v[5], "b" );
BOOST_CHECK_EQUAL( s, str::joinEscaped( v.begin(), v.end(), 'o' ) );
}
+BOOST_AUTO_TEST_CASE(bnc_909772)
+{
+ // While \-escaping processes single-quote, double-quote, backslash and sepchar[ ]
+ // deescaping failed to process the quotes correctly.
+ std::string s;
+ std::vector<std::string> v;
+
+ v.clear();
+ v.push_back("");
+ v.push_back("'\" \\");
+ v.push_back("\\'\\\"\\ \\\\");
+ s = str::joinEscaped( v.begin(), v.end() );
+ BOOST_CHECK_EQUAL( s, "\"\"" " " "\\'\\\"\\ \\\\" " " "\\\\\\'\\\\\\\"\\\\\\ \\\\\\\\" );
+
+ s += " ";
+ s += "'" "\\\\\" \\ \\\\" "'\\ single"; // single quote: all literal, no ' inside
+
+ s += " ";
+ s += "\"" "\\'\\\" \\ \\\\" "\"\\ double";// double quote: all literal except \\ \"
+
+ v.clear();
+ splitEscaped( s, std::back_inserter(v) );
+ BOOST_CHECK_EQUAL( v.size(), 5 );
+ BOOST_CHECK_EQUAL( v[0], "" );
+ BOOST_CHECK_EQUAL( v[1], "'\" \\" );
+ BOOST_CHECK_EQUAL( v[2], "\\'\\\"\\ \\\\" );
+ BOOST_CHECK_EQUAL( v[3], "\\\\\" \\ \\\\ single" );
+ BOOST_CHECK_EQUAL( v[4], "\\'\" \\ \\ double" );
+}
+
BOOST_AUTO_TEST_CASE(testsplitEscapedWithEmpty)
{
string s( "simple:non-escaped:string" );
}
std::string d( str::hexdecode( e ) );
+ // decoded equals original
BOOST_CHECK( o == d );
-// for ( unsigned i = 0; i < 255; ++i )
-// if ( o[i] != d[i] )
-// WAR << i << " " << unsigned(o[i]) << " != " << unsigned(d[i]) << endl;
+
+ // Test %XX is decoded for hexdigits only
+ const char *const dig = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ for ( const char * d1 = dig; *d1; ++d1 )
+ for ( const char * d2 = dig; *d2; ++d2 )
+ {
+ std::string eu( "%" );
+ eu += *d1; eu += *d2;
+ std::string el( str::toLower(eu) );
+
+ std::string u( str::hexdecode( eu ) );
+ std::string l( str::hexdecode( el ) );
+
+ if ( *d1 <= 'F' && *d2 <= 'F' )
+ {
+ BOOST_CHECK_EQUAL( u, l ); // no matter if upper or lower case hexdigit
+ BOOST_CHECK_EQUAL( u.size(), 1 ); // size 1 == decoded
+ }
+ else
+ {
+ BOOST_CHECK_EQUAL( u, eu ); // no hexdigits remain unchanged
+ BOOST_CHECK_EQUAL( l, el );
+ }
+ }
}