This is an automated email from the ASF dual-hosted git repository.
jmclean pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 93aa2e8730 Add test for RemoveRoleFromGroup to verify UNKNOWN_GROUP
error handli… (#9335)
93aa2e8730 is described below
commit 93aa2e87303f6e48a15bf2041af65abc54926972
Author: Umair Shahid <[email protected]>
AuthorDate: Wed Dec 3 05:19:39 2025 +0100
Add test for RemoveRoleFromGroup to verify UNKNOWN_GROUP error handli…
(#9335)
…ng Fixes #9306
This PR adds a missing unit test for the RemoveRoleFromGroup CLI
command.
The test covers the scenario where a user attempts to remove a role from
a
group that does not exist, and the GravitinoClient throws a
NoSuchGroupException.
The new test ensures that the CLI behaves consistently with other
command implementations
when encountering a “missing group” error.
### What the Test Covers
- Creates a spy of RemoveRoleFromGroup to override client construction.
- Mocks GravitinoClient to throw NoSuchGroupException when
revokeRolesFromGroup is called.
- Ensures the command:
- Exits with code **-1** (using `Main.useExit = false`)
- Prints **ErrorMessages.UNKNOWN_GROUP** to stderr
- Wraps the error in a RuntimeException, consistent with CLI error
handling
### Why This Is Needed
Other CLI commands (CreateGroup, DeleteGroup, RemoveAllRoles…) already
have
coverage verifying their error handling. This test brings
RemoveRoleFromGroup
in line with those patterns and ensures regressions are caught early.
### Additional Notes
- The test resets `System.err` and `Main.useExit` to avoid interaction
with other tests.
- UTF-8 decoding is used explicitly to satisfy ErrorProne rules and
match the
project-wide charset expectations on UNIX-based build agents.
### Fixes
Fixes #9306
---------
Co-authored-by: umairshahid88 <[email protected]>
---
.../cli/commands/RemoveRoleFromGroup.java | 3 +
.../cli/commands/TestRemoveRoleFromGroup.java | 80 ++++++++++++++++++++++
2 files changed, 83 insertions(+)
diff --git
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java
index 23ef742580..51760e66db 100644
---
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java
+++
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import org.apache.gravitino.cli.CommandContext;
import org.apache.gravitino.cli.ErrorMessages;
import org.apache.gravitino.client.GravitinoClient;
+import org.apache.gravitino.exceptions.NoSuchGroupException;
import org.apache.gravitino.exceptions.NoSuchMetalakeException;
import org.apache.gravitino.exceptions.NoSuchRoleException;
import org.apache.gravitino.exceptions.NoSuchUserException;
@@ -66,6 +67,8 @@ public class RemoveRoleFromGroup extends Command {
exitWithError(ErrorMessages.UNKNOWN_ROLE);
} catch (NoSuchUserException err) {
exitWithError(ErrorMessages.UNKNOWN_USER);
+ } catch (NoSuchGroupException err) {
+ exitWithError(ErrorMessages.UNKNOWN_GROUP);
} catch (Exception exp) {
exitWithError(exp.getMessage());
}
diff --git
a/clients/cli/src/test/java/org/apache/gravitino/cli/commands/TestRemoveRoleFromGroup.java
b/clients/cli/src/test/java/org/apache/gravitino/cli/commands/TestRemoveRoleFromGroup.java
new file mode 100644
index 0000000000..2d1b5db847
--- /dev/null
+++
b/clients/cli/src/test/java/org/apache/gravitino/cli/commands/TestRemoveRoleFromGroup.java
@@ -0,0 +1,80 @@
+/*
+ * 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.gravitino.cli.commands;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Collections;
+import org.apache.commons.cli.CommandLine;
+import org.apache.gravitino.cli.CommandContext;
+import org.apache.gravitino.cli.ErrorMessages;
+import org.apache.gravitino.cli.Main;
+import org.apache.gravitino.client.GravitinoClient;
+import org.apache.gravitino.exceptions.NoSuchGroupException;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class TestRemoveRoleFromGroup {
+
+ private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+ private final PrintStream originalErr = System.err;
+
+ @BeforeEach
+ void setup() {
+ System.setErr(new PrintStream(errContent));
+ }
+
+ @AfterEach
+ void restore() {
+ System.setErr(originalErr);
+ Main.useExit = true;
+ }
+
+ @Test
+ void handleWithMissingGroupExitsWithUnknownGroupError() throws Exception {
+ Main.useExit = false;
+ CommandLine mockCmdLine = mock(CommandLine.class);
+ CommandContext context = new CommandContext(mockCmdLine);
+
+ RemoveRoleFromGroup command =
+ spy(new RemoveRoleFromGroup(context, "metalake1", "group1", "role1"));
+
+ GravitinoClient mockClient = mock(GravitinoClient.class);
+ doReturn(mockClient).when(command).buildClient("metalake1");
+
+ doThrow(new NoSuchGroupException("group missing"))
+ .when(mockClient)
+ .revokeRolesFromGroup(Collections.singletonList("role1"), "group1");
+
+ RuntimeException ex = assertThrows(RuntimeException.class,
command::handle);
+
+ assertTrue(ex.getMessage().contains("Exit with code -1"));
+
assertTrue(errContent.toString(UTF_8).contains(ErrorMessages.UNKNOWN_GROUP));
+ }
+}