Fix Flags<> api to be more consistent and add testcase.
authorMichael Andres <ma@suse.de>
Thu, 22 Dec 2011 12:13:06 +0000 (13:13 +0100)
committerMichael Andres <ma@suse.de>
Thu, 22 Dec 2011 12:13:06 +0000 (13:13 +0100)
 - no implicit conversion from unsigned to Flags
 - allow Flags/Enum in all operations

tests/zypp/CMakeLists.txt
tests/zypp/Flags_test.cc [new file with mode: 0644]
zypp/base/Flags.h

index 01862a5..3872f7d 100644 (file)
@@ -16,6 +16,7 @@ ADD_TESTS(
   Edition
   Fetcher
   FileChecker
+  Flags
   InstanceId
   KeyRing
   Locks
diff --git a/tests/zypp/Flags_test.cc b/tests/zypp/Flags_test.cc
new file mode 100644 (file)
index 0000000..d6e4666
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// tests for Flags
+//
+#include <boost/test/auto_unit_test.hpp>
+#include "zypp/base/Logger.h"
+#include "zypp/base/Flags.h"
+
+using boost::unit_test::test_case;
+using std::cout;
+using std::endl;
+using namespace zypp;
+
+enum TBits
+{
+  T_0  = 0,
+  T_1  = 1 << 0,
+  T_2  = 1 << 1,
+  T_3  = T_2 | T_1,
+  T_4  = 1 << 2,
+  T_5  = T_4 | T_1,
+  T_8  = 1 << 3,
+};
+
+ZYPP_DECLARE_FLAGS( TFlags, TBits );
+ZYPP_DECLARE_OPERATORS_FOR_FLAGS( TFlags );
+
+static const TFlags T_6( T_4 | T_2 );
+static const TFlags T_7( T_4 | T_2 | T_1 );
+
+BOOST_AUTO_TEST_CASE(flags)
+{
+  TFlags t0;
+  BOOST_CHECK_EQUAL( t0, 0 );
+  BOOST_CHECK_EQUAL( t0, T_0 );
+  BOOST_CHECK_EQUAL( t0, TFlags(0) );
+  BOOST_CHECK_EQUAL( ~t0, ~0 );
+  BOOST_CHECK_EQUAL( ~~t0, 0 );
+  BOOST_CHECK_EQUAL( ~t0, ~T_0 );
+  BOOST_CHECK_EQUAL( ~~t0, T_0 );
+
+  TFlags t1( T_1 );
+  BOOST_CHECK_EQUAL( t1, 1 );
+  BOOST_CHECK_EQUAL( t1, T_1 );
+  BOOST_CHECK_EQUAL( t1, TFlags(1) );
+
+  TFlags t;
+  // t = 1;    // must not compile: assign from int_type
+  t = T_2;     // = enum
+  BOOST_CHECK_EQUAL( t, T_2 );
+  t = T_6;     // = TFlags
+  BOOST_CHECK_EQUAL( t, T_6 );
+
+  // enum op enum
+  t = ~T_1;     BOOST_CHECK_EQUAL( ~t, T_1 );
+  t = T_1 & T_2; BOOST_CHECK_EQUAL( t, T_0 );
+  t = T_1 | T_2; BOOST_CHECK_EQUAL( t, T_3 );
+  t = T_1 ^ T_2; BOOST_CHECK_EQUAL( t, T_3 );
+
+  // enum op TFlags
+  t = T_2 & T_6; BOOST_CHECK_EQUAL( t, T_2 );
+  t = T_2 | T_6; BOOST_CHECK_EQUAL( t, T_6 );
+  t = T_2 ^ T_6; BOOST_CHECK_EQUAL( t, T_4 );
+
+  // TFlags op enum
+  t = ~T_7;     BOOST_CHECK_EQUAL( ~t, T_7 );
+  t = T_7 & T_2; BOOST_CHECK_EQUAL( t, T_2 );
+  t = T_7 | T_2; BOOST_CHECK_EQUAL( t, T_7 );
+  t = T_7 ^ T_2; BOOST_CHECK_EQUAL( t, T_5 );
+
+  // TFlags op enum
+  t = T_7 & T_6; BOOST_CHECK_EQUAL( t, T_6 );
+  t = T_7 | T_6; BOOST_CHECK_EQUAL( t, T_7 );
+  t = T_7 ^ T_7; BOOST_CHECK_EQUAL( t, T_0 );
+
+
+  t = T_3;
+  BOOST_CHECK( t.testFlag( T_1 ) );
+  BOOST_CHECK( t.testFlag( T_2 ) );
+  BOOST_CHECK( t.testFlag( T_3 ) );
+  t.unsetFlag( T_2 );          BOOST_CHECK( t.testFlag( T_1 ) );
+  t.setFlag( T_1, false );     BOOST_CHECK( t.testFlag( T_0 ) );
+  t.setFlag( T_3, true );      BOOST_CHECK( t.testFlag( T_3 ) );
+}
\ No newline at end of file
index 6547d6a..70b3a8a 100644 (file)
@@ -63,7 +63,7 @@ namespace zypp
       public:
         Flags()                               : _val( 0 ) {}
         Flags( Enum flag_r )                  : _val( flag_r ) {}
-        Flags( unsigned flag_r )              : _val( flag_r ) {}
+        explicit Flags( unsigned flag_r )     : _val( flag_r ) {}
 
         Flags & operator&=( Flags rhs )       { _val &= rhs._val; return *this; }
         Flags & operator&=( Enum rhs )        { _val &= rhs;      return *this; }
@@ -89,13 +89,17 @@ namespace zypp
         Flags operator~() const               { return Flags( ~_val ); }
 
       public:
-        Flags & setFlag( Enum flag_r, bool newval_r )
-        { return( newval_r ? setFlag(flag_r) : unsetFlag(flag_r) ); }
+        Flags & setFlag( Flags flag_r, bool newval_r ) { return( newval_r ? setFlag(flag_r) : unsetFlag(flag_r) ); }
+        Flags & setFlag( Enum flag_r, bool newval_r )  { return( newval_r ? setFlag(flag_r) : unsetFlag(flag_r) ); }
 
-        Flags & setFlag( Enum flag_r )           { _val |= flag_r; return *this; }
-        Flags & unsetFlag( Enum flag_r )         { _val &= ~flag_r; return *this; }
+        Flags & setFlag( Flags flag_r )       { _val |= flag_r; return *this; }
+        Flags & setFlag( Enum flag_r )        { _val |= flag_r; return *this; }
 
-        bool testFlag( Enum flag_r ) const    { return _val & flag_r; }
+        Flags & unsetFlag( Flags flag_r )     { _val &= ~flag_r; return *this; }
+        Flags & unsetFlag( Enum flag_r )      { _val &= ~flag_r; return *this; }
+
+        bool testFlag( Flags flag_r ) const   { return ( _val & flag_r ) == flag_r; }
+        bool testFlag( Enum flag_r ) const    { return ( _val & flag_r ) == flag_r; }
 
       private:
         unsigned _val;
@@ -111,8 +115,13 @@ namespace zypp
 
     /** \relates Flags */
 #define ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Name) \
-inline Name operator|( Name::enum_type lhs, Name::enum_type rhs )    { return Name( lhs ) |= rhs; } \
-inline Name operator|( Name::enum_type lhs, Name rhs )               { return rhs |= lhs; }
+inline Name operator&( Name::enum_type lhs, Name::enum_type rhs )      { return Name( lhs ) &= rhs; }  \
+inline Name operator&( Name::enum_type lhs, Name rhs )                 { return rhs &= lhs; }          \
+inline Name operator|( Name::enum_type lhs, Name::enum_type rhs )      { return Name( lhs ) |= rhs; }  \
+inline Name operator|( Name::enum_type lhs, Name rhs )                 { return rhs |= lhs; }          \
+inline Name operator^( Name::enum_type lhs, Name::enum_type rhs )      { return Name( lhs ) ^= rhs; }  \
+inline Name operator^( Name::enum_type lhs, Name rhs )                 { return rhs ^= lhs; }          \
+inline Name operator~( Name::enum_type lhs )                           { return ~Name( lhs ); }
 
     /** \relates Flags */
 #define ZYPP_DECLARE_FLAGS_AND_OPERATORS(Name,Enum) \