diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/ZKUtil.java b/zookeeper-server/src/main/java/org/apache/zookeeper/ZKUtil.java index fd35ae39a5d..d2063414470 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/ZKUtil.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/ZKUtil.java @@ -193,7 +193,8 @@ public static List listSubTreeBFS( String node = queue.poll(); List children = zk.getChildren(node, false); for (final String child : children) { - final String childPath = node + "/" + child; + // Fix IllegalArgumentException when list "/". + final String childPath = (node.equals("/") ? "" : node) + "/" + child; queue.add(childPath); tree.add(childPath); } diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/ZKUtilTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/ZKUtilTest.java index 1111c2a237a..51df907023a 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/ZKUtilTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/ZKUtilTest.java @@ -20,15 +20,20 @@ import static org.junit.Assume.assumeTrue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import java.io.File; import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.UUID; +import org.apache.zookeeper.test.ClientBase; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -public class ZKUtilTest { +public class ZKUtilTest extends ClientBase { private static final File testData = new File(System.getProperty("test.data.dir", "build/test/data")); @@ -85,4 +90,33 @@ public void testUnreadableFileInput() throws Exception { assertEquals(expectedMessage, error); } + @Test + public void testListRootPathSuccess() throws IOException, InterruptedException, KeeperException { + TestableZooKeeper zk = createClient(); + zk.setData("/", "some".getBytes(), -1); + zk.create("/a", "some".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + zk.create("/a/b", "some".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + + List list = ZKUtil.listSubTreeBFS(zk, "/"); + list.remove(Quotas.procZookeeper); + list.remove(Quotas.quotaZookeeper); + list.remove(ZooDefs.CONFIG_NODE); + assertEquals(3, list.size()); + assertIterableEquals(Arrays.asList("/", "/a", "/a/b"), list); + } + + @Test + public void testListNoneRootPathSuccess() throws IOException, InterruptedException, KeeperException { + TestableZooKeeper zk = createClient(); + zk.setData("/", "some".getBytes(), -1); + zk.create("/a", "some".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + zk.create("/a/b", "some".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + List aList = ZKUtil.listSubTreeBFS(zk, "/a"); + assertEquals(2, aList.size()); + assertIterableEquals(Arrays.asList("/a", "/a/b"), aList); + + List bList = ZKUtil.listSubTreeBFS(zk, "/a/b"); + assertEquals(1, bList.size()); + assertIterableEquals(Collections.singletonList("/a/b"), bList); + } }