00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _tests_TxMocks_h
00022 #define _tests_TxMocks_h
00023
00024
00025 #include "qpid/Exception.h"
00026 #include "qpid/broker/TransactionalStore.h"
00027 #include "qpid/broker/TxOp.h"
00028 #include <iostream>
00029 #include <vector>
00030
00031 using namespace qpid::broker;
00032 using boost::static_pointer_cast;
00033 using std::string;
00034
00035 template <class T> void assertEqualVector(std::vector<T>& expected, std::vector<T>& actual){
00036 unsigned int i = 0;
00037 while(i < expected.size() && i < actual.size()){
00038 CPPUNIT_ASSERT_EQUAL(expected[i], actual[i]);
00039 i++;
00040 }
00041 if (i < expected.size()) {
00042 throw qpid::Exception(QPID_MSG("Missing " << expected[i]));
00043 } else if (i < actual.size()) {
00044 throw qpid::Exception(QPID_MSG("Extra " << actual[i]));
00045 }
00046 CPPUNIT_ASSERT_EQUAL(expected.size(), actual.size());
00047 }
00048
00049 class TxOpConstants{
00050 protected:
00051 const string PREPARE;
00052 const string COMMIT;
00053 const string ROLLBACK;
00054
00055 TxOpConstants() : PREPARE("PREPARE"), COMMIT("COMMIT"), ROLLBACK("ROLLBACK") {}
00056 };
00057
00058 class MockTxOp : public TxOp, public TxOpConstants{
00059 std::vector<string> expected;
00060 std::vector<string> actual;
00061 bool failOnPrepare;
00062 string debugName;
00063 public:
00064 typedef boost::shared_ptr<MockTxOp> shared_ptr;
00065
00066 MockTxOp() : failOnPrepare(false) {}
00067 MockTxOp(bool _failOnPrepare) : failOnPrepare(_failOnPrepare) {}
00068
00069 void setDebugName(string name){
00070 debugName = name;
00071 }
00072
00073 void printExpected(){
00074 std::cout << std::endl << "MockTxOp[" << debugName << "] expects: ";
00075 for (std::vector<string>::iterator i = expected.begin(); i < expected.end(); i++) {
00076 if(i != expected.begin()) std::cout << ", ";
00077 std::cout << *i;
00078 }
00079 std::cout << std::endl;
00080 }
00081
00082 void printActual(){
00083 std::cout << std::endl << "MockTxOp[" << debugName << "] actual: ";
00084 for (std::vector<string>::iterator i = actual.begin(); i < actual.end(); i++) {
00085 if(i != actual.begin()) std::cout << ", ";
00086 std::cout << *i;
00087 }
00088 std::cout << std::endl;
00089 }
00090
00091 bool prepare(TransactionContext*) throw(){
00092 actual.push_back(PREPARE);
00093 return !failOnPrepare;
00094 }
00095 void commit() throw(){
00096 actual.push_back(COMMIT);
00097 }
00098 void rollback() throw(){
00099 if(!debugName.empty()) std::cout << std::endl << "MockTxOp[" << debugName << "]::rollback()" << std::endl;
00100 actual.push_back(ROLLBACK);
00101 }
00102 MockTxOp& expectPrepare(){
00103 expected.push_back(PREPARE);
00104 return *this;
00105 }
00106 MockTxOp& expectCommit(){
00107 expected.push_back(COMMIT);
00108 return *this;
00109 }
00110 MockTxOp& expectRollback(){
00111 expected.push_back(ROLLBACK);
00112 return *this;
00113 }
00114 void check(){
00115 assertEqualVector(expected, actual);
00116 }
00117 ~MockTxOp(){}
00118 };
00119
00120 class MockTransactionalStore : public TransactionalStore{
00121 const string BEGIN;
00122 const string BEGIN2PC;
00123 const string PREPARE;
00124 const string COMMIT;
00125 const string ABORT;
00126 std::vector<string> expected;
00127 std::vector<string> actual;
00128
00129 enum states {OPEN = 1, PREPARED = 2, COMMITTED = 3, ABORTED = 4};
00130 int state;
00131
00132 class TestTransactionContext : public TPCTransactionContext{
00133 MockTransactionalStore* store;
00134 public:
00135 TestTransactionContext(MockTransactionalStore* _store) : store(_store) {}
00136 void prepare(){
00137 if(!store->isOpen()) throw "txn already completed";
00138 store->state = PREPARED;
00139 }
00140
00141 void commit(){
00142 if(!store->isOpen() && !store->isPrepared()) throw "txn already completed";
00143 store->state = COMMITTED;
00144 }
00145
00146 void abort(){
00147 if(!store->isOpen() && !store->isPrepared()) throw "txn already completed";
00148 store->state = ABORTED;
00149 }
00150 ~TestTransactionContext(){}
00151 };
00152
00153 public:
00154 MockTransactionalStore() :
00155 BEGIN("BEGIN"), BEGIN2PC("BEGIN2PC"), PREPARE("PREPARE"), COMMIT("COMMIT"), ABORT("ABORT"), state(OPEN){}
00156
00157 void collectPreparedXids(std::set<std::string>&)
00158 {
00159 throw "Operation not supported";
00160 }
00161
00162 std::auto_ptr<TPCTransactionContext> begin(const std::string&){
00163 actual.push_back(BEGIN2PC);
00164 std::auto_ptr<TPCTransactionContext> txn(new TestTransactionContext(this));
00165 return txn;
00166 }
00167 std::auto_ptr<TransactionContext> begin(){
00168 actual.push_back(BEGIN);
00169 std::auto_ptr<TransactionContext> txn(new TestTransactionContext(this));
00170 return txn;
00171 }
00172 void prepare(TPCTransactionContext& ctxt){
00173 actual.push_back(PREPARE);
00174 dynamic_cast<TestTransactionContext&>(ctxt).prepare();
00175 }
00176 void commit(TransactionContext& ctxt){
00177 actual.push_back(COMMIT);
00178 dynamic_cast<TestTransactionContext&>(ctxt).commit();
00179 }
00180 void abort(TransactionContext& ctxt){
00181 actual.push_back(ABORT);
00182 dynamic_cast<TestTransactionContext&>(ctxt).abort();
00183 }
00184 MockTransactionalStore& expectBegin(){
00185 expected.push_back(BEGIN);
00186 return *this;
00187 }
00188 MockTransactionalStore& expectBegin2PC(){
00189 expected.push_back(BEGIN2PC);
00190 return *this;
00191 }
00192 MockTransactionalStore& expectPrepare(){
00193 expected.push_back(PREPARE);
00194 return *this;
00195 }
00196 MockTransactionalStore& expectCommit(){
00197 expected.push_back(COMMIT);
00198 return *this;
00199 }
00200 MockTransactionalStore& expectAbort(){
00201 expected.push_back(ABORT);
00202 return *this;
00203 }
00204 void check(){
00205 assertEqualVector(expected, actual);
00206 }
00207
00208 bool isPrepared(){
00209 return state == PREPARED;
00210 }
00211
00212 bool isCommitted(){
00213 return state == COMMITTED;
00214 }
00215
00216 bool isAborted(){
00217 return state == ABORTED;
00218 }
00219
00220 bool isOpen() const{
00221 return state == OPEN;
00222 }
00223 ~MockTransactionalStore(){}
00224 };
00225
00226 #endif