This is an automated email from the ASF dual-hosted git repository.

cmccabe pushed a commit to branch cmccabe_2023-06-30_shell
in repository https://gitbox.apache.org/repos/asf/kafka.git

commit 8ffa695d7f81e3d6435059927f4699281bfc9b44
Author: Colin P. McCabe <[email protected]>
AuthorDate: Fri Jun 30 13:00:13 2023 -0700

    MINOR: some minor shell fixes and improvements
    
    Make the output of 'find' and 'ls' sorted alphabetically.
    
    Add GlobComponentTest.java to test globbing.
    
    Add shell/src/test/resources/log4j.properties so that shell JUnit tests 
show some output
---
 .../kafka/shell/command/FindCommandHandler.java    |  5 +-
 .../kafka/shell/command/LsCommandHandler.java      |  1 +
 .../kafka/shell/state/MetadataShellPublisher.java  |  4 ++
 .../apache/kafka/shell/glob/GlobComponentTest.java | 76 ++++++++++++++++++++++
 shell/src/test/resources/log4j.properties          | 22 +++++++
 5 files changed, 107 insertions(+), 1 deletion(-)

diff --git 
a/shell/src/main/java/org/apache/kafka/shell/command/FindCommandHandler.java 
b/shell/src/main/java/org/apache/kafka/shell/command/FindCommandHandler.java
index 8e11385b6ef..a41b0b21ca3 100644
--- a/shell/src/main/java/org/apache/kafka/shell/command/FindCommandHandler.java
+++ b/shell/src/main/java/org/apache/kafka/shell/command/FindCommandHandler.java
@@ -26,6 +26,7 @@ import org.apache.kafka.shell.state.MetadataShellState;
 import org.jline.reader.Candidate;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
@@ -103,7 +104,9 @@ public final class FindCommandHandler implements 
Commands.Handler {
     private void find(PrintWriter writer, String path, MetadataNode node) {
         writer.println(path);
         if (node.isDirectory()) {
-            for (String name : node.childNames()) {
+            ArrayList<String> childNames = new ArrayList<>(node.childNames());
+            childNames.sort(String::compareTo);
+            for (String name : childNames) {
                 String nextPath = path.equals("/") ? path + name : path + "/" 
+ name;
                 MetadataNode child = node.child(name);
                 if (child == null) {
diff --git 
a/shell/src/main/java/org/apache/kafka/shell/command/LsCommandHandler.java 
b/shell/src/main/java/org/apache/kafka/shell/command/LsCommandHandler.java
index 728fe7282f0..90587d5e61d 100644
--- a/shell/src/main/java/org/apache/kafka/shell/command/LsCommandHandler.java
+++ b/shell/src/main/java/org/apache/kafka/shell/command/LsCommandHandler.java
@@ -117,6 +117,7 @@ public final class LsCommandHandler implements 
Commands.Handler {
                     if (node.isDirectory()) {
                         List<String> children = new ArrayList<>();
                         children.addAll(node.childNames());
+                        children.sort(String::compareTo);
                         targetDirectories.add(
                             new TargetDirectory(info.lastPathComponent(), 
children));
                     } else {
diff --git 
a/shell/src/main/java/org/apache/kafka/shell/state/MetadataShellPublisher.java 
b/shell/src/main/java/org/apache/kafka/shell/state/MetadataShellPublisher.java
index c0c6d296b4b..ec4998edca7 100644
--- 
a/shell/src/main/java/org/apache/kafka/shell/state/MetadataShellPublisher.java
+++ 
b/shell/src/main/java/org/apache/kafka/shell/state/MetadataShellPublisher.java
@@ -51,4 +51,8 @@ public class MetadataShellPublisher implements 
MetadataPublisher {
         log.trace("onMetadataUpdate newImage={}", newImage);
         state.setRoot(new RootShellNode(newImage));
     }
+
+    public MetadataShellState state() {
+        return state;
+    }
 }
diff --git 
a/shell/src/test/java/org/apache/kafka/shell/glob/GlobComponentTest.java 
b/shell/src/test/java/org/apache/kafka/shell/glob/GlobComponentTest.java
new file mode 100644
index 00000000000..ae883ee8bd3
--- /dev/null
+++ b/shell/src/test/java/org/apache/kafka/shell/glob/GlobComponentTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.kafka.shell.glob;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+
+@Timeout(value = 120000, unit = MILLISECONDS)
+public class GlobComponentTest {
+    private void verifyIsLiteral(GlobComponent globComponent, String 
component) {
+        assertTrue(globComponent.literal());
+        assertEquals(component, globComponent.component());
+        assertTrue(globComponent.matches(component));
+        assertFalse(globComponent.matches(component + "foo"));
+    }
+
+    @Test
+    public void testLiteralComponent() {
+        verifyIsLiteral(new GlobComponent("abc"), "abc");
+        verifyIsLiteral(new GlobComponent(""), "");
+        verifyIsLiteral(new GlobComponent("foobar_123"), "foobar_123");
+        verifyIsLiteral(new GlobComponent("$blah+"), "$blah+");
+    }
+
+    @Test
+    public void testToRegularExpression() {
+        assertNull(GlobComponent.toRegularExpression("blah"));
+        assertNull(GlobComponent.toRegularExpression(""));
+        assertNull(GlobComponent.toRegularExpression("does not need a regex, 
actually"));
+        assertEquals("^\\$blah.*$", 
GlobComponent.toRegularExpression("$blah*"));
+        assertEquals("^.*$", GlobComponent.toRegularExpression("*"));
+        assertEquals("^foo(?:(?:bar)|(?:baz))$", 
GlobComponent.toRegularExpression("foo{bar,baz}"));
+    }
+
+    @Test
+    public void testGlobMatch() {
+        GlobComponent star = new GlobComponent("*");
+        assertFalse(star.literal());
+        assertTrue(star.matches(""));
+        assertTrue(star.matches("anything"));
+        GlobComponent question = new GlobComponent("b?b");
+        assertFalse(question.literal());
+        assertFalse(question.matches(""));
+        assertTrue(question.matches("bob"));
+        assertTrue(question.matches("bib"));
+        assertFalse(question.matches("bic"));
+        GlobComponent foobarOrFoobaz = new GlobComponent("foo{bar,baz}");
+        assertFalse(foobarOrFoobaz.literal());
+        assertTrue(foobarOrFoobaz.matches("foobar"));
+        assertTrue(foobarOrFoobaz.matches("foobaz"));
+        assertFalse(foobarOrFoobaz.matches("foobah"));
+        assertFalse(foobarOrFoobaz.matches("foo"));
+        assertFalse(foobarOrFoobaz.matches("baz"));
+    }
+}
diff --git a/shell/src/test/resources/log4j.properties 
b/shell/src/test/resources/log4j.properties
new file mode 100644
index 00000000000..db3879386f1
--- /dev/null
+++ b/shell/src/test/resources/log4j.properties
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+log4j.rootLogger=DEBUG, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d] %p %m (%c:%L)%n
+
+log4j.logger.org.apache.kafka=DEBUG
+log4j.logger.org.apache.zookeeper=WARN

Reply via email to