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 package org.apache.zookeeper.test; 20 21 import static org.junit.jupiter.api.Assertions.assertEquals; 22 import static org.junit.jupiter.api.Assertions.assertNotNull; 23 import static org.junit.jupiter.api.Assertions.assertNull; 24 import static org.junit.jupiter.api.Assertions.assertSame; 25 import static org.junit.jupiter.api.Assertions.assertTrue; 26 import static org.junit.jupiter.api.Assertions.fail; 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.Collections; 30 import java.util.List; 31 import java.util.concurrent.CountDownLatch; 32 import java.util.concurrent.TimeUnit; 33 import org.apache.zookeeper.AsyncCallback.ACLCallback; 34 import org.apache.zookeeper.AsyncCallback.Children2Callback; 35 import org.apache.zookeeper.AsyncCallback.ChildrenCallback; 36 import org.apache.zookeeper.AsyncCallback.Create2Callback; 37 import org.apache.zookeeper.AsyncCallback.DataCallback; 38 import org.apache.zookeeper.AsyncCallback.MultiCallback; 39 import org.apache.zookeeper.AsyncCallback.StatCallback; 40 import org.apache.zookeeper.AsyncCallback.StringCallback; 41 import org.apache.zookeeper.AsyncCallback.VoidCallback; 42 import org.apache.zookeeper.CreateMode; 43 import org.apache.zookeeper.KeeperException; 44 import org.apache.zookeeper.KeeperException.Code; 45 import org.apache.zookeeper.Op; 46 import org.apache.zookeeper.OpResult; 47 import org.apache.zookeeper.ZooDefs.Ids; 48 import org.apache.zookeeper.ZooKeeper; 49 import org.apache.zookeeper.data.ACL; 50 import org.apache.zookeeper.data.Stat; 51 52 public class AsyncOps { 53 54 /** 55 * This is the base class for all of the async callback classes. It will 56 * verify the expected value against the actual value. 57 * 58 * Basic operation is that the subclasses will generate an "expected" value 59 * which is defined by the "toString" method of the subclass. This is 60 * passed through to the verify clause by specifying it as the ctx object 61 * of each async call (processResult methods get the ctx as part of 62 * the callback). Additionally the callback will also overwrite any 63 * instance fields with matching parameter arguments to the processResult 64 * method. The cb instance can then compare the expected to the 65 * actual value by again calling toString and comparing the two. 66 * 67 * The format of each expected value differs (is defined) by subclass. 68 * Generally the expected value starts with the result code (rc) and path 69 * of the node being operated on, followed by the fields specific to 70 * each operation type (cb subclass). For example ChildrenCB specifies 71 * a list of the expected children suffixed onto the rc and path. See 72 * the toString() method of each subclass for details of it's format. 73 */ 74 public abstract static class AsyncCB { 75 76 protected final ZooKeeper zk; 77 protected long defaultTimeoutMillis = 30000; 78 79 /** the latch is used to await the results from the server */ 80 CountDownLatch latch; 81 82 Code rc = Code.OK; 83 String path = "/foo"; 84 String expected; 85 AsyncCB(ZooKeeper zk, CountDownLatch latch)86 public AsyncCB(ZooKeeper zk, CountDownLatch latch) { 87 this.zk = zk; 88 this.latch = latch; 89 } 90 setRC(Code rc)91 public void setRC(Code rc) { 92 this.rc = rc; 93 } 94 setPath(String path)95 public void setPath(String path) { 96 this.path = path; 97 } 98 processResult(Code rc, String path, Object ctx)99 public void processResult(Code rc, String path, Object ctx) { 100 this.rc = rc; 101 this.path = path; 102 this.expected = (String) ctx; 103 latch.countDown(); 104 } 105 106 /** String format is rc:path:<suffix> where <suffix> is defined by each 107 * subclass individually. */ 108 @Override toString()109 public String toString() { 110 return rc + ":" + path + ":"; 111 } 112 verify()113 protected void verify() { 114 try { 115 latch.await(defaultTimeoutMillis, TimeUnit.MILLISECONDS); 116 } catch (InterruptedException e) { 117 fail("unexpected interrupt"); 118 } 119 // on the lookout for timeout 120 assertSame(0L, latch.getCount()); 121 122 String actual = toString(); 123 124 assertEquals(expected, actual); 125 } 126 127 } 128 129 public static class StringCB extends AsyncCB implements StringCallback { 130 131 byte[] data = new byte[10]; 132 List<ACL> acl = Ids.CREATOR_ALL_ACL; 133 CreateMode flags = CreateMode.PERSISTENT; 134 String name = path; 135 StringCB(ZooKeeper zk)136 StringCB(ZooKeeper zk) { 137 this(zk, new CountDownLatch(1)); 138 } 139 StringCB(ZooKeeper zk, CountDownLatch latch)140 StringCB(ZooKeeper zk, CountDownLatch latch) { 141 super(zk, latch); 142 } 143 setPath(String path)144 public void setPath(String path) { 145 super.setPath(path); 146 this.name = path; 147 } 148 nodeName()149 public String nodeName() { 150 return path.substring(path.lastIndexOf('/') + 1); 151 } 152 processResult(int rc, String path, Object ctx, String name)153 public void processResult(int rc, String path, Object ctx, String name) { 154 this.name = name; 155 super.processResult(Code.get(rc), path, ctx); 156 } 157 create()158 public AsyncCB create() { 159 zk.create(path, data, acl, flags, this, toString()); 160 return this; 161 } 162 createEphemeral()163 public AsyncCB createEphemeral() { 164 zk.create(path, data, acl, CreateMode.EPHEMERAL, this, toString()); 165 return this; 166 } 167 verifyCreate()168 public void verifyCreate() { 169 create(); 170 verify(); 171 } 172 verifyCreateEphemeral()173 public void verifyCreateEphemeral() { 174 createEphemeral(); 175 verify(); 176 } 177 verifyCreateFailure_NodeExists()178 public void verifyCreateFailure_NodeExists() { 179 new StringCB(zk).verifyCreate(); 180 181 rc = Code.NODEEXISTS; 182 name = null; 183 zk.create(path, data, acl, flags, this, toString()); 184 verify(); 185 } 186 verifyCreateFailure_NoNode()187 public void verifyCreateFailure_NoNode() { 188 189 rc = Code.NONODE; 190 name = null; 191 path = path + "/bar"; 192 zk.create(path, data, acl, flags, this, toString()); 193 194 verify(); 195 } 196 verifyCreateFailure_NoChildForEphemeral()197 public void verifyCreateFailure_NoChildForEphemeral() { 198 new StringCB(zk).verifyCreateEphemeral(); 199 200 rc = Code.NOCHILDRENFOREPHEMERALS; 201 name = null; 202 path = path + "/bar"; 203 zk.create(path, data, acl, flags, this, toString()); 204 205 verify(); 206 } 207 208 @Override toString()209 public String toString() { 210 return super.toString() + name; 211 } 212 213 } 214 215 public static class ACLCB extends AsyncCB implements ACLCallback { 216 217 List<ACL> acl = Ids.CREATOR_ALL_ACL; 218 int version = 0; 219 Stat stat = new Stat(); 220 byte[] data = "testing".getBytes(); 221 ACLCB(ZooKeeper zk)222 ACLCB(ZooKeeper zk) { 223 this(zk, new CountDownLatch(1)); 224 } 225 ACLCB(ZooKeeper zk, CountDownLatch latch)226 ACLCB(ZooKeeper zk, CountDownLatch latch) { 227 super(zk, latch); 228 stat.setAversion(0); 229 stat.setCversion(0); 230 stat.setEphemeralOwner(0); 231 stat.setVersion(0); 232 } 233 processResult(int rc, String path, Object ctx, List<ACL> acl, Stat stat)234 public void processResult(int rc, String path, Object ctx, List<ACL> acl, Stat stat) { 235 this.acl = acl; 236 this.stat = stat; 237 super.processResult(Code.get(rc), path, ctx); 238 } 239 verifyGetACL()240 public void verifyGetACL() { 241 new StringCB(zk).verifyCreate(); 242 243 zk.getACL(path, stat, this, toString()); 244 verify(); 245 } 246 verifyGetACLFailure_NoNode()247 public void verifyGetACLFailure_NoNode() { 248 rc = Code.NONODE; 249 stat = null; 250 acl = null; 251 zk.getACL(path, stat, this, toString()); 252 253 verify(); 254 } 255 toString(List<ACL> acls)256 public String toString(List<ACL> acls) { 257 if (acls == null) { 258 return ""; 259 } 260 261 StringBuilder result = new StringBuilder(); 262 for (ACL acl : acls) { 263 result.append(acl.getPerms()).append("::"); 264 } 265 return result.toString(); 266 } 267 268 @Override toString()269 public String toString() { 270 return super.toString() 271 + toString(acl) + ":" 272 + ":" + version 273 + ":" + new String(data) 274 + ":" + (stat == null ? "null" : stat.getAversion() 275 + ":" + stat.getCversion() 276 + ":" + stat.getEphemeralOwner() 277 + ":" + stat.getVersion()); 278 } 279 280 } 281 282 public static class ChildrenCB extends AsyncCB implements ChildrenCallback { 283 284 List<String> children = new ArrayList<String>(); 285 ChildrenCB(ZooKeeper zk)286 ChildrenCB(ZooKeeper zk) { 287 this(zk, new CountDownLatch(1)); 288 } 289 ChildrenCB(ZooKeeper zk, CountDownLatch latch)290 ChildrenCB(ZooKeeper zk, CountDownLatch latch) { 291 super(zk, latch); 292 } 293 processResult(int rc, String path, Object ctx, List<String> children)294 public void processResult(int rc, String path, Object ctx, List<String> children) { 295 this.children = (children == null ? new ArrayList<String>() : children); 296 Collections.sort(this.children); 297 super.processResult(Code.get(rc), path, ctx); 298 } 299 createNode()300 public StringCB createNode() { 301 StringCB parent = new StringCB(zk); 302 parent.verifyCreate(); 303 304 return parent; 305 } 306 createNode(StringCB parent)307 public StringCB createNode(StringCB parent) { 308 String childName = "bar"; 309 310 return createNode(parent, childName); 311 } 312 createNode(StringCB parent, String childName)313 public StringCB createNode(StringCB parent, String childName) { 314 StringCB child = new StringCB(zk); 315 child.setPath(parent.path + "/" + childName); 316 child.verifyCreate(); 317 318 return child; 319 } 320 verifyGetChildrenEmpty()321 public void verifyGetChildrenEmpty() { 322 StringCB parent = createNode(); 323 path = parent.path; 324 verify(); 325 } 326 verifyGetChildrenSingle()327 public void verifyGetChildrenSingle() { 328 StringCB parent = createNode(); 329 StringCB child = createNode(parent); 330 331 path = parent.path; 332 children.add(child.nodeName()); 333 334 verify(); 335 } 336 verifyGetChildrenTwo()337 public void verifyGetChildrenTwo() { 338 StringCB parent = createNode(); 339 StringCB child1 = createNode(parent, "child1"); 340 StringCB child2 = createNode(parent, "child2"); 341 342 path = parent.path; 343 children.add(child1.nodeName()); 344 children.add(child2.nodeName()); 345 346 verify(); 347 } 348 verifyGetChildrenFailure_NoNode()349 public void verifyGetChildrenFailure_NoNode() { 350 rc = KeeperException.Code.NONODE; 351 verify(); 352 } 353 354 @Override verify()355 public void verify() { 356 zk.getChildren(path, false, this, toString()); 357 super.verify(); 358 } 359 360 @Override toString()361 public String toString() { 362 return super.toString() + children.toString(); 363 } 364 365 } 366 367 public static class Children2CB extends AsyncCB implements Children2Callback { 368 369 List<String> children = new ArrayList<String>(); 370 Children2CB(ZooKeeper zk)371 Children2CB(ZooKeeper zk) { 372 this(zk, new CountDownLatch(1)); 373 } 374 Children2CB(ZooKeeper zk, CountDownLatch latch)375 Children2CB(ZooKeeper zk, CountDownLatch latch) { 376 super(zk, latch); 377 } 378 processResult(int rc, String path, Object ctx, List<String> children, Stat stat)379 public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) { 380 this.children = (children == null ? new ArrayList<String>() : children); 381 Collections.sort(this.children); 382 super.processResult(Code.get(rc), path, ctx); 383 } 384 createNode()385 public StringCB createNode() { 386 StringCB parent = new StringCB(zk); 387 parent.verifyCreate(); 388 389 return parent; 390 } 391 createNode(StringCB parent)392 public StringCB createNode(StringCB parent) { 393 String childName = "bar"; 394 395 return createNode(parent, childName); 396 } 397 createNode(StringCB parent, String childName)398 public StringCB createNode(StringCB parent, String childName) { 399 StringCB child = new StringCB(zk); 400 child.setPath(parent.path + "/" + childName); 401 child.verifyCreate(); 402 403 return child; 404 } 405 verifyGetChildrenEmpty()406 public void verifyGetChildrenEmpty() { 407 StringCB parent = createNode(); 408 path = parent.path; 409 verify(); 410 } 411 verifyGetChildrenSingle()412 public void verifyGetChildrenSingle() { 413 StringCB parent = createNode(); 414 StringCB child = createNode(parent); 415 416 path = parent.path; 417 children.add(child.nodeName()); 418 419 verify(); 420 } 421 verifyGetChildrenTwo()422 public void verifyGetChildrenTwo() { 423 StringCB parent = createNode(); 424 StringCB child1 = createNode(parent, "child1"); 425 StringCB child2 = createNode(parent, "child2"); 426 427 path = parent.path; 428 children.add(child1.nodeName()); 429 children.add(child2.nodeName()); 430 431 verify(); 432 } 433 verifyGetChildrenFailure_NoNode()434 public void verifyGetChildrenFailure_NoNode() { 435 rc = KeeperException.Code.NONODE; 436 verify(); 437 } 438 439 @Override verify()440 public void verify() { 441 zk.getChildren(path, false, this, toString()); 442 super.verify(); 443 } 444 445 @Override toString()446 public String toString() { 447 return super.toString() + children.toString(); 448 } 449 450 } 451 452 public static class Create2CB extends AsyncCB implements Create2Callback { 453 454 byte[] data = new byte[10]; 455 List<ACL> acl = Ids.CREATOR_ALL_ACL; 456 CreateMode flags = CreateMode.PERSISTENT; 457 String name = path; 458 Stat stat = new Stat(); 459 Create2CB(ZooKeeper zk)460 Create2CB(ZooKeeper zk) { 461 this(zk, new CountDownLatch(1)); 462 } 463 Create2CB(ZooKeeper zk, CountDownLatch latch)464 Create2CB(ZooKeeper zk, CountDownLatch latch) { 465 super(zk, latch); 466 } 467 setPath(String path)468 public void setPath(String path) { 469 super.setPath(path); 470 this.name = path; 471 } 472 nodeName()473 public String nodeName() { 474 return path.substring(path.lastIndexOf('/') + 1); 475 } 476 processResult(int rc, String path, Object ctx, String name, Stat stat)477 public void processResult(int rc, String path, Object ctx, String name, Stat stat) { 478 this.name = name; 479 this.stat = stat; 480 super.processResult(Code.get(rc), path, ctx); 481 } 482 create()483 public AsyncCB create() { 484 zk.create(path, data, acl, flags, this, toString()); 485 return this; 486 } 487 verifyCreate()488 public void verifyCreate() { 489 create(); 490 verify(); 491 } 492 verifyCreateFailure_NodeExists()493 public void verifyCreateFailure_NodeExists() { 494 new Create2CB(zk).verifyCreate(); 495 rc = Code.NODEEXISTS; 496 name = null; 497 stat = null; 498 zk.create(path, data, acl, flags, this, toString()); 499 verify(); 500 } 501 verifyCreateFailure_NoNode()502 public void verifyCreateFailure_NoNode() { 503 rc = Code.NONODE; 504 name = null; 505 stat = null; 506 path = path + "/bar"; 507 zk.create(path, data, acl, flags, this, toString()); 508 509 verify(); 510 } 511 verifyCreateFailure_NoChildForEphemeral()512 public void verifyCreateFailure_NoChildForEphemeral() { 513 new StringCB(zk).verifyCreateEphemeral(); 514 515 rc = Code.NOCHILDRENFOREPHEMERALS; 516 name = null; 517 stat = null; 518 path = path + "/bar"; 519 zk.create(path, data, acl, flags, this, toString()); 520 521 verify(); 522 } 523 524 @Override toString()525 public String toString() { 526 return super.toString() 527 + name + ":" 528 + (stat == null 529 ? "null" 530 : stat.getAversion() 531 + ":" + stat.getCversion() 532 + ":" + stat.getEphemeralOwner() 533 + ":" + stat.getVersion()); 534 } 535 536 } 537 538 public static class DataCB extends AsyncCB implements DataCallback { 539 540 byte[] data = new byte[10]; 541 Stat stat = new Stat(); 542 DataCB(ZooKeeper zk)543 DataCB(ZooKeeper zk) { 544 this(zk, new CountDownLatch(1)); 545 } 546 DataCB(ZooKeeper zk, CountDownLatch latch)547 DataCB(ZooKeeper zk, CountDownLatch latch) { 548 super(zk, latch); 549 stat.setAversion(0); 550 stat.setCversion(0); 551 stat.setEphemeralOwner(0); 552 stat.setVersion(0); 553 } 554 processResult(int rc, String path, Object ctx, byte[] data, Stat stat)555 public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) { 556 this.data = data; 557 this.stat = stat; 558 super.processResult(Code.get(rc), path, ctx); 559 } 560 verifyGetData()561 public void verifyGetData() { 562 new StringCB(zk).verifyCreate(); 563 564 zk.getData(path, false, this, toString()); 565 verify(); 566 } 567 verifyGetDataFailure_NoNode()568 public void verifyGetDataFailure_NoNode() { 569 rc = KeeperException.Code.NONODE; 570 data = null; 571 stat = null; 572 zk.getData(path, false, this, toString()); 573 verify(); 574 } 575 576 @Override toString()577 public String toString() { 578 return super.toString() 579 + ":" + (data == null ? "null" : new String(data)) 580 + ":" + (stat == null ? "null" : stat.getAversion() 581 + ":" + stat.getCversion() 582 + ":" + stat.getEphemeralOwner() 583 + ":" + stat.getVersion()); 584 } 585 586 } 587 588 public static class StatCB extends AsyncCB implements StatCallback { 589 590 List<ACL> acl = Ids.CREATOR_ALL_ACL; 591 int version = 0; 592 Stat stat = new Stat(); 593 byte[] data = "testing".getBytes(); 594 StatCB(ZooKeeper zk)595 StatCB(ZooKeeper zk) { 596 this(zk, new CountDownLatch(1)); 597 } 598 StatCB(ZooKeeper zk, CountDownLatch latch)599 StatCB(ZooKeeper zk, CountDownLatch latch) { 600 super(zk, latch); 601 stat.setAversion(0); 602 stat.setCversion(0); 603 stat.setEphemeralOwner(0); 604 stat.setVersion(0); 605 } 606 processResult(int rc, String path, Object ctx, Stat stat)607 public void processResult(int rc, String path, Object ctx, Stat stat) { 608 this.stat = stat; 609 super.processResult(Code.get(rc), path, ctx); 610 } 611 verifySetACL()612 public void verifySetACL() { 613 stat.setAversion(1); 614 new StringCB(zk).verifyCreate(); 615 616 zk.setACL(path, acl, version, this, toString()); 617 verify(); 618 } 619 verifySetACLFailure_NoNode()620 public void verifySetACLFailure_NoNode() { 621 rc = KeeperException.Code.NONODE; 622 stat = null; 623 zk.setACL(path, acl, version, this, toString()); 624 verify(); 625 } 626 verifySetACLFailure_BadVersion()627 public void verifySetACLFailure_BadVersion() { 628 new StringCB(zk).verifyCreate(); 629 630 rc = Code.BADVERSION; 631 stat = null; 632 zk.setACL(path, acl, version + 1, this, toString()); 633 634 verify(); 635 } 636 setData()637 public void setData() { 638 zk.setData(path, data, version, this, toString()); 639 } 640 verifySetData()641 public void verifySetData() { 642 stat.setVersion(1); 643 new StringCB(zk).verifyCreate(); 644 645 setData(); 646 verify(); 647 } 648 verifySetDataFailure_NoNode()649 public void verifySetDataFailure_NoNode() { 650 rc = KeeperException.Code.NONODE; 651 stat = null; 652 zk.setData(path, data, version, this, toString()); 653 verify(); 654 } 655 verifySetDataFailure_BadVersion()656 public void verifySetDataFailure_BadVersion() { 657 new StringCB(zk).verifyCreate(); 658 659 rc = Code.BADVERSION; 660 stat = null; 661 zk.setData(path, data, version + 1, this, toString()); 662 663 verify(); 664 } 665 verifyExists()666 public void verifyExists() { 667 new StringCB(zk).verifyCreate(); 668 669 zk.exists(path, false, this, toString()); 670 verify(); 671 } 672 verifyExistsFailure_NoNode()673 public void verifyExistsFailure_NoNode() { 674 rc = KeeperException.Code.NONODE; 675 stat = null; 676 zk.exists(path, false, this, toString()); 677 verify(); 678 } 679 680 @Override toString()681 public String toString() { 682 return super.toString() + version 683 + ":" + new String(data) 684 + ":" + (stat == null ? "null" : stat.getAversion() 685 + ":" + stat.getCversion() 686 + ":" + stat.getEphemeralOwner() 687 + ":" + stat.getVersion()); 688 } 689 690 } 691 692 public static class VoidCB extends AsyncCB implements VoidCallback { 693 694 int version = 0; 695 VoidCB(ZooKeeper zk)696 VoidCB(ZooKeeper zk) { 697 this(zk, new CountDownLatch(1)); 698 } 699 VoidCB(ZooKeeper zk, CountDownLatch latch)700 VoidCB(ZooKeeper zk, CountDownLatch latch) { 701 super(zk, latch); 702 } 703 processResult(int rc, String path, Object ctx)704 public void processResult(int rc, String path, Object ctx) { 705 super.processResult(Code.get(rc), path, ctx); 706 } 707 delete()708 public void delete() { 709 zk.delete(path, version, this, toString()); 710 } 711 verifyDelete()712 public void verifyDelete() { 713 new StringCB(zk).verifyCreate(); 714 715 delete(); 716 verify(); 717 } 718 verifyDeleteFailure_NoNode()719 public void verifyDeleteFailure_NoNode() { 720 rc = Code.NONODE; 721 zk.delete(path, version, this, toString()); 722 verify(); 723 } 724 verifyDeleteFailure_BadVersion()725 public void verifyDeleteFailure_BadVersion() { 726 new StringCB(zk).verifyCreate(); 727 rc = Code.BADVERSION; 728 zk.delete(path, version + 1, this, toString()); 729 verify(); 730 } 731 verifyDeleteFailure_NotEmpty()732 public void verifyDeleteFailure_NotEmpty() { 733 StringCB scb = new StringCB(zk); 734 scb.create(); 735 scb.setPath(path + "/bar"); 736 scb.create(); 737 738 rc = Code.NOTEMPTY; 739 zk.delete(path, version, this, toString()); 740 verify(); 741 } 742 sync()743 public void sync() { 744 zk.sync(path, this, toString()); 745 } 746 verifySync()747 public void verifySync() { 748 sync(); 749 verify(); 750 } 751 752 @Override toString()753 public String toString() { 754 return super.toString() + version; 755 } 756 757 } 758 759 public static class MultiCB implements MultiCallback { 760 761 ZooKeeper zk; 762 int rc; 763 List<OpResult> opResults; 764 final CountDownLatch latch = new CountDownLatch(1); 765 MultiCB(ZooKeeper zk)766 MultiCB(ZooKeeper zk) { 767 this.zk = zk; 768 } 769 processResult(int rc, String path, Object ctx, List<OpResult> opResults)770 public void processResult(int rc, String path, Object ctx, List<OpResult> opResults) { 771 this.rc = rc; 772 this.opResults = opResults; 773 latch.countDown(); 774 } 775 latch_await()776 void latch_await() { 777 try { 778 latch.await(10000, TimeUnit.MILLISECONDS); 779 } catch (InterruptedException e) { 780 fail("unexpected interrupt"); 781 } 782 assertSame(0L, latch.getCount()); 783 } 784 verifyMulti()785 public void verifyMulti() { 786 List<Op> ops = Arrays.asList( 787 Op.create("/multi", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT), 788 Op.delete("/multi", -1)); 789 zk.multi(ops, this, null); 790 latch_await(); 791 792 assertEquals(this.rc, KeeperException.Code.OK.intValue()); 793 assertTrue(this.opResults.get(0) instanceof OpResult.CreateResult); 794 assertTrue(this.opResults.get(1) instanceof OpResult.DeleteResult); 795 } 796 verifyMultiFailure_AllErrorResult()797 public void verifyMultiFailure_AllErrorResult() { 798 List<Op> ops = Arrays.asList( 799 Op.create("/multi", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT), 800 Op.delete("/nonexist1", -1), Op.setData("/multi", "test".getBytes(), -1)); 801 zk.multi(ops, this, null); 802 latch_await(); 803 804 assertTrue(this.opResults.get(0) instanceof OpResult.ErrorResult); 805 assertTrue(this.opResults.get(1) instanceof OpResult.ErrorResult); 806 assertTrue(this.opResults.get(2) instanceof OpResult.ErrorResult); 807 } 808 verifyMultiFailure_NoSideEffect()809 public void verifyMultiFailure_NoSideEffect() throws KeeperException, InterruptedException { 810 List<Op> ops = Arrays.asList( 811 Op.create("/multi", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT), 812 Op.delete("/nonexist1", -1)); 813 zk.multi(ops, this, null); 814 latch_await(); 815 816 assertTrue(this.opResults.get(0) instanceof OpResult.ErrorResult); 817 assertNull(zk.exists("/multi", false)); 818 } 819 verifyMultiSequential_NoSideEffect()820 public void verifyMultiSequential_NoSideEffect() throws Exception { 821 StringCB scb = new StringCB(zk); 822 scb.verifyCreate(); 823 String path = scb.path + "-"; 824 String seqPath = path + "0000000002"; 825 826 zk.create(path, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); 827 assertNotNull(zk.exists(path + "0000000001", false)); 828 829 List<Op> ops = Arrays.asList( 830 Op.create(path, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL), 831 Op.delete("/nonexist", -1)); 832 zk.multi(ops, this, null); 833 latch_await(); 834 835 assertNull(zk.exists(seqPath, false)); 836 zk.create(path, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); 837 assertNotNull(zk.exists(seqPath, false)); 838 } 839 840 } 841 842 } 843