1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <cppunit/extensions/HelperMacros.h>
20 #include "CppAssertHelper.h"
21 
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/select.h>
26 
27 #include "CollectionUtil.h"
28 #include "ThreadingUtil.h"
29 
30 using namespace Util;
31 
32 #include "Vector.h"
33 using namespace std;
34 
35 #include <cstring>
36 #include <list>
37 
38 #include <zookeeper.h>
39 #include <errno.h>
40 #include <recordio.h>
41 #include "Util.h"
42 #include "ZKMocks.h"
43 
44 struct buff_struct_2 {
45     int32_t len;
46     int32_t off;
47     char *buffer;
48 };
49 
50 // TODO(br33d): the vast majority of this test is not usable with single threaded.
51 //              it needs a overhaul to work properly with both threaded and single
52 //              threaded (ZOOKEEPER-2640)
53 #ifdef THREADED
54 // For testing LogMessage Callback functionality
55 list<string> logMessages;
logMessageHandler(const char * message)56 void logMessageHandler(const char* message) {
57     cout << "Log Message Received: [" << message << "]" << endl;
58     logMessages.push_back(message);
59 }
60 
Stat_eq(struct Stat * a,struct Stat * b)61 static int Stat_eq(struct Stat* a, struct Stat* b)
62 {
63     if (a->czxid != b->czxid) return 0;
64     if (a->mzxid != b->mzxid) return 0;
65     if (a->ctime != b->ctime) return 0;
66     if (a->mtime != b->mtime) return 0;
67     if (a->version != b->version) return 0;
68     if (a->cversion != b->cversion) return 0;
69     if (a->aversion != b->aversion) return 0;
70     if (a->ephemeralOwner != b->ephemeralOwner) return 0;
71     if (a->dataLength != b->dataLength) return 0;
72     if (a->numChildren != b->numChildren) return 0;
73     if (a->pzxid != b->pzxid) return 0;
74     return 1;
75 }
76 #ifdef THREADED
yield(zhandle_t * zh,int i)77     static void yield(zhandle_t *zh, int i)
78     {
79         sleep(i);
80     }
81 #else
yield(zhandle_t * zh,int seconds)82     static void yield(zhandle_t *zh, int seconds)
83     {
84         int fd;
85         int interest;
86         int events;
87         struct timeval tv;
88         int rc;
89         time_t expires = time(0) + seconds;
90         time_t timeLeft = seconds;
91         fd_set rfds, wfds, efds;
92         FD_ZERO(&rfds);
93         FD_ZERO(&wfds);
94         FD_ZERO(&efds);
95 
96         while(timeLeft >= 0) {
97             zookeeper_interest(zh, &fd, &interest, &tv);
98             if (fd != -1) {
99                 if (interest&ZOOKEEPER_READ) {
100                     FD_SET(fd, &rfds);
101                 } else {
102                     FD_CLR(fd, &rfds);
103                 }
104                 if (interest&ZOOKEEPER_WRITE) {
105                     FD_SET(fd, &wfds);
106                 } else {
107                     FD_CLR(fd, &wfds);
108                 }
109             } else {
110                 fd = 0;
111             }
112             FD_SET(0, &rfds);
113             if (tv.tv_sec > timeLeft) {
114                 tv.tv_sec = timeLeft;
115             }
116             rc = select(fd+1, &rfds, &wfds, &efds, &tv);
117             timeLeft = expires - time(0);
118             events = 0;
119             if (FD_ISSET(fd, &rfds)) {
120                 events |= ZOOKEEPER_READ;
121             }
122             if (FD_ISSET(fd, &wfds)) {
123                 events |= ZOOKEEPER_WRITE;
124             }
125             zookeeper_process(zh, events);
126         }
127     }
128 #endif
129 
130 typedef struct evt {
131     string path;
132     int type;
133 } evt_t;
134 
135 typedef struct watchCtx {
136 private:
137     list<evt_t> events;
138     watchCtx(const watchCtx&);
139     watchCtx& operator=(const watchCtx&);
140 public:
141     bool connected;
142     zhandle_t *zh;
143     Mutex mutex;
144 
watchCtxwatchCtx145     watchCtx() {
146         connected = false;
147         zh = 0;
148     }
~watchCtxwatchCtx149     ~watchCtx() {
150         if (zh) {
151             zookeeper_close(zh);
152             zh = 0;
153         }
154     }
155 
getEventwatchCtx156     evt_t getEvent() {
157         evt_t evt;
158         mutex.acquire();
159         CPPUNIT_ASSERT( events.size() > 0);
160         evt = events.front();
161         events.pop_front();
162         mutex.release();
163         return evt;
164     }
165 
countEventswatchCtx166     int countEvents() {
167         int count;
168         mutex.acquire();
169         count = events.size();
170         mutex.release();
171         return count;
172     }
173 
putEventwatchCtx174     void putEvent(evt_t evt) {
175         mutex.acquire();
176         events.push_back(evt);
177         mutex.release();
178     }
179 
waitForConnectedwatchCtx180     bool waitForConnected(zhandle_t *zh) {
181         time_t expires = time(0) + 10;
182         while(!connected && time(0) < expires) {
183             yield(zh, 1);
184         }
185         return connected;
186     }
187 
waitForDisconnectedwatchCtx188     bool waitForDisconnected(zhandle_t *zh) {
189         time_t expires = time(0) + 15;
190         while(connected && time(0) < expires) {
191             yield(zh, 1);
192         }
193         return !connected;
194     }
195 
196 } watchctx_t;
197 
198 class Zookeeper_simpleSystem : public CPPUNIT_NS::TestFixture
199 {
200     CPPUNIT_TEST_SUITE(Zookeeper_simpleSystem);
201     CPPUNIT_TEST(testLogCallbackSet);
202     CPPUNIT_TEST(testLogCallbackInit);
203     CPPUNIT_TEST(testLogCallbackClear);
204     CPPUNIT_TEST(testAsyncWatcherAutoReset);
205     CPPUNIT_TEST(testDeserializeString);
206     CPPUNIT_TEST(testFirstServerDown);
207     CPPUNIT_TEST(testNonexistentHost);
208 #ifdef THREADED
209     CPPUNIT_TEST(testNullData);
210 #ifdef ZOO_IPV6_ENABLED
211     CPPUNIT_TEST(testIPV6);
212 #endif
213 #ifdef HAVE_OPENSSL_H
214     CPPUNIT_TEST(testSSL);
215 #endif
216     CPPUNIT_TEST(testCreate);
217     CPPUNIT_TEST(testCreateContainer);
218     CPPUNIT_TEST(testCreateTtl);
219     CPPUNIT_TEST(testPath);
220     CPPUNIT_TEST(testPathValidation);
221     CPPUNIT_TEST(testPing);
222     CPPUNIT_TEST(testAcl);
223     CPPUNIT_TEST(testChroot);
224     CPPUNIT_TEST(testAuth);
225     CPPUNIT_TEST(testHangingClient);
226     CPPUNIT_TEST(testWatcherAutoResetWithGlobal);
227     CPPUNIT_TEST(testWatcherAutoResetWithLocal);
228     CPPUNIT_TEST(testGetChildren2);
229     CPPUNIT_TEST(testLastZxid);
230     CPPUNIT_TEST(testServersResolutionDelay);
231     CPPUNIT_TEST(testRemoveWatchers);
232 #endif
233     CPPUNIT_TEST_SUITE_END();
234 
watcher(zhandle_t *,int type,int state,const char * path,void * v)235     static void watcher(zhandle_t *, int type, int state, const char *path,void*v){
236         watchctx_t *ctx = (watchctx_t*)v;
237 
238         if (state == ZOO_CONNECTED_STATE) {
239             ctx->connected = true;
240         } else {
241             ctx->connected = false;
242         }
243         if (type != ZOO_SESSION_EVENT) {
244             evt_t evt;
245             evt.path = path;
246             evt.type = type;
247             ctx->putEvent(evt);
248         }
249     }
250 
251     static const char hostPorts[];
252 
getHostPorts()253     const char *getHostPorts() {
254         return hostPorts;
255     }
256 
createClient(watchctx_t * ctx)257     zhandle_t *createClient(watchctx_t *ctx) {
258         return createClient(hostPorts, ctx);
259     }
260 
createClient(watchctx_t * ctx,log_callback_fn logCallback)261     zhandle_t *createClient(watchctx_t *ctx, log_callback_fn logCallback) {
262         zhandle_t *zk = zookeeper_init2(hostPorts, watcher, 10000, 0, ctx, 0, logCallback);
263         ctx->zh = zk;
264         sleep(1);
265         return zk;
266     }
267 
createClient(const char * hp,watchctx_t * ctx)268     zhandle_t *createClient(const char *hp, watchctx_t *ctx) {
269         zhandle_t *zk = zookeeper_init(hp, watcher, 10000, 0, ctx, 0);
270         ctx->zh = zk;
271         sleep(1);
272         return zk;
273     }
274 
275 #ifdef HAVE_OPENSSL_H
createSSLClient(const char * hp,const char * cert,watchctx_t * ctx)276     zhandle_t *createSSLClient(const char *hp, const char *cert, watchctx_t *ctx) {
277         zhandle_t *zk = zookeeper_init_ssl(hp, cert, watcher, 30000, 0, ctx, 0);
278         ctx->zh = zk;
279         sleep(1);
280         return zk;
281     }
282 #endif
283 
createchClient(watchctx_t * ctx,const char * chroot)284     zhandle_t *createchClient(watchctx_t *ctx, const char* chroot) {
285         zhandle_t *zk = zookeeper_init(chroot, watcher, 10000, 0, ctx, 0);
286         ctx->zh = zk;
287         sleep(1);
288         return zk;
289     }
290 
291     FILE *logfile;
292 public:
293 
Zookeeper_simpleSystem()294     Zookeeper_simpleSystem() {
295       logfile = openlogfile("Zookeeper_simpleSystem");
296     }
297 
~Zookeeper_simpleSystem()298     ~Zookeeper_simpleSystem() {
299       if (logfile) {
300         fflush(logfile);
301         fclose(logfile);
302         logfile = 0;
303       }
304     }
305 
setUp()306     void setUp()
307     {
308         zoo_set_log_stream(logfile);
309     }
310 
startServer()311     void startServer() {
312         char cmd[1024];
313         sprintf(cmd, "%s start %s", ZKSERVER_CMD, getHostPorts());
314         CPPUNIT_ASSERT(system(cmd) == 0);
315     }
316 
stopServer()317     void stopServer() {
318         char cmd[1024];
319         sprintf(cmd, "%s stop %s", ZKSERVER_CMD, getHostPorts());
320         CPPUNIT_ASSERT(system(cmd) == 0);
321     }
322 
tearDown()323     void tearDown()
324     {
325     }
326 
327     /** have a callback in the default watcher **/
default_zoo_watcher(zhandle_t * zzh,int type,int state,const char * path,void * context)328     static void default_zoo_watcher(zhandle_t *zzh, int type, int state, const char *path, void *context){
329         int zrc;
330         struct String_vector str_vec = {0, NULL};
331         zrc = zoo_wget_children(zzh, "/mytest", default_zoo_watcher, NULL, &str_vec);
332         CPPUNIT_ASSERT(zrc == ZOK || zrc == ZCLOSING);
333     }
334 
335     /** ZOOKEEPER-1057 This checks that the client connects to the second server when the first is not reachable **/
testFirstServerDown()336     void testFirstServerDown() {
337         watchctx_t ctx;
338 
339         zoo_deterministic_conn_order(true);
340 
341         zhandle_t* zk = createClient("127.0.0.1:22182,127.0.0.1:22181", &ctx);
342         CPPUNIT_ASSERT(zk != 0);
343         CPPUNIT_ASSERT(ctx.waitForConnected(zk));
344     }
345 
346     /* Checks that a non-existent host will not block the connection*/
testNonexistentHost()347     void testNonexistentHost() {
348       char hosts[] = "jimmy:5555,127.0.0.1:22181";
349       watchctx_t ctx;
350       zoo_deterministic_conn_order(true /* disable permute */);
351       zhandle_t *zh = createClient(hosts, &ctx);
352       CPPUNIT_ASSERT(ctx.waitForConnected(zh));
353       zoo_deterministic_conn_order(false /* enable permute */);
354     }
355 
356     /** this checks for a deadlock in calling zookeeper_close and calls from a default watcher that might get triggered just when zookeeper_close() is in progress **/
testHangingClient()357     void testHangingClient() {
358         int zrc;
359         char buff[10] = "testall";
360         char path[512];
361         watchctx_t *ctx = NULL;
362         struct String_vector str_vec = {0, NULL};
363         zhandle_t *zh = zookeeper_init(hostPorts, NULL, 10000, 0, ctx, 0);
364         sleep(1);
365         zrc = zoo_create(zh, "/mytest", buff, 10, &ZOO_OPEN_ACL_UNSAFE, 0, path, 512);
366         CPPUNIT_ASSERT_EQUAL((int)ZOK, zrc);
367         zrc = zoo_wget_children(zh, "/mytest", default_zoo_watcher, NULL, &str_vec);
368         CPPUNIT_ASSERT_EQUAL((int)ZOK, zrc);
369         zrc = zoo_create(zh, "/mytest/test1", buff, 10, &ZOO_OPEN_ACL_UNSAFE, 0, path, 512);
370         CPPUNIT_ASSERT_EQUAL((int)ZOK, zrc);
371         zrc = zoo_wget_children(zh, "/mytest", default_zoo_watcher, NULL, &str_vec);
372         CPPUNIT_ASSERT_EQUAL((int)ZOK, zrc);
373         zrc = zoo_delete(zh, "/mytest/test1", -1);
374         CPPUNIT_ASSERT_EQUAL((int)ZOK, zrc);
375         zookeeper_close(zh);
376     }
377 
testBadDescriptor()378     void testBadDescriptor() {
379         watchctx_t *ctx = NULL;
380         zhandle_t *zh = zookeeper_init(hostPorts, NULL, 10000, 0, ctx, 0);
381         sleep(1);
382         zh->io_count = 0;
383         //close socket
384         close_zsock(zh->fd);
385         sleep(1);
386         //Check that doIo isn't spinning
387         CPPUNIT_ASSERT(zh->io_count < 2);
388         zookeeper_close(zh);
389     }
390 
391     /* Checks the zoo_set_servers_resolution_delay default and operation */
testServersResolutionDelay()392     void testServersResolutionDelay() {
393         watchctx_t ctx;
394         zhandle_t *zk = createClient(&ctx);
395         int rc;
396         struct timeval tv;
397         struct Stat stat;
398 
399         CPPUNIT_ASSERT(zk);
400         CPPUNIT_ASSERT(zk->resolve_delay_ms == 0);
401 
402         // a) Default/0 case: resolve at each request.
403 
404         tv = zk->last_resolve;
405         usleep(10000); // 10ms
406 
407         rc = zoo_exists(zk, "/", 0, &stat);
408         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
409 
410         // Must have changed because of the request.
411         CPPUNIT_ASSERT(zk->last_resolve.tv_sec != tv.tv_sec ||
412                        zk->last_resolve.tv_usec != tv.tv_usec);
413 
414         // b) Disabled/-1 case: never perform "routine" resolutions.
415 
416         rc = zoo_set_servers_resolution_delay(zk, -1); // Disabled
417         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
418 
419         tv = zk->last_resolve;
420         usleep(10000); // 10ms
421 
422         rc = zoo_exists(zk, "/", 0, &stat);
423         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
424 
425         // Must not have changed as auto-resolution is disabled.
426         CPPUNIT_ASSERT(zk->last_resolve.tv_sec == tv.tv_sec &&
427                        zk->last_resolve.tv_usec == tv.tv_usec);
428 
429         // c) Invalid delay is rejected.
430 
431         rc = zoo_set_servers_resolution_delay(zk, -1000); // Bad
432         CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, rc);
433 
434         // d) Valid delay, no resolution within window.
435 
436         rc = zoo_set_servers_resolution_delay(zk, 500); // 0.5s
437         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
438 
439         tv = zk->last_resolve;
440         usleep(10000); // 10ms
441 
442         rc = zoo_exists(zk, "/", 0, &stat);
443         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
444 
445         // Must not have changed because the request (hopefully!)
446         // executed in less than 0.5s.
447         CPPUNIT_ASSERT(zk->last_resolve.tv_sec == tv.tv_sec &&
448                        zk->last_resolve.tv_usec == tv.tv_usec);
449 
450         // e) Valid delay, at least one resolution after delay.
451 
452         usleep(500 * 1000); // 0.5s
453 
454         rc = zoo_exists(zk, "/", 0, &stat);
455         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
456 
457         // Must have changed because we waited 0.5s between the
458         // capture and the last request.
459         CPPUNIT_ASSERT(zk->last_resolve.tv_sec != tv.tv_sec ||
460                        zk->last_resolve.tv_usec != tv.tv_usec);
461     }
462 
testPing()463     void testPing()
464     {
465         watchctx_t ctxIdle;
466         watchctx_t ctxWC;
467         zhandle_t *zkIdle = createClient(&ctxIdle);
468         zhandle_t *zkWatchCreator = createClient(&ctxWC);
469 
470         CPPUNIT_ASSERT(zkIdle);
471         CPPUNIT_ASSERT(zkWatchCreator);
472 
473         char path[80];
474         sprintf(path, "/testping");
475         int rc = zoo_create(zkWatchCreator, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
476         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
477 
478         for(int i = 0; i < 30; i++) {
479             sprintf(path, "/testping/%i", i);
480             rc = zoo_create(zkWatchCreator, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
481             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
482         }
483 
484         for(int i = 0; i < 30; i++) {
485             sprintf(path, "/testping/%i", i);
486             struct Stat stat;
487             rc = zoo_exists(zkIdle, path, 1, &stat);
488             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
489         }
490 
491         for(int i = 0; i < 30; i++) {
492             sprintf(path, "/testping/%i", i);
493             usleep(500000);
494             rc = zoo_delete(zkWatchCreator, path, -1);
495             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
496         }
497         struct Stat stat;
498         CPPUNIT_ASSERT_EQUAL((int)ZNONODE, zoo_exists(zkIdle, "/testping/0", 0, &stat));
499     }
500 
waitForEvent(zhandle_t * zh,watchctx_t * ctx,int seconds)501     bool waitForEvent(zhandle_t *zh, watchctx_t *ctx, int seconds) {
502         time_t expires = time(0) + seconds;
503         while(ctx->countEvents() == 0 && time(0) < expires) {
504             yield(zh, 1);
505         }
506         return ctx->countEvents() > 0;
507     }
508 
509 #define COUNT 100
510 
511     static zhandle_t *async_zk;
512     static volatile int count;
513     static const char* hp_chroot;
514 
statCompletion(int rc,const struct Stat * stat,const void * data)515     static void statCompletion(int rc, const struct Stat *stat, const void *data) {
516         int tmp = (int) (long) data;
517         CPPUNIT_ASSERT_EQUAL(tmp, rc);
518     }
519 
stringCompletion(int rc,const char * value,const void * data)520     static void stringCompletion(int rc, const char *value, const void *data) {
521         char *path = (char*)data;
522 
523         if (rc == ZCONNECTIONLOSS && path) {
524             // Try again
525             rc = zoo_acreate(async_zk, path, "", 0,  &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, 0);
526         } else if (rc != ZOK) {
527             // fprintf(stderr, "rc = %d with path = %s\n", rc, (path ? path : "null"));
528         }
529         if (path) {
530             free(path);
531         }
532     }
533 
stringStatCompletion(int rc,const char * value,const struct Stat * stat,const void * data)534     static void stringStatCompletion(int rc, const char *value, const struct Stat *stat,
535             const void *data) {
536         stringCompletion(rc, value, data);
537         CPPUNIT_ASSERT(stat != 0);
538     }
539 
create_completion_fn(int rc,const char * value,const void * data)540     static void create_completion_fn(int rc, const char* value, const void *data) {
541         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
542         if (data) {
543             const char *expected_value = (const char *)data;
544             CPPUNIT_ASSERT_EQUAL(string(expected_value), string(value));
545         }
546         count++;
547     }
548 
waitForCreateCompletion(int seconds)549     static void waitForCreateCompletion(int seconds) {
550         time_t expires = time(0) + seconds;
551         while(count == 0 && time(0) < expires) {
552             sleep(1);
553         }
554         count--;
555     }
556 
watcher_chroot_fn(zhandle_t * zh,int type,int state,const char * path,void * watcherCtx)557     static void watcher_chroot_fn(zhandle_t *zh, int type,
558                                     int state, const char *path,void *watcherCtx) {
559         // check for path
560         char *client_path = (char *) watcherCtx;
561         CPPUNIT_ASSERT(strcmp(client_path, path) == 0);
562         count ++;
563     }
564 
waitForChrootWatch(int seconds)565     static void waitForChrootWatch(int seconds) {
566         time_t expires = time(0) + seconds;
567         while (count == 0 && time(0) < expires) {
568             sleep(1);
569         }
570         count--;
571     }
572 
waitForVoidCompletion(int seconds)573     static void waitForVoidCompletion(int seconds) {
574         time_t expires = time(0) + seconds;
575         while(count == 0 && time(0) < expires) {
576             sleep(1);
577         }
578         count--;
579     }
580 
voidCompletion(int rc,const void * data)581     static void voidCompletion(int rc, const void *data) {
582         int tmp = (int) (long) data;
583         CPPUNIT_ASSERT_EQUAL(tmp, rc);
584         count++;
585     }
586 
verifyCreateFails(const char * path,zhandle_t * zk)587     static void verifyCreateFails(const char *path, zhandle_t *zk) {
588       CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, zoo_create(zk,
589           path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0));
590     }
591 
verifyCreateOk(const char * path,zhandle_t * zk)592     static void verifyCreateOk(const char *path, zhandle_t *zk) {
593       CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_create(zk,
594           path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0));
595     }
596 
verifyCreateFailsSeq(const char * path,zhandle_t * zk)597     static void verifyCreateFailsSeq(const char *path, zhandle_t *zk) {
598       CPPUNIT_ASSERT_EQUAL((int)ZBADARGUMENTS, zoo_create(zk,
599           path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0));
600     }
601 
verifyCreateOkSeq(const char * path,zhandle_t * zk)602     static void verifyCreateOkSeq(const char *path, zhandle_t *zk) {
603       CPPUNIT_ASSERT_EQUAL((int)ZOK, zoo_create(zk,
604           path, "", 0, &ZOO_OPEN_ACL_UNSAFE, ZOO_SEQUENCE, 0, 0));
605     }
606 
607 
608     /**
609        returns false if the vectors dont match
610     **/
compareAcl(struct ACL_vector acl1,struct ACL_vector acl2)611     bool compareAcl(struct ACL_vector acl1, struct ACL_vector acl2) {
612         if (acl1.count != acl2.count) {
613             return false;
614         }
615         struct ACL *aclval1 = acl1.data;
616         struct ACL *aclval2 = acl2.data;
617         if (aclval1->perms != aclval2->perms) {
618             return false;
619         }
620         struct Id id1 = aclval1->id;
621         struct Id id2 = aclval2->id;
622         if (strcmp(id1.scheme, id2.scheme) != 0) {
623             return false;
624         }
625         if (strcmp(id1.id, id2.id) != 0) {
626             return false;
627         }
628         return true;
629     }
630 
testDeserializeString()631     void testDeserializeString() {
632         char *val_str;
633         int rc = 0;
634         int val = -1;
635         struct iarchive *ia;
636         struct buff_struct_2 *b;
637         struct oarchive *oa = create_buffer_oarchive();
638         oa->serialize_Int(oa, "int", &val);
639         b = (struct buff_struct_2 *) oa->priv;
640         ia = create_buffer_iarchive(b->buffer, b->len);
641         rc = ia->deserialize_String(ia, "string", &val_str);
642         CPPUNIT_ASSERT_EQUAL(-EINVAL, rc);
643     }
644 
testAcl()645     void testAcl() {
646         int rc;
647         struct ACL_vector aclvec;
648         struct Stat stat;
649         watchctx_t ctx;
650         zhandle_t *zk = createClient(&ctx);
651         rc = zoo_create(zk, "/acl", "", 0,
652                         &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
653         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
654         rc = zoo_get_acl(zk, "/acl", &aclvec, &stat  );
655         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
656         bool cmp = compareAcl(ZOO_OPEN_ACL_UNSAFE, aclvec);
657         CPPUNIT_ASSERT_EQUAL(true, cmp);
658         rc = zoo_set_acl(zk, "/acl", -1, &ZOO_READ_ACL_UNSAFE);
659         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
660         rc = zoo_get_acl(zk, "/acl", &aclvec, &stat);
661         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
662         cmp = compareAcl(ZOO_READ_ACL_UNSAFE, aclvec);
663         CPPUNIT_ASSERT_EQUAL(true, cmp);
664     }
665 
666 
testAuth()667     void testAuth() {
668         int rc;
669         count = 0;
670         watchctx_t ctx1, ctx2, ctx3, ctx4, ctx5;
671         zhandle_t *zk = createClient(&ctx1);
672         struct ACL_vector nodeAcl;
673         struct ACL acl_val;
674         rc = zoo_add_auth(0, "", 0, 0, voidCompletion, (void*)-1);
675         CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
676 
677         rc = zoo_add_auth(zk, 0, 0, 0, voidCompletion, (void*)-1);
678         CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
679 
680         // auth as pat, create /tauth1, close session
681         rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion,
682                           (void*)ZOK);
683         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
684         waitForVoidCompletion(3);
685         CPPUNIT_ASSERT(count == 0);
686 
687         rc = zoo_create(zk, "/tauth1", "", 0, &ZOO_CREATOR_ALL_ACL, 0, 0, 0);
688         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
689 
690         {
691             //create a new client
692             zk = createClient(&ctx4);
693             rc = zoo_add_auth(zk, "digest", "", 0, voidCompletion, (void*)ZOK);
694             CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
695             waitForVoidCompletion(3);
696             CPPUNIT_ASSERT(count == 0);
697 
698             rc = zoo_add_auth(zk, "digest", "", 0, voidCompletion, (void*)ZOK);
699             CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
700             waitForVoidCompletion(3);
701             CPPUNIT_ASSERT(count == 0);
702         }
703 
704         //create a new client
705         zk = createClient(&ctx2);
706 
707         rc = zoo_add_auth(zk, "digest", "pat:passwd2", 11, voidCompletion,
708                           (void*)ZOK);
709         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
710         waitForVoidCompletion(3);
711         CPPUNIT_ASSERT(count == 0);
712 
713         char buf[1024];
714         int blen = sizeof(buf);
715         struct Stat stat;
716         rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
717         CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, rc);
718         // add auth pat w/correct pass verify success
719         rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion,
720                           (void*)ZOK);
721 
722         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
723         rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
724         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
725         waitForVoidCompletion(3);
726         CPPUNIT_ASSERT(count == 0);
727         //create a new client
728         zk = createClient(&ctx3);
729         rc = zoo_add_auth(zk, "digest", "pat:passwd", 10, voidCompletion, (void*) ZOK);
730         waitForVoidCompletion(3);
731         CPPUNIT_ASSERT(count == 0);
732         rc = zoo_add_auth(zk, "ip", "none", 4, voidCompletion, (void*)ZOK);
733         //make the server forget the auths
734         waitForVoidCompletion(3);
735         CPPUNIT_ASSERT(count == 0);
736 
737         stopServer();
738         CPPUNIT_ASSERT(ctx3.waitForDisconnected(zk));
739         startServer();
740         CPPUNIT_ASSERT(ctx3.waitForConnected(zk));
741         // now try getting the data
742         rc = zoo_get(zk, "/tauth1", 0, buf, &blen, &stat);
743         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
744         // also check for get
745         rc = zoo_get_acl(zk, "/", &nodeAcl, &stat);
746         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
747         // check if the acl has all the perms
748         CPPUNIT_ASSERT_EQUAL((int)1, (int)nodeAcl.count);
749         acl_val = *(nodeAcl.data);
750         CPPUNIT_ASSERT_EQUAL((int) acl_val.perms, ZOO_PERM_ALL);
751         // verify on root node
752         rc = zoo_set_acl(zk, "/", -1, &ZOO_CREATOR_ALL_ACL);
753         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
754 
755         rc = zoo_set_acl(zk, "/", -1, &ZOO_OPEN_ACL_UNSAFE);
756         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
757 
758         //[ZOOKEEPER-1108], test that auth info is sent to server, if client is not
759         //connected to server when zoo_add_auth was called.
760         zhandle_t *zk_auth = zookeeper_init(hostPorts, NULL, 10000, 0, NULL, 0);
761         rc = zoo_add_auth(zk_auth, "digest", "pat:passwd", 10, voidCompletion, (void*)ZOK);
762         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
763         sleep(2);
764         CPPUNIT_ASSERT(count == 1);
765         count  = 0;
766         CPPUNIT_ASSERT_EQUAL((int) ZOK, zookeeper_close(zk_auth));
767 
768         struct sockaddr addr;
769         socklen_t addr_len = sizeof(addr);
770         zk = createClient(&ctx5);
771         stopServer();
772         CPPUNIT_ASSERT(ctx5.waitForDisconnected(zk));
773         CPPUNIT_ASSERT(zookeeper_get_connected_host(zk, &addr, &addr_len) == NULL);
774         addr_len = sizeof(addr);
775         startServer();
776         CPPUNIT_ASSERT(ctx5.waitForConnected(zk));
777         CPPUNIT_ASSERT(zookeeper_get_connected_host(zk, &addr, &addr_len) != NULL);
778     }
779 
testCreate()780     void testCreate() {
781         watchctx_t ctx;
782         int rc = 0;
783         zhandle_t *zk = createClient(&ctx);
784         CPPUNIT_ASSERT(zk);
785         char pathbuf[80];
786 
787         struct Stat stat_a = {0};
788         struct Stat stat_b = {0};
789         rc = zoo_create2(zk, "/testcreateA", "", 0,
790                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, sizeof(pathbuf), &stat_a);
791         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
792         CPPUNIT_ASSERT(strcmp(pathbuf, "/testcreateA") == 0);
793         CPPUNIT_ASSERT(stat_a.czxid > 0);
794         CPPUNIT_ASSERT(stat_a.mtime > 0);
795 
796         rc = zoo_create2(zk, "/testcreateB", "", 0,
797                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, sizeof(pathbuf), &stat_b);
798         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
799         CPPUNIT_ASSERT(strcmp(pathbuf, "/testcreateB") == 0);
800         CPPUNIT_ASSERT(stat_b.czxid > 0);
801         CPPUNIT_ASSERT(stat_b.mtime > 0);
802 
803         // Should get different Stats back from different creates
804         CPPUNIT_ASSERT(Stat_eq(&stat_a, &stat_b) != 1);
805     }
806 
testCreateContainer()807     void testCreateContainer() {
808         watchctx_t ctx;
809         int rc = 0;
810         zhandle_t *zk = createClient(&ctx);
811         CPPUNIT_ASSERT(zk);
812         char pathbuf[80];
813         struct Stat stat = {0};
814 
815         rc = zoo_create2(zk, "/testContainer", "", 0, &ZOO_OPEN_ACL_UNSAFE,
816                          ZOO_CONTAINER, pathbuf, sizeof(pathbuf), &stat);
817         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
818     }
819 
testCreateTtl()820     void testCreateTtl() {
821         watchctx_t ctx;
822         int rc = 0;
823         zhandle_t *zk = createClient(&ctx);
824         CPPUNIT_ASSERT(zk);
825         char pathbuf[80];
826         struct Stat stat = {0};
827 
828         rc = zoo_create2_ttl(zk, "/testTtl", "", 0, &ZOO_OPEN_ACL_UNSAFE,
829                              ZOO_PERSISTENT_WITH_TTL, 1, pathbuf, sizeof(pathbuf), &stat);
830         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
831 
832         sleep(1);
833 
834         rc = zoo_exists(zk, "/testTtl", 1, &stat);
835         CPPUNIT_ASSERT_EQUAL((int) ZNONODE, rc);
836     }
837 
testGetChildren2()838     void testGetChildren2() {
839         int rc;
840         watchctx_t ctx;
841         zhandle_t *zk = createClient(&ctx);
842 
843         rc = zoo_create(zk, "/parent", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
844         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
845 
846         rc = zoo_create(zk, "/parent/child_a", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
847         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
848 
849         rc = zoo_create(zk, "/parent/child_b", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
850         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
851 
852         rc = zoo_create(zk, "/parent/child_c", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
853         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
854 
855         rc = zoo_create(zk, "/parent/child_d", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
856         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
857 
858         struct String_vector strings;
859         struct Stat stat_a, stat_b;
860 
861         rc = zoo_get_children2(zk, "/parent", 0, &strings, &stat_a);
862         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
863 
864         rc = zoo_exists(zk, "/parent", 0, &stat_b);
865         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
866 
867         CPPUNIT_ASSERT(Stat_eq(&stat_a, &stat_b));
868         CPPUNIT_ASSERT(stat_a.numChildren == 4);
869     }
870 
testIPV6()871     void testIPV6() {
872         watchctx_t ctx;
873         zhandle_t *zk = createClient("::1:22181", &ctx);
874         CPPUNIT_ASSERT(zk);
875         int rc = 0;
876         rc = zoo_create(zk, "/ipv6", NULL, -1,
877                         &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
878         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
879     }
880 
881 #ifdef HAVE_OPENSSL_H
testSSL()882     void testSSL() {
883         watchctx_t ctx;
884         zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
885         zhandle_t *zk = createSSLClient("127.0.0.1:22281", "/tmp/certs/server.crt,/tmp/certs/client.crt,/tmp/certs/clientkey.pem,password", &ctx);
886         CPPUNIT_ASSERT(zk);
887         int rc = 0;
888         rc = zoo_create(zk, "/ssl", NULL, -1,
889                         &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
890         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
891     }
892 #endif
893 
testNullData()894     void testNullData() {
895         watchctx_t ctx;
896         zhandle_t *zk = createClient(&ctx);
897         CPPUNIT_ASSERT(zk);
898         int rc = 0;
899         rc = zoo_create(zk, "/mahadev", NULL, -1,
900                         &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
901         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
902         char buffer[512];
903         struct Stat stat;
904         int len = 512;
905         rc = zoo_wget(zk, "/mahadev", NULL, NULL, buffer, &len, &stat);
906         CPPUNIT_ASSERT_EQUAL( -1, len);
907         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
908         rc = zoo_set(zk, "/mahadev", NULL, -1, -1);
909         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
910         rc = zoo_wget(zk, "/mahadev", NULL, NULL, buffer, &len, &stat);
911         CPPUNIT_ASSERT_EQUAL( -1, len);
912         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
913     }
914 
testPath()915     void testPath() {
916         watchctx_t ctx;
917         char pathbuf[20];
918         zhandle_t *zk = createClient(&ctx);
919         CPPUNIT_ASSERT(zk);
920         int rc = 0;
921 
922         memset(pathbuf, 'X', 20);
923         rc = zoo_create(zk, "/testpathpath0", "", 0,
924                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 0);
925         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
926         CPPUNIT_ASSERT_EQUAL('X', pathbuf[0]);
927 
928         rc = zoo_create(zk, "/testpathpath1", "", 0,
929                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 1);
930         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
931         CPPUNIT_ASSERT(strlen(pathbuf) == 0);
932 
933         rc = zoo_create(zk, "/testpathpath2", "", 0,
934                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 2);
935         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
936         CPPUNIT_ASSERT(strcmp(pathbuf, "/") == 0);
937 
938         rc = zoo_create(zk, "/testpathpath3", "", 0,
939                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 3);
940         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
941         CPPUNIT_ASSERT(strcmp(pathbuf, "/t") == 0);
942 
943         rc = zoo_create(zk, "/testpathpath7", "", 0,
944                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 15);
945         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
946         CPPUNIT_ASSERT(strcmp(pathbuf, "/testpathpath7") == 0);
947 
948         rc = zoo_create(zk, "/testpathpath8", "", 0,
949                         &ZOO_OPEN_ACL_UNSAFE, 0, pathbuf, 16);
950         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
951         CPPUNIT_ASSERT(strcmp(pathbuf, "/testpathpath8") == 0);
952     }
953 
testPathValidation()954     void testPathValidation() {
955         watchctx_t ctx;
956         zhandle_t *zk = createClient(&ctx);
957         CPPUNIT_ASSERT(zk);
958 
959         verifyCreateFails(0, zk);
960         verifyCreateFails("", zk);
961         verifyCreateFails("//", zk);
962         verifyCreateFails("///", zk);
963         verifyCreateFails("////", zk);
964         verifyCreateFails("/.", zk);
965         verifyCreateFails("/..", zk);
966         verifyCreateFails("/./", zk);
967         verifyCreateFails("/../", zk);
968         verifyCreateFails("/foo/./", zk);
969         verifyCreateFails("/foo/../", zk);
970         verifyCreateFails("/foo/.", zk);
971         verifyCreateFails("/foo/..", zk);
972         verifyCreateFails("/./.", zk);
973         verifyCreateFails("/../..", zk);
974         verifyCreateFails("/foo/bar/", zk);
975         verifyCreateFails("/foo//bar", zk);
976         verifyCreateFails("/foo/bar//", zk);
977 
978         verifyCreateFails("foo", zk);
979         verifyCreateFails("a", zk);
980 
981         // verify that trailing fails, except for seq which adds suffix
982         verifyCreateOk("/createseq", zk);
983         verifyCreateFails("/createseq/", zk);
984         verifyCreateOkSeq("/createseq/", zk);
985         verifyCreateOkSeq("/createseq/.", zk);
986         verifyCreateOkSeq("/createseq/..", zk);
987         verifyCreateFailsSeq("/createseq//", zk);
988         verifyCreateFailsSeq("/createseq/./", zk);
989         verifyCreateFailsSeq("/createseq/../", zk);
990 
991         verifyCreateOk("/.foo", zk);
992         verifyCreateOk("/.f.", zk);
993         verifyCreateOk("/..f", zk);
994         verifyCreateOk("/..f..", zk);
995         verifyCreateOk("/f.c", zk);
996         verifyCreateOk("/f", zk);
997         verifyCreateOk("/f/.f", zk);
998         verifyCreateOk("/f/f.", zk);
999         verifyCreateOk("/f/..f", zk);
1000         verifyCreateOk("/f/f..", zk);
1001         verifyCreateOk("/f/.f/f", zk);
1002         verifyCreateOk("/f/f./f", zk);
1003     }
1004 
testChroot()1005     void testChroot() {
1006         // the c client async callbacks do
1007         // not callback with the path, so
1008         // we dont need to test taht for now
1009         // we should fix that though soon!
1010         watchctx_t ctx, ctx_ch;
1011         zhandle_t *zk, *zk_ch;
1012         char buf[60];
1013         int rc, len;
1014         struct Stat stat;
1015         const char* data = "garbage";
1016         const char* retStr = "/chroot";
1017         const char* root= "/";
1018         zk_ch = createchClient(&ctx_ch, "127.0.0.1:22181/testch1/mahadev");
1019         CPPUNIT_ASSERT(zk_ch != NULL);
1020         zk = createClient(&ctx);
1021         // first test with a NULL zk handle, make sure client library does not
1022         // dereference a null pointer, but instead returns ZBADARGUMENTS
1023         rc = zoo_create(NULL, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1024         CPPUNIT_ASSERT_EQUAL((int) ZBADARGUMENTS, rc);
1025         rc = zoo_create(zk, "/testch1", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1026         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1027         rc = zoo_create(zk, "/testch1/mahadev", data, 7, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1028         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1029         // try an exists with /
1030         len = 60;
1031         rc = zoo_get(zk_ch, "/", 0, buf, &len, &stat);
1032         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1033         //check if the data is the same
1034         CPPUNIT_ASSERT(strncmp(buf, data, 7) == 0);
1035         //check for watches
1036         rc = zoo_wexists(zk_ch, "/chroot", watcher_chroot_fn, (void *) retStr, &stat);
1037         //now check if we can do create/delete/get/sets/acls/getChildren and others
1038         //check create
1039         rc = zoo_create(zk_ch, "/chroot", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0,0);
1040         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1041         waitForChrootWatch(3);
1042         CPPUNIT_ASSERT(count == 0);
1043         rc = zoo_create(zk_ch, "/chroot/child", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1044         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1045         rc = zoo_exists(zk, "/testch1/mahadev/chroot/child", 0, &stat);
1046         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1047 
1048         rc = zoo_delete(zk_ch, "/chroot/child", -1);
1049         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1050         rc = zoo_exists(zk, "/testch1/mahadev/chroot/child", 0, &stat);
1051         CPPUNIT_ASSERT_EQUAL((int) ZNONODE, rc);
1052         rc = zoo_wget(zk_ch, "/chroot", watcher_chroot_fn, (char*) retStr,
1053                       buf, &len, &stat);
1054         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1055         rc = zoo_set(zk_ch, "/chroot",buf, 3, -1);
1056         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1057         waitForChrootWatch(3);
1058         CPPUNIT_ASSERT(count == 0);
1059         // check for getchildren
1060         struct String_vector children;
1061         rc = zoo_get_children(zk_ch, "/", 0, &children);
1062         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1063         CPPUNIT_ASSERT_EQUAL((int)1, (int)children.count);
1064         //check if te child if chroot
1065         CPPUNIT_ASSERT(strcmp((retStr+1), children.data[0]) == 0);
1066         // check for get/set acl
1067         struct ACL_vector acl;
1068         rc = zoo_get_acl(zk_ch, "/", &acl, &stat);
1069         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1070         CPPUNIT_ASSERT_EQUAL((int)1, (int)acl.count);
1071         CPPUNIT_ASSERT_EQUAL((int)ZOO_PERM_ALL, (int)acl.data->perms);
1072         // set acl
1073         rc = zoo_set_acl(zk_ch, "/chroot", -1,  &ZOO_READ_ACL_UNSAFE);
1074         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1075         // see if you add children
1076         rc = zoo_create(zk_ch, "/chroot/child1", "",0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1077         CPPUNIT_ASSERT_EQUAL((int)ZNOAUTH, rc);
1078         //add wget children test
1079         rc = zoo_wget_children(zk_ch, "/", watcher_chroot_fn, (char*) root, &children);
1080         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1081 
1082         //now create a node
1083         rc = zoo_create(zk_ch, "/child2", "",0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1084         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1085         waitForChrootWatch(3);
1086         CPPUNIT_ASSERT(count == 0);
1087         //check for one async call just to make sure
1088         rc = zoo_acreate(zk_ch, "/child3", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0,
1089                          create_completion_fn, 0);
1090         waitForCreateCompletion(3);
1091         CPPUNIT_ASSERT(count == 0);
1092 
1093         //ZOOKEEPER-1027 correctly return path_buffer without prefixed chroot
1094         const char* path = "/zookeeper1027";
1095         char path_buffer[1024];
1096         int path_buffer_len=sizeof(path_buffer);
1097         rc = zoo_create(zk_ch, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, path_buffer, path_buffer_len);
1098         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1099         CPPUNIT_ASSERT_EQUAL(string(path), string(path_buffer));
1100 
1101         const char* path2282 = "/zookeeper2282";
1102         rc = zoo_acreate(zk_ch, path2282, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0,
1103                          create_completion_fn, path2282);
1104         waitForCreateCompletion(3);
1105         CPPUNIT_ASSERT(count == 0);
1106     }
1107 
1108     // Test creating normal handle via zookeeper_init then explicitly setting callback
testLogCallbackSet()1109     void testLogCallbackSet()
1110     {
1111         watchctx_t ctx;
1112         CPPUNIT_ASSERT(logMessages.empty());
1113         zhandle_t *zk = createClient(&ctx);
1114 
1115         zoo_set_log_callback(zk, &logMessageHandler);
1116         CPPUNIT_ASSERT_EQUAL(zoo_get_log_callback(zk), &logMessageHandler);
1117 
1118         // Log 10 messages and ensure all go to callback
1119         const std::size_t expected = 10;
1120         for (std::size_t i = 0; i < expected; i++)
1121         {
1122             LOG_INFO(LOGCALLBACK(zk), "%s #%d", __FUNCTION__, i);
1123         }
1124         CPPUNIT_ASSERT(expected == logMessages.size());
1125     }
1126 
1127     // Test creating handle via zookeeper_init2 to ensure all connection messages go to callback
testLogCallbackInit()1128     void testLogCallbackInit()
1129     {
1130         logMessages.clear();
1131         watchctx_t ctx;
1132         zhandle_t *zk = createClient(&ctx, &logMessageHandler);
1133         CPPUNIT_ASSERT_EQUAL(zoo_get_log_callback(zk), &logMessageHandler);
1134 
1135         // All the connection messages should have gone to the callback -- don't
1136         // want this to be a maintenance issue so we're not asserting exact count
1137         std::size_t numBefore = logMessages.size();
1138         CPPUNIT_ASSERT(numBefore != 0);
1139 
1140         // Log 10 messages and ensure all go to callback
1141         const std::size_t expected = 10;
1142         for (std::size_t i = 0; i < expected; i++)
1143         {
1144             LOG_INFO(LOGCALLBACK(zk), "%s #%d", __FUNCTION__, i);
1145         }
1146         CPPUNIT_ASSERT(logMessages.size() == numBefore + expected);
1147     }
1148 
1149     // Test clearing log callback -- logging should resume going to logstream
testLogCallbackClear()1150     void testLogCallbackClear()
1151     {
1152         logMessages.clear();
1153         watchctx_t ctx;
1154         zhandle_t *zk = createClient(&ctx, &logMessageHandler);
1155         CPPUNIT_ASSERT_EQUAL(zoo_get_log_callback(zk), &logMessageHandler);
1156 
1157         // All the connection messages should have gone to the callback -- again, we don't
1158         // want this to be a maintenance issue so we're not asserting exact count
1159         int numBefore = logMessages.size();
1160         CPPUNIT_ASSERT(numBefore > 0);
1161 
1162         // Clear log_callback
1163         zoo_set_log_callback(zk, NULL);
1164 
1165         // Future log messages should go to logstream not callback
1166         LOG_INFO(LOGCALLBACK(zk), __FUNCTION__);
1167         int numAfter = logMessages.size();
1168         CPPUNIT_ASSERT_EQUAL(numBefore, numAfter);
1169     }
1170 
testAsyncWatcherAutoReset()1171     void testAsyncWatcherAutoReset()
1172     {
1173         watchctx_t ctx;
1174         zhandle_t *zk = createClient(&ctx);
1175         watchctx_t lctx[COUNT];
1176         int i;
1177         char path[80];
1178         int rc;
1179         evt_t evt;
1180 
1181         async_zk = zk;
1182         for(i = 0; i < COUNT; i++) {
1183             sprintf(path, "/awar%d", i);
1184             rc = zoo_awexists(zk, path, watcher, &lctx[i], statCompletion, (void*)ZNONODE);
1185             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1186         }
1187 
1188         yield(zk, 0);
1189 
1190         for(i = 0; i < COUNT/4; i++) {
1191             sprintf(path, "/awar%d", i);
1192             rc = zoo_acreate(zk, path, "", 0,  &ZOO_OPEN_ACL_UNSAFE, 0,
1193                 stringCompletion, strdup(path));
1194             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1195         }
1196 
1197         for(i = COUNT/4; i < COUNT/2; i++) {
1198             sprintf(path, "/awar%d", i);
1199             rc = zoo_acreate2(zk, path, "", 0,  &ZOO_OPEN_ACL_UNSAFE, 0,
1200                 stringStatCompletion, strdup(path));
1201             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1202         }
1203 
1204         yield(zk, 3);
1205         for(i = 0; i < COUNT/2; i++) {
1206             sprintf(path, "/awar%d", i);
1207             CPPUNIT_ASSERT_MESSAGE(path, waitForEvent(zk, &lctx[i], 5));
1208             evt = lctx[i].getEvent();
1209             CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path.c_str(), ZOO_CREATED_EVENT, evt.type);
1210             CPPUNIT_ASSERT_EQUAL(string(path), evt.path);
1211         }
1212 
1213         for(i = COUNT/2 + 1; i < COUNT*10; i++) {
1214             sprintf(path, "/awar%d", i);
1215             rc = zoo_acreate(zk, path, "", 0,  &ZOO_OPEN_ACL_UNSAFE, 0, stringCompletion, strdup(path));
1216             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1217         }
1218 
1219         yield(zk, 1);
1220         stopServer();
1221         CPPUNIT_ASSERT(ctx.waitForDisconnected(zk));
1222         startServer();
1223         CPPUNIT_ASSERT(ctx.waitForConnected(zk));
1224         yield(zk, 3);
1225         for(i = COUNT/2+1; i < COUNT; i++) {
1226             sprintf(path, "/awar%d", i);
1227             CPPUNIT_ASSERT_MESSAGE(path, waitForEvent(zk, &lctx[i], 5));
1228             evt = lctx[i].getEvent();
1229             CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CREATED_EVENT, evt.type);
1230             CPPUNIT_ASSERT_EQUAL(string(path), evt.path);
1231         }
1232     }
1233 
testWatcherAutoReset(zhandle_t * zk,watchctx_t * ctxGlobal,watchctx_t * ctxLocal)1234     void testWatcherAutoReset(zhandle_t *zk, watchctx_t *ctxGlobal,
1235                               watchctx_t *ctxLocal)
1236     {
1237         bool isGlobal = (ctxGlobal == ctxLocal);
1238         int rc;
1239         struct Stat stat;
1240         char buf[1024];
1241         int blen;
1242         struct String_vector strings;
1243         const char *testName;
1244 
1245         rc = zoo_create(zk, "/watchtest", "", 0,
1246                         &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1247         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1248         rc = zoo_create(zk, "/watchtest/child", "", 0,
1249                         &ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL, 0, 0);
1250         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1251 
1252         if (isGlobal) {
1253             testName = "GlobalTest";
1254             rc = zoo_get_children(zk, "/watchtest", 1, &strings);
1255             deallocate_String_vector(&strings);
1256             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1257             blen = sizeof(buf);
1258             rc = zoo_get(zk, "/watchtest/child", 1, buf, &blen, &stat);
1259             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1260             rc = zoo_exists(zk, "/watchtest/child2", 1, &stat);
1261             CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
1262         } else {
1263             testName = "LocalTest";
1264             rc = zoo_wget_children(zk, "/watchtest", watcher, ctxLocal,
1265                                  &strings);
1266             deallocate_String_vector(&strings);
1267             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1268             blen = sizeof(buf);
1269             rc = zoo_wget(zk, "/watchtest/child", watcher, ctxLocal,
1270                          buf, &blen, &stat);
1271             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1272             rc = zoo_wexists(zk, "/watchtest/child2", watcher, ctxLocal,
1273                             &stat);
1274             CPPUNIT_ASSERT_EQUAL((int)ZNONODE, rc);
1275         }
1276 
1277         CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
1278 
1279         stopServer();
1280         CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
1281         startServer();
1282         CPPUNIT_ASSERT_MESSAGE(testName, ctxLocal->waitForConnected(zk));
1283 
1284         CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
1285 
1286         rc = zoo_set(zk, "/watchtest/child", "1", 1, -1);
1287         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1288         struct Stat stat1, stat2;
1289         rc = zoo_set2(zk, "/watchtest/child", "1", 1, -1, &stat1);
1290         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1291         CPPUNIT_ASSERT(stat1.version >= 0);
1292         rc = zoo_set2(zk, "/watchtest/child", "1", 1, stat1.version, &stat2);
1293         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1294         rc = zoo_set(zk, "/watchtest/child", "1", 1, stat2.version);
1295         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1296         rc = zoo_create(zk, "/watchtest/child2", "", 0,
1297                         &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1298         CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1299 
1300         CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
1301 
1302         evt_t evt = ctxLocal->getEvent();
1303         CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHANGED_EVENT, evt.type);
1304         CPPUNIT_ASSERT_EQUAL(string("/watchtest/child"), evt.path);
1305 
1306         CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
1307         // The create will trigget the get children and the
1308         // exists watches
1309         evt = ctxLocal->getEvent();
1310         CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CREATED_EVENT, evt.type);
1311         CPPUNIT_ASSERT_EQUAL(string("/watchtest/child2"), evt.path);
1312         CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
1313         evt = ctxLocal->getEvent();
1314         CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHILD_EVENT, evt.type);
1315         CPPUNIT_ASSERT_EQUAL(string("/watchtest"), evt.path);
1316 
1317         // Make sure Pings are giving us problems
1318         sleep(5);
1319 
1320         CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
1321 
1322         stopServer();
1323         CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
1324         startServer();
1325         CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForConnected(zk));
1326 
1327         if (isGlobal) {
1328             testName = "GlobalTest";
1329             rc = zoo_get_children(zk, "/watchtest", 1, &strings);
1330             deallocate_String_vector(&strings);
1331             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1332             blen = sizeof(buf);
1333             rc = zoo_get(zk, "/watchtest/child", 1, buf, &blen, &stat);
1334             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1335             rc = zoo_exists(zk, "/watchtest/child2", 1, &stat);
1336             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1337         } else {
1338             testName = "LocalTest";
1339             rc = zoo_wget_children(zk, "/watchtest", watcher, ctxLocal,
1340                                  &strings);
1341             deallocate_String_vector(&strings);
1342             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1343             blen = sizeof(buf);
1344             rc = zoo_wget(zk, "/watchtest/child", watcher, ctxLocal,
1345                          buf, &blen, &stat);
1346             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1347             rc = zoo_wexists(zk, "/watchtest/child2", watcher, ctxLocal,
1348                             &stat);
1349             CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1350         }
1351 
1352         zoo_delete(zk, "/watchtest/child2", -1);
1353 
1354         CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
1355 
1356         evt = ctxLocal->getEvent();
1357         CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_DELETED_EVENT, evt.type);
1358         CPPUNIT_ASSERT_EQUAL(string("/watchtest/child2"), evt.path);
1359 
1360         CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
1361         evt = ctxLocal->getEvent();
1362         CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_CHILD_EVENT, evt.type);
1363         CPPUNIT_ASSERT_EQUAL(string("/watchtest"), evt.path);
1364 
1365         stopServer();
1366         CPPUNIT_ASSERT_MESSAGE(testName, ctxGlobal->waitForDisconnected(zk));
1367         startServer();
1368         CPPUNIT_ASSERT_MESSAGE(testName, ctxLocal->waitForConnected(zk));
1369 
1370         zoo_delete(zk, "/watchtest/child", -1);
1371         zoo_delete(zk, "/watchtest", -1);
1372 
1373         CPPUNIT_ASSERT_MESSAGE(testName, waitForEvent(zk, ctxLocal, 5));
1374 
1375         evt = ctxLocal->getEvent();
1376         CPPUNIT_ASSERT_EQUAL_MESSAGE(evt.path, ZOO_DELETED_EVENT, evt.type);
1377         CPPUNIT_ASSERT_EQUAL(string("/watchtest/child"), evt.path);
1378 
1379         // Make sure nothing is straggling
1380         sleep(1);
1381         CPPUNIT_ASSERT(ctxLocal->countEvents() == 0);
1382     }
1383 
testWatcherAutoResetWithGlobal()1384     void testWatcherAutoResetWithGlobal()
1385     {
1386       {
1387         watchctx_t ctx;
1388         zhandle_t *zk = createClient(&ctx);
1389         int rc = zoo_create(zk, "/testarwg", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1390         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1391         rc = zoo_create(zk, "/testarwg/arwg", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1392         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1393       }
1394 
1395       {
1396         watchctx_t ctx;
1397         zhandle_t *zk = createchClient(&ctx, "127.0.0.1:22181/testarwg/arwg");
1398 
1399         testWatcherAutoReset(zk, &ctx, &ctx);
1400       }
1401     }
1402 
testWatcherAutoResetWithLocal()1403     void testWatcherAutoResetWithLocal()
1404     {
1405       {
1406         watchctx_t ctx;
1407         zhandle_t *zk = createClient(&ctx);
1408         int rc = zoo_create(zk, "/testarwl", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1409         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1410         rc = zoo_create(zk, "/testarwl/arwl", "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1411         CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1412       }
1413 
1414       {
1415         watchctx_t ctx;
1416         watchctx_t lctx;
1417         zhandle_t *zk = createchClient(&ctx, "127.0.0.1:22181/testarwl/arwl");
1418         testWatcherAutoReset(zk, &ctx, &lctx);
1419       }
1420     }
1421 
testLastZxid()1422     void testLastZxid() {
1423       // ZOOKEEPER-1417: Test that c-client only update last zxid upon
1424       // receiving request response only.
1425       const int timeout = 5000;
1426       int rc;
1427       watchctx_t ctx1, ctx2;
1428       zhandle_t *zk1 = createClient(&ctx1);
1429       zhandle_t *zk2 = createClient(&ctx2);
1430       CPPUNIT_ASSERT(zk1);
1431       CPPUNIT_ASSERT(zk2);
1432 
1433       int64_t original = zk2->last_zxid;
1434 
1435       // Create txn to increase system zxid
1436       rc = zoo_create(zk1, "/lastzxid", "", 0,
1437                       &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1438       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1439 
1440       // This should be enough time for zk2 to receive ping request
1441       usleep(timeout/2 * 1000);
1442 
1443       // check that zk1's last zxid is updated
1444       struct Stat stat;
1445       rc = zoo_exists(zk1, "/lastzxid", 0, &stat);
1446       CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1447       CPPUNIT_ASSERT_EQUAL((int64_t) zk1->last_zxid, stat.czxid);
1448       // zk2's last zxid should remain the same
1449       CPPUNIT_ASSERT_EQUAL(original, (int64_t) zk2->last_zxid);
1450 
1451       // Perform read and also register a watch
1452       rc = zoo_wexists(zk2, "/lastzxid", watcher, &ctx2, &stat);
1453       CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1454       int64_t updated = zk2->last_zxid;
1455       // check that zk2's last zxid is updated
1456       CPPUNIT_ASSERT_EQUAL(updated, stat.czxid);
1457 
1458       // Increment system zxid again
1459       rc = zoo_set(zk1, "/lastzxid", NULL, -1, -1);
1460       CPPUNIT_ASSERT_EQUAL((int) ZOK, rc);
1461 
1462       // Wait for zk2 to get watch event
1463       CPPUNIT_ASSERT(waitForEvent(zk2, &ctx2, 5));
1464       // zk2's last zxid should remain the same
1465       CPPUNIT_ASSERT_EQUAL(updated, (int64_t) zk2->last_zxid);
1466     }
1467 
watcher_rw(zhandle_t * zh,int type,int state,const char * path,void * ctx)1468 	static void watcher_rw(zhandle_t *zh,
1469 		                   int type,
1470 		                   int state,
1471 		                   const char *path,
1472 		                   void *ctx) {
1473 		count++;
1474 	}
1475 
watcher_rw2(zhandle_t * zh,int type,int state,const char * path,void * ctx)1476 	static void watcher_rw2(zhandle_t *zh,
1477 		                    int type,
1478 		                    int state,
1479 		                    const char *path,
1480 		                    void *ctx) {
1481 		count++;
1482     }
1483 
testRemoveWatchers()1484     void testRemoveWatchers() {
1485       const char *path = "/something";
1486       char buf[1024];
1487       int blen = sizeof(buf);
1488       int rc;
1489       watchctx_t ctx;
1490       zhandle_t *zk;
1491 
1492       /* setup path */
1493       zk = createClient(&ctx);
1494       CPPUNIT_ASSERT(zk);
1495 
1496       rc = zoo_create(zk, path, "", 0, &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1497       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1498 
1499       rc = zoo_create(zk, "/something2", "", 0,
1500                       &ZOO_OPEN_ACL_UNSAFE, 0, 0, 0);
1501       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1502 
1503       /* remove all watchers */
1504       count = 0;
1505       rc = zoo_wget(zk, path, watcher_rw, NULL, buf, &blen, NULL);
1506       rc = zoo_wget(zk, path, watcher_rw2, NULL, buf, &blen, NULL);
1507       rc = zoo_remove_all_watches(zk, path, ZWATCHTYPE_ANY, 0);
1508 			CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1509 			rc = zoo_set(zk, path, "nowatch", 7, -1);
1510       CPPUNIT_ASSERT(count == 0);
1511 
1512       /* remove a specific watcher before it's added (should fail) */
1513       rc = zoo_remove_watches(zk, path, ZWATCHTYPE_DATA,
1514                                watcher_rw, NULL, 0);
1515       CPPUNIT_ASSERT_EQUAL((int)ZNOWATCHER, rc);
1516 
1517       /* now add a specific watcher and then remove it */
1518       rc = zoo_wget(zk, path, watcher_rw, NULL,
1519                     buf, &blen, NULL);
1520       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1521       rc = zoo_remove_watches(zk, path, ZWATCHTYPE_DATA,
1522                                watcher_rw, NULL, 0);
1523       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1524 
1525       /* ditto for children watcher */
1526       rc = zoo_remove_watches(zk, path, ZWATCHTYPE_CHILD,
1527                                watcher_rw, NULL, 0);
1528       CPPUNIT_ASSERT_EQUAL((int)ZNOWATCHER, rc);
1529 
1530       struct String_vector str_vec = {0, NULL};
1531       rc = zoo_wget_children(zk, path, watcher_rw, NULL,
1532                              &str_vec);
1533       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1534       rc = zoo_remove_watches(zk, path, ZWATCHTYPE_CHILD,
1535                                watcher_rw, NULL, 0);
1536       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1537 
1538       /* add a watch, stop the server, and have remove fail */
1539       rc = zoo_wget(zk, path, watcher_rw, NULL,
1540                     buf, &blen, NULL);
1541       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1542       stopServer();
1543       ctx.waitForDisconnected(zk);
1544       rc = zoo_remove_watches(zk, path, ZWATCHTYPE_DATA,
1545                                watcher_rw, NULL, 0);
1546       CPPUNIT_ASSERT_EQUAL((int)ZCONNECTIONLOSS, rc);
1547 
1548       zookeeper_close(zk);
1549 
1550       /* bring the server back */
1551       startServer();
1552       zk = createClient(&ctx);
1553 
1554       /* add a watch, stop the server, and remove it locally */
1555       void* ctx1=(void*)0x1;
1556       void* ctx2=(void*)0x2;
1557 
1558       rc = zoo_wget(zk, path, watcher_rw, ctx1,
1559                     buf, &blen, NULL);
1560       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1561 
1562       rc = zoo_wget(zk, "/something2", watcher_rw, ctx2,
1563                          buf, &blen, NULL);
1564       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1565 
1566       stopServer();
1567       rc = zoo_remove_watches(zk, path, ZWATCHTYPE_DATA,
1568                                watcher_rw, ctx1, 1);
1569       CPPUNIT_ASSERT_EQUAL((int)ZOK, rc);
1570 
1571       rc = zoo_remove_watches(zk, path, ZWATCHTYPE_DATA,
1572                                     watcher_rw, ctx1, 1);
1573       CPPUNIT_ASSERT_EQUAL((int)ZNOWATCHER, rc);
1574 
1575       rc = zoo_remove_watches(zk, "/something2", ZWATCHTYPE_DATA,
1576                                           watcher_rw, ctx2, 1);
1577       CPPUNIT_ASSERT_EQUAL((int)ZOK,rc);
1578     }
1579 };
1580 
1581 volatile int Zookeeper_simpleSystem::count;
1582 zhandle_t *Zookeeper_simpleSystem::async_zk;
1583 const char Zookeeper_simpleSystem::hostPorts[] = "127.0.0.1:22181";
1584 CPPUNIT_TEST_SUITE_REGISTRATION(Zookeeper_simpleSystem);
1585 #endif
1586