5b975e0d7d7143bbd7c7a6b9744f321ddfff1f65
[platform/upstream/libzypp.git] / tests / zypp / ResStatus_test.cc
1 #include "TestSetup.h"
2 #include "zypp/ResStatus.h"
3
4 #define BOOST_TEST_MODULE ResStatus
5
6 BOOST_AUTO_TEST_CASE(Default)
7 {
8   {
9     ResStatus s;
10     BOOST_CHECK( s.isUninstalled() );
11     BOOST_CHECK_EQUAL( s.isInstalled(), ! s.isUninstalled() );
12     BOOST_CHECK_EQUAL( s.getTransactValue(),   ResStatus::KEEP_STATE );
13     BOOST_CHECK_EQUAL( s.getTransactByValue(), ResStatus::SOLVER );
14   }
15   {
16     ResStatus s( true );
17     BOOST_CHECK( s.isInstalled() );
18     BOOST_CHECK_EQUAL( s.isInstalled(), ! s.isUninstalled() );
19     BOOST_CHECK_EQUAL( s.getTransactValue(),   ResStatus::KEEP_STATE );
20     BOOST_CHECK_EQUAL( s.getTransactByValue(), ResStatus::SOLVER );
21   }
22 }
23
24 ////////////////////////////////////////////////////////////////////////////////
25 // tools
26 ////////////////////////////////////////////////////////////////////////////////
27 template<class _Tp>
28 inline const _Tp & max( const _Tp & lhs, const _Tp & rhs )
29 { return lhs < rhs ? rhs : lhs; }
30
31 template<class _Tp, int N>
32 inline _Tp * begin( _Tp (& _array)[N] ) { return _array; }
33
34 template<class _Tp, int N>
35 inline _Tp * end( _Tp (& _array)[N] ) { return _array + (sizeof(_array)/sizeof(_Tp)); }
36
37 ResStatus::TransactByValue transactByValues[] = {
38   ResStatus::USER, ResStatus::APPL_HIGH, ResStatus::APPL_LOW, ResStatus::SOLVER
39 };
40
41 ResStatus::TransactValue transactValues[] = {
42   ResStatus::TRANSACT, ResStatus::KEEP_STATE, ResStatus::LOCKED
43 };
44
45 bool transactTo[] = {
46   true, false
47 };
48
49 // Status transition like setTransact, setLock, setSoftTransact
50 typedef bool (ResStatus::* Transition)( bool, ResStatus::TransactByValue );
51
52 // Result evaluation
53 typedef void (* Evaluate)( ResStatus::TransactValue, ResStatus::TransactByValue, /* fromState, fromBy */
54                            bool,                     ResStatus::TransactByValue, /* toState,   toBy */
55                            bool,                     ResStatus );                /* done,      result */
56
57 // build status and return whether the comination is supported. (e.g currently no LOCKED state below APPL_HIGH)
58 inline bool initStatus( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy, ResStatus & from )
59 {
60   from = ResStatus();
61   if ( fromState == ResStatus::KEEP_STATE )
62   {
63     from.setSoftLock( fromBy );
64   }
65   else
66   {
67     from.setTransactValue( fromState, fromBy );
68     if ( fromState == ResStatus::LOCKED && ! from.isLocked() )
69       return false; // no lock at this level (by now just USER APPL_HIGH)
70   }
71   return true;
72 }
73
74 void testTable( Transition transition, Evaluate evaluate )
75 {
76   // Table: For each causer combination (fromBy -> toBy) invoke transition:
77   //
78   //    bool ok = ResStatus(fromState,fromBy).transition( toState, toBy )
79   //
80   // And evaluate the result.
81   //
82   for ( ResStatus::TransactByValue * toBy = begin( transactByValues ); toBy != end( transactByValues ); ++toBy )
83   {
84     for ( ResStatus::TransactByValue * fromBy = begin( transactByValues ); fromBy != end( transactByValues ); ++fromBy )
85     {
86       INT << "=== " << *fromBy << " ==> " << *toBy << " ===" << endl;
87       for ( ResStatus::TransactValue * fromState = begin( transactValues ); fromState != end( transactValues ); ++fromState )
88       {
89         ResStatus from;
90         if ( ! initStatus( *fromState, *fromBy, from ) )
91         {
92           //WAR << "Unsupported ResStatus(" << *fromState << "," << *fromBy << ")" << endl;
93           continue; // Unsupported ResStatus
94         }
95         for ( bool * toState = begin( transactTo ); toState != end( transactTo ); ++toState )
96         {
97           ResStatus result( from );
98           bool done = (result.*transition)( *toState, *toBy );
99           if ( ! done )
100             BOOST_CHECK_EQUAL( from, result ); // status stays unchaged on failure!
101           evaluate( *fromState, *fromBy, *toState, *toBy, done, result );
102         }
103       }
104     }
105   }
106 }
107
108 // BOOST_CHECK_EQUAL or BOOST_REQUIRE_EQUAL
109 #define X BOOST_CHECK_EQUAL
110
111
112 // Transition must succeeds always
113 #define CHECK_DONE_ALWAYS       X( done, true ); if ( ! done ) return
114
115 // Transition succeeds if same or higher TransactByValue
116 #define CHECK_DONE_IFCAUSER     X( done, toBy >= fromBy ); if ( ! done ) return
117
118 // Transition succeeds if a locker (APPL_HIGH or USER)
119 #define CHECK_DONE_ALWAYS_IFLOCKER     X( done, toBy >= ResStatus::APPL_HIGH ); if ( ! done ) return
120
121 // Transition succeeds if a locker (APPL_HIGH or USER) and  same or higher TransactByValue
122 #define CHECK_DONE_IFCAUSER_ISLOCKER     X( done, toBy >= max(fromBy,ResStatus::APPL_HIGH) ); if ( ! done ) return
123
124
125 // Expected target state after transistion
126 #define CHECK_STATE(NEW)        X( result.getTransactValue(), ResStatus::NEW )
127
128
129 // Transition result: Remember the causer (i.e. may downgrade superior causer of previous state)
130 #define CHECK_CAUSER_SET        X( result.getTransactByValue(), toBy )
131
132 // Transition result: Remember a superior causer
133 #define CHECK_CAUSER_RAISED     X( result.getTransactByValue(), max(fromBy,toBy) )
134
135 // Transition result: Causer stays the same
136 #define CHECK_CAUSER_STAYS      X( result.getTransactByValue(), fromBy )
137
138 // Transition result: Causer reset to least (SOLVER) level.
139 #define CHECK_CAUSER_TO_SOLVER  X( result.getTransactByValue(), ResStatus::SOLVER )
140
141
142 ////////////////////////////////////////////////////////////////////////////////
143 // test cases (see BOOST_AUTO_TEST_CASE(transition))
144 ////////////////////////////////////////////////////////////////////////////////
145 // All tests below should define 3 checks, abbrev. by defines
146 //
147 //    CHECK_DONE_*:         When does the tranaction succeed? (return if not)
148 //    CHECK_STATE( NEXT ):  The state the transition leads to (if successfull)
149 //    CHECK_CAUSER_*:       Changes to the remembered causer (if successfull)
150 //
151
152 #define DOCHECK( FROMSTATE, TOSTATE, C_DONE, C_STATE, C_CAUSER ) \
153         if ( ResStatus::FROMSTATE == fromState && TOSTATE == toState ) { C_DONE; CHECK_STATE( C_STATE ); C_CAUSER; }
154
155 void evaluateSetTransact( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy,
156                           bool                     toState,   ResStatus::TransactByValue toBy,
157                           bool                     done,      ResStatus                  result )
158 {
159   ResStatus from;
160   initStatus( fromState, fromBy, from );
161   MIL << from << " =setTransact("<<toState<<","<<toBy<<")=>\t" << done << ":" << result << endl;
162
163   DOCHECK( TRANSACT,    true,   CHECK_DONE_ALWAYS,      TRANSACT,       CHECK_CAUSER_RAISED     );
164   DOCHECK( TRANSACT,    false,  CHECK_DONE_IFCAUSER,    KEEP_STATE,     CHECK_CAUSER_RAISED     ); // from transact into softlock
165   DOCHECK( KEEP_STATE,  true,   CHECK_DONE_ALWAYS,      TRANSACT,       CHECK_CAUSER_SET        );
166   DOCHECK( KEEP_STATE,  false,  CHECK_DONE_ALWAYS,      KEEP_STATE,     CHECK_CAUSER_STAYS      ); // keep is not raised to softlock
167   DOCHECK( LOCKED,      true,   CHECK_DONE_IFCAUSER,    TRANSACT,       CHECK_CAUSER_SET        );
168   DOCHECK( LOCKED,      false,  CHECK_DONE_ALWAYS,      LOCKED,         CHECK_CAUSER_STAYS      );
169 }
170
171 void evaluateSetSoftTransact( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy,
172                               bool                     toState,   ResStatus::TransactByValue toBy,
173                               bool                     done,      ResStatus                  result )
174 {
175   ResStatus from;
176   initStatus( fromState, fromBy, from );
177   MIL << from << " =setSoftTransact("<<toState<<","<<toBy<<")=>\t" << done << ":" << result << endl;
178
179   DOCHECK( TRANSACT,    true,   CHECK_DONE_ALWAYS,      TRANSACT,       CHECK_CAUSER_RAISED     );
180   DOCHECK( TRANSACT,    false,  CHECK_DONE_IFCAUSER,    KEEP_STATE,     CHECK_CAUSER_RAISED     ); // from transact into softlock
181   DOCHECK( KEEP_STATE,  true,   CHECK_DONE_IFCAUSER,    TRANSACT,       CHECK_CAUSER_SET        ); // leaving KEEP requires sup. causer
182   DOCHECK( KEEP_STATE,  false,  CHECK_DONE_ALWAYS,      KEEP_STATE,     CHECK_CAUSER_STAYS      ); // keep is not raised to softlock
183   DOCHECK( LOCKED,      true,   CHECK_DONE_IFCAUSER,    TRANSACT,       CHECK_CAUSER_SET        );
184   DOCHECK( LOCKED,      false,  CHECK_DONE_ALWAYS,      LOCKED,         CHECK_CAUSER_STAYS      );
185 }
186
187 // Check whether failures are ok and whether success lead to the correct state
188 void evaluateSetLock( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy,
189                       bool                     toState,   ResStatus::TransactByValue toBy,
190                       bool                     done,      ResStatus                  result )
191 {
192   ResStatus from;
193   initStatus( fromState, fromBy, from );
194   MIL << from << " =setLock("<<toState<<","<<toBy<<")=>\t" << done << ":" << result << endl;
195
196   DOCHECK( TRANSACT,    true,   CHECK_DONE_IFCAUSER_ISLOCKER,   LOCKED,         CHECK_CAUSER_SET        ); // transact is 'not locked'
197   DOCHECK( TRANSACT,    false,  CHECK_DONE_ALWAYS,              TRANSACT,       CHECK_CAUSER_STAYS      );
198   DOCHECK( KEEP_STATE,  true,   CHECK_DONE_ALWAYS_IFLOCKER,     LOCKED,         CHECK_CAUSER_SET        );
199   DOCHECK( KEEP_STATE,  false,  CHECK_DONE_ALWAYS,              KEEP_STATE,     CHECK_CAUSER_STAYS      );
200   DOCHECK( LOCKED,      true,   CHECK_DONE_ALWAYS,              LOCKED,         CHECK_CAUSER_RAISED     );
201   DOCHECK( LOCKED,      false,  CHECK_DONE_IFCAUSER,            KEEP_STATE,     CHECK_CAUSER_TO_SOLVER  );
202 }
203
204 BOOST_AUTO_TEST_CASE(transition)
205 {
206   //base::LogControl::TmpLineWriter shutUp( new log::FileLineWriter( "-" ) );
207   MIL << endl;
208   testTable( &ResStatus::setTransact,           &evaluateSetTransact );
209   testTable( &ResStatus::setSoftTransact,       &evaluateSetSoftTransact );
210   testTable( &ResStatus::setLock,               &evaluateSetLock );
211 }
212
213
214 bool WhilePoolItemSameStateIsPrivate( ResStatus ostatus, ResStatus nstatus )
215 {
216   if ( nstatus == ostatus )
217     return true;
218         // some bits changed...
219   if ( nstatus.getTransactValue() != ostatus.getTransactValue()
220        && ( ! nstatus.isBySolver() // ignore solver state changes
221                   // removing a user lock also goes to bySolver
222        || ostatus.getTransactValue() == ResStatus::LOCKED ) )
223     return false;
224   if ( nstatus.isLicenceConfirmed() != ostatus.isLicenceConfirmed() )
225     return false;
226   return true;
227 }
228
229 BOOST_AUTO_TEST_CASE(savestate)
230 {
231   ResStatus ostatus;
232   ResStatus nstatus;
233
234   BOOST_CHECK_EQUAL( WhilePoolItemSameStateIsPrivate( ostatus, nstatus ), true );
235   nstatus.setLock( true, ResStatus::USER );
236   BOOST_CHECK_EQUAL( WhilePoolItemSameStateIsPrivate( ostatus, nstatus ), false );
237   ostatus = nstatus;
238   nstatus.setLock( false, ResStatus::USER );
239   BOOST_CHECK_EQUAL( WhilePoolItemSameStateIsPrivate( ostatus, nstatus ), false );
240 }
241
242
243