Imported Upstream version 17.22.1
[platform/upstream/libzypp.git] / tests / zypp / base / String_test.cc
index ff9f345..f779eac 100644 (file)
@@ -1,4 +1,4 @@
-#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/unit_test.hpp>
 
 #include "zypp/base/LogTools.h"
 #include "zypp/base/String.h"
@@ -11,6 +11,56 @@ using namespace std;
 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";
@@ -45,43 +95,110 @@ BOOST_AUTO_TEST_CASE(testsplitEscaped)
   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[0], "escaped sentence " );
+
+  v.clear();
+  s = string( "\"escaped \\\\sent\\\"ence \\\\\"" );
+  splitEscaped( s, std::back_inserter(v) );
   BOOST_CHECK_EQUAL( v.size(), 1 );
-  BOOST_CHECK_EQUAL( v.front(), string( "escaped sentence " ) );
-
-   v.clear();
-   s = string( "\"escaped \\\\sent\\\"ence \\\\\"" );
-   ii = insert_iterator<vector<string> >( v, v.end() );
-   splitEscaped( s, ii );
-   BOOST_CHECK_EQUAL( v.size(), 1 );
-   BOOST_CHECK_EQUAL( v.front(), string( "escaped \\sent\"ence \\" ) );
-
-
-   v.clear();
-   s = string( "escaped sentence\\ with\\ space" );
-   ii = insert_iterator<vector<string> >( v, v.end() );
-   splitEscaped( s, ii );
-   BOOST_CHECK_EQUAL( v.size(), 2 );
-   BOOST_CHECK_EQUAL( v[1], string( "sentence with space" ) );
-
-   // split - join
-   v.clear();
-   s = "some line \"\" foo\\ a foo\\\\ b";
-   str::splitEscaped( s, std::back_inserter(v) );
-   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( s, str::joinEscaped( v.begin(), v.end(), 'o' ) );
+  BOOST_CHECK_EQUAL( v[0], "escaped \\sent\"ence \\" );
+
+  v.clear();
+  s = string( "escaped sentence\\ with\\ space" );
+  splitEscaped( s, std::back_inserter(v) );
+  BOOST_CHECK_EQUAL( v.size(), 2 );
+  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" );
+  vector<string> v;
+
+  BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3);
+  BOOST_CHECK_EQUAL(v.size(), 3);
+
+  v.clear();
+  s = "non-escaped:with::spaces:";
+  BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 5);
+  BOOST_CHECK_EQUAL(v.size(), 5);
+
+  v.clear();
+  s = "::";
+  BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3);
+  BOOST_CHECK_EQUAL(v.size(), 3);
+
+  v.clear();
+  s = ":escaped::with\\:spaces";
+  BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 4);
+  BOOST_CHECK_EQUAL(v.size(), 4);
 }
 
 BOOST_AUTO_TEST_CASE(test_escape)
@@ -92,7 +209,7 @@ BOOST_AUTO_TEST_CASE(test_escape)
   BOOST_CHECK_EQUAL( escaped, "bad\\|ass\\\\\\|worse" );
 }
 
-BOOST_AUTO_TEST_CASE(convertions)
+BOOST_AUTO_TEST_CASE(conversions)
 {
     BOOST_CHECK_EQUAL(str::numstring(42),     "42");
     BOOST_CHECK_EQUAL(str::numstring(42, 6),  "    42");
@@ -111,6 +228,62 @@ BOOST_AUTO_TEST_CASE(convertions)
     BOOST_CHECK_EQUAL(str::toLower("This IS A TeST"), "this is a test");
     BOOST_CHECK_EQUAL(str::toUpper("This IS A TeST"), "THIS IS A TEST");
     BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0);
+
+    BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0);
+    BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0);
+}
+
+BOOST_AUTO_TEST_CASE(conversions_to_bool)
+{
+  // true iff true-string {1,on,yes,true}
+  BOOST_CHECK_EQUAL( str::strToTrue("1"),     true );
+  BOOST_CHECK_EQUAL( str::strToTrue("42"),    true );
+  BOOST_CHECK_EQUAL( str::strToTrue("ON"),    true );
+  BOOST_CHECK_EQUAL( str::strToTrue("YES"),   true );
+  BOOST_CHECK_EQUAL( str::strToTrue("TRUE"),  true );
+  BOOST_CHECK_EQUAL( str::strToTrue("0"),     false );
+  BOOST_CHECK_EQUAL( str::strToTrue("OFF"),   false );
+  BOOST_CHECK_EQUAL( str::strToTrue("NO"),    false );
+  BOOST_CHECK_EQUAL( str::strToTrue("FALSE"), false );
+  BOOST_CHECK_EQUAL( str::strToTrue(""),      false );
+  BOOST_CHECK_EQUAL( str::strToTrue("foo"),   false );
+
+  // false iff false-string {0,off,no,false}
+  BOOST_CHECK_EQUAL( str::strToFalse("1"),     true );
+  BOOST_CHECK_EQUAL( str::strToFalse("42"),    true );
+  BOOST_CHECK_EQUAL( str::strToFalse("ON"),    true );
+  BOOST_CHECK_EQUAL( str::strToFalse("YES"),   true );
+  BOOST_CHECK_EQUAL( str::strToFalse("TRUE"),  true );
+  BOOST_CHECK_EQUAL( str::strToFalse("0"),     false );
+  BOOST_CHECK_EQUAL( str::strToFalse("OFF"),   false );
+  BOOST_CHECK_EQUAL( str::strToFalse("NO"),    false );
+  BOOST_CHECK_EQUAL( str::strToFalse("FALSE"), false );
+  BOOST_CHECK_EQUAL( str::strToFalse(""),      true );
+  BOOST_CHECK_EQUAL( str::strToFalse("foo"),   true );
+
+  // true iff true-string
+  BOOST_CHECK_EQUAL( str::strToBool("TRUE",  false), true );
+  BOOST_CHECK_EQUAL( str::strToBool("FALSE", false), false );
+  BOOST_CHECK_EQUAL( str::strToBool("",      false), false );
+  BOOST_CHECK_EQUAL( str::strToBool("foo",   false), false );
+
+  // false iff false-string
+  BOOST_CHECK_EQUAL( str::strToBool("TRUE",  true),  true );
+  BOOST_CHECK_EQUAL( str::strToBool("FALSE", true),  false );
+  BOOST_CHECK_EQUAL( str::strToBool("",      true),  true );
+  BOOST_CHECK_EQUAL( str::strToBool("foo",   true),  true );
+
+  // true/false iff true/false-string, else unchanged
+  bool ret;
+  ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("TRUE",  ret),  true );
+  ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("FALSE", ret),  false );
+  ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("",      ret),  true );
+  ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("foo",   ret),  true );
+
+  ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("TRUE",  ret),  true );
+  ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("FALSE", ret),  false );
+  ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("",      ret),  false );
+  ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("foo",   ret),  false );
 }
 
 BOOST_AUTO_TEST_CASE(operations)
@@ -168,4 +341,58 @@ BOOST_AUTO_TEST_CASE(prefix_suffix)
   BOOST_CHECK( str::contains("abcXabcYabc", "XabcY") );
   BOOST_CHECK( ! str::contains("abcXabcYabc", "xabcy") );
   BOOST_CHECK( str::containsCI("abcXabcYabc", "xabcy") );
+
+  BOOST_CHECK_EQUAL( str::commonPrefix("", ""),                0 );
+  BOOST_CHECK_EQUAL( str::commonPrefix("a", ""),       0 );
+  BOOST_CHECK_EQUAL( str::commonPrefix("", "b"),       0 );
+  BOOST_CHECK_EQUAL( str::commonPrefix("a", "b"),      0 );
+  BOOST_CHECK_EQUAL( str::commonPrefix("c", "c"),      1 );
+  BOOST_CHECK_EQUAL( str::commonPrefix("ca", "cb"),    1 );
+}
+
+BOOST_AUTO_TEST_CASE(hexencode_hexdecode)
+{
+  std::string o;
+  o.reserve( 256 );
+  for ( unsigned i = 1; i < 256; ++i )
+    o += i;
+
+  std::string e( str::hexencode( o ) );
+  // encoded contains nothing but [%a-zA-Z0-9]
+  for ( unsigned i = 0; i < 255; ++i )
+  {
+    char ch = e[i];
+    BOOST_CHECK( ch == '%'
+                 || ( 'a' <= ch && ch <= 'z' )
+                 || ( 'A' <= ch && ch <= 'Z' )
+                 || ( '0' <= ch && ch <= '9' ) );
+  }
+
+  std::string d( str::hexdecode( e ) );
+  // decoded equals original
+  BOOST_CHECK( o == d );
+
+  // 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 );
+     }
+    }
 }