ZKMocks.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. * Copyright 2008, Yahoo! Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef ZKMOCKS_H_
  17. #define ZKMOCKS_H_
  18. #include <zookeeper.h>
  19. #include "src/zk_adaptor.h"
  20. #include "Util.h"
  21. #include "LibCMocks.h"
  22. #include "MocksBase.h"
  23. // *****************************************************************************
  24. // sets internal zhandle_t members to certain values to simulate the client
  25. // connected state. This function should only be used with the single-threaded
  26. // Async API tests!
  27. void forceConnected(zhandle_t* zh);
  28. // *****************************************************************************
  29. // Abstract watcher action
  30. struct SyncedBoolCondition;
  31. class WatcherAction{
  32. public:
  33. WatcherAction():triggered_(false){}
  34. virtual ~WatcherAction(){}
  35. virtual void onSessionExpired(zhandle_t*){}
  36. virtual void onNodeValueChanged(zhandle_t*,const char* path){}
  37. SyncedBoolCondition isWatcherTriggered() const;
  38. void setWatcherTriggered(){
  39. synchronized(mx_);
  40. triggered_=true;
  41. }
  42. protected:
  43. mutable Mutex mx_;
  44. bool triggered_;
  45. };
  46. // zh->context is a pointer to a WatcherAction instance
  47. // based on the event type and state, the watcher calls a specific watcher
  48. // action method
  49. void activeWatcher(zhandle_t *zh, int type, int state, const char *path);
  50. // *****************************************************************************
  51. // a set of async completion signatures
  52. class AsyncCompletion{
  53. public:
  54. virtual ~AsyncCompletion(){}
  55. virtual void aclCompl(int rc, ACL_vector *acl,Stat *stat){}
  56. virtual void dataCompl(int rc, const char *value, int len, const Stat *stat){}
  57. virtual void statCompl(int rc, const Stat *stat){}
  58. virtual void stringCompl(int rc, const char *value){}
  59. virtual void stringsCompl(int rc,const String_vector *strings){}
  60. virtual void voidCompl(int rc){}
  61. };
  62. void asyncCompletion(int rc, ACL_vector *acl,Stat *stat, const void *data);
  63. void asyncCompletion(int rc, const char *value, int len, const Stat *stat,
  64. const void *data);
  65. void asyncCompletion(int rc, const Stat *stat, const void *data);
  66. void asyncCompletion(int rc, const char *value, const void *data);
  67. void asyncCompletion(int rc,const String_vector *strings, const void *data);
  68. void asyncCompletion(int rc, const void *data);
  69. // *****************************************************************************
  70. // some common predicates to use with ensureCondition():
  71. // checks if the connection is established
  72. struct ClientConnected{
  73. ClientConnected(zhandle_t* zh):zh_(zh){}
  74. bool operator()() const{
  75. return zoo_state(zh_)==CONNECTED_STATE;
  76. }
  77. zhandle_t* zh_;
  78. };
  79. // check in the session expired
  80. struct SessionExpired{
  81. SessionExpired(zhandle_t* zh):zh_(zh){}
  82. bool operator()() const{
  83. return zoo_state(zh_)==EXPIRED_SESSION_STATE;
  84. }
  85. zhandle_t* zh_;
  86. };
  87. // checks if the IO thread has stopped; CheckedPthread must be active
  88. struct IOThreadStopped{
  89. IOThreadStopped(zhandle_t* zh):zh_(zh){}
  90. bool operator()() const;
  91. zhandle_t* zh_;
  92. };
  93. struct SyncedBoolCondition{
  94. SyncedBoolCondition(const bool& cond,Mutex& mx):cond_(cond),mx_(mx){}
  95. bool operator()() const{
  96. synchronized(mx_);
  97. return cond_;
  98. }
  99. const bool& cond_;
  100. Mutex& mx_;
  101. };
  102. // *****************************************************************************
  103. // make sure to call zookeeper_close() even in presence of exceptions
  104. struct CloseFinally{
  105. CloseFinally(zhandle_t** zh):zh_(zh){}
  106. ~CloseFinally(){
  107. execute();
  108. }
  109. int execute(){
  110. if(zh_==0)return ZOK;
  111. zhandle_t* lzh=*zh_;
  112. *zh_=0;
  113. disarm();
  114. return zookeeper_close(lzh);
  115. }
  116. void disarm(){zh_=0;}
  117. zhandle_t ** zh_;
  118. };
  119. struct TestClientId: clientid_t{
  120. static const int SESSION_ID=123456789;
  121. static const char* PASSWD;
  122. TestClientId(){
  123. client_id=SESSION_ID;
  124. memcpy(passwd,PASSWD,sizeof(passwd));
  125. }
  126. };
  127. // *****************************************************************************
  128. // special client id recongnized by the ZK server simulator
  129. extern TestClientId testClientId;
  130. #define TEST_CLIENT_ID &testClientId
  131. // *****************************************************************************
  132. //
  133. struct HandshakeRequest: public connect_req
  134. {
  135. static HandshakeRequest* parse(const std::string& buf);
  136. static bool isValid(const std::string& buf){
  137. // this is just quick and dirty check before we go and parse the request
  138. return buf.size()==HANDSHAKE_REQ_SIZE;
  139. }
  140. };
  141. // *****************************************************************************
  142. // flush_send_queue
  143. class Mock_flush_send_queue: public Mock
  144. {
  145. public:
  146. Mock_flush_send_queue():counter(0),callReturns(ZOK){mock_=this;}
  147. ~Mock_flush_send_queue(){mock_=0;}
  148. int counter;
  149. int callReturns;
  150. virtual int call(zhandle_t* zh, int timeout){
  151. counter++;
  152. return callReturns;
  153. }
  154. static Mock_flush_send_queue* mock_;
  155. };
  156. // *****************************************************************************
  157. // get_xid
  158. class Mock_get_xid: public Mock
  159. {
  160. public:
  161. static const int32_t XID=123456;
  162. Mock_get_xid(int retValue=XID):callReturns(retValue){mock_=this;}
  163. ~Mock_get_xid(){mock_=0;}
  164. int callReturns;
  165. virtual int call(){
  166. return callReturns;
  167. }
  168. static Mock_get_xid* mock_;
  169. };
  170. // *****************************************************************************
  171. // a zookeeper Stat wrapper
  172. struct NodeStat: public Stat
  173. {
  174. NodeStat(){
  175. czxid=0;
  176. mzxid=0;
  177. ctime=0;
  178. mtime=0;
  179. version=1;
  180. cversion=0;
  181. aversion=0;
  182. ephemeralOwner=0;
  183. }
  184. NodeStat(const Stat& other){
  185. memcpy(this,&other,sizeof(*this));
  186. }
  187. };
  188. // *****************************************************************************
  189. // Abstract server Response
  190. class Response
  191. {
  192. public:
  193. virtual ~Response(){}
  194. virtual void setXID(int32_t xid){}
  195. virtual std::string toString() const =0;
  196. };
  197. // *****************************************************************************
  198. // Handshake response
  199. class HandshakeResponse: public Response
  200. {
  201. public:
  202. HandshakeResponse(int64_t sessId=1)
  203. :protocolVersion(1),timeOut(10000),sessionId(sessId),passwd_len(sizeof(passwd))
  204. {
  205. memcpy(passwd,"1234567890123456",sizeof(passwd));
  206. }
  207. int32_t protocolVersion;
  208. int32_t timeOut;
  209. int64_t sessionId;
  210. int32_t passwd_len;
  211. char passwd[16];
  212. virtual std::string toString() const ;
  213. };
  214. // zoo_get() response
  215. class ZooGetResponse: public Response
  216. {
  217. public:
  218. ZooGetResponse(const char* data, int len,int32_t xid=0,int rc=ZOK,const Stat& stat=NodeStat())
  219. :xid_(xid),data_(data,len),rc_(rc),stat_(stat)
  220. {
  221. }
  222. virtual std::string toString() const;
  223. virtual void setXID(int32_t xid) {xid_=xid;}
  224. private:
  225. int32_t xid_;
  226. std::string data_;
  227. int rc_;
  228. Stat stat_;
  229. };
  230. // PING response
  231. class PingResponse: public Response
  232. {
  233. public:
  234. virtual std::string toString() const;
  235. };
  236. // watcher znode event
  237. class ZNodeEvent: public Response
  238. {
  239. public:
  240. ZNodeEvent(int type,const char* path):type_(type),path_(path){}
  241. virtual std::string toString() const;
  242. private:
  243. int type_;
  244. std::string path_;
  245. };
  246. // ****************************************************************************
  247. // Zookeeper server simulator
  248. class ZookeeperServer: public Mock_socket
  249. {
  250. public:
  251. ZookeeperServer():
  252. serverDownSkipCount_(-1),sessionExpired(false),connectionLost(false)
  253. {
  254. connectReturns=-1;
  255. connectErrno=EWOULDBLOCK;
  256. }
  257. virtual ~ZookeeperServer(){
  258. clearRecvQueue();
  259. clearRespQueue();
  260. }
  261. virtual int callClose(int fd){
  262. if(fd!=FD)
  263. return LIBC_SYMBOLS.close(fd);
  264. clearRecvQueue();
  265. clearRespQueue();
  266. return Mock_socket::callClose(fd);
  267. }
  268. // connection handling
  269. // what to do when the handshake request comes in?
  270. int serverDownSkipCount_;
  271. // this will cause getsockopt(zh->fd,SOL_SOCKET,SO_ERROR,&error,&len) return
  272. // a failure after skipCount dropped to zero, thus simulating a server down
  273. // condition
  274. // passing skipCount==-1 will make every connect attempt succeed
  275. void setServerDown(int skipCount=0){
  276. serverDownSkipCount_=skipCount;
  277. optvalSO_ERROR=0;
  278. }
  279. virtual void setSO_ERROR(void *optval,socklen_t len){
  280. if(serverDownSkipCount_!=-1){
  281. if(serverDownSkipCount_==0)
  282. optvalSO_ERROR=ECONNREFUSED;
  283. else
  284. serverDownSkipCount_--;
  285. }
  286. Mock_socket::setSO_ERROR(optval,len);
  287. }
  288. // this is a trigger that gets reset back to false
  289. // a connect request will return a non-matching session id thus causing
  290. // the client throw SESSION_EXPIRED
  291. bool sessionExpired;
  292. void returnSessionExpired(){ sessionExpired=true; }
  293. // this is a trigger that gets reset back to false
  294. // next recv call will return 0 length, thus simulating a connecton loss
  295. bool connectionLost;
  296. void setConnectionLost() {connectionLost=true;}
  297. // recv
  298. // this queue is used for server responses: client's recv() system call
  299. // returns next available message from this queue
  300. typedef std::pair<Response*,int> Element;
  301. typedef std::deque<Element> ResponseList;
  302. ResponseList recvQueue;
  303. mutable Mutex recvQMx;
  304. AtomicInt recvHasMore;
  305. ZookeeperServer& addRecvResponse(Response* resp, int errnum=0){
  306. synchronized(recvQMx);
  307. recvQueue.push_back(Element(resp,errnum));
  308. ++recvHasMore;
  309. return *this;
  310. }
  311. ZookeeperServer& addRecvResponse(int errnum){
  312. synchronized(recvQMx);
  313. recvQueue.push_back(Element(0,errnum));
  314. ++recvHasMore;
  315. return *this;
  316. }
  317. ZookeeperServer& addRecvResponse(const Element& e){
  318. synchronized(recvQMx);
  319. recvQueue.push_back(e);
  320. ++recvHasMore;
  321. return *this;
  322. }
  323. void clearRecvQueue(){
  324. synchronized(recvQMx);
  325. recvHasMore=0;
  326. for(unsigned i=0; i<recvQueue.size();i++)
  327. delete recvQueue[i].first;
  328. recvQueue.clear();
  329. }
  330. virtual ssize_t callRecv(int s,void *buf,size_t len,int flags);
  331. virtual bool hasMoreRecv() const;
  332. // the operation response queue holds zookeeper operation responses till the
  333. // operation request has been sent to the server. After that, the operation
  334. // response gets moved on to the recv queue (see above) ready to be read by
  335. // the next recv() system call
  336. // send operation doesn't try to match request to the response
  337. ResponseList respQueue;
  338. mutable Mutex respQMx;
  339. ZookeeperServer& addOperationResponse(Response* resp, int errnum=0){
  340. synchronized(respQMx);
  341. respQueue.push_back(Element(resp,errnum));
  342. return *this;
  343. }
  344. void clearRespQueue(){
  345. synchronized(respQMx);
  346. for(unsigned i=0; i<respQueue.size();i++)
  347. delete respQueue[i].first;
  348. respQueue.clear();
  349. }
  350. AtomicInt closeSent;
  351. virtual void notifyBufferSent(const std::string& buffer);
  352. // simulates an arrival of a client request
  353. // a callback to be implemented by subclasses (no-op by default)
  354. virtual void onMessageReceived(const RequestHeader& rh, iarchive* ia);
  355. };
  356. #endif /*ZKMOCKS_H_*/