diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java index 3423cee07f7..1d6db1a5acd 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java @@ -32,6 +32,7 @@ public class ErrorMessages { public static final String MISSING_NAME = "Missing --name option."; public static final String MISSING_GROUP = "Missing --group option."; public static final String MISSING_USER = "Missing --user option."; + public static final String MISSING_TAG = "Missing --tag option."; public static final String METALAKE_EXISTS = "Metalake already exists."; public static final String CATALOG_EXISTS = "Catalog already exists."; public static final String SCHEMA_EXISTS = "Schema already exists."; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 7c8539ba1c7..48d97294350 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -31,8 +31,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; @@ -255,6 +253,7 @@ private void handleCatalogCommand() { String outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT); Command.setAuthenticationMode(auth, userName); + List missingEntities = Lists.newArrayList(); // Handle the CommandActions.LIST action separately as it doesn't use `catalog` if (CommandActions.LIST.equals(command)) { @@ -263,6 +262,8 @@ private void handleCatalogCommand() { } String catalog = name.getCatalogName(); + if (catalog == null) missingEntities.add(CommandEntities.CATALOG); + checkEntities(missingEntities); switch (command) { case CommandActions.DETAILS: @@ -343,29 +344,21 @@ private void handleSchemaCommand() { String catalog = name.getCatalogName(); Command.setAuthenticationMode(auth, userName); + List missingEntities = Lists.newArrayList(); if (metalake == null) missingEntities.add(CommandEntities.METALAKE); if (catalog == null) missingEntities.add(CommandEntities.CATALOG); // Handle the CommandActions.LIST action separately as it doesn't use `schema` if (CommandActions.LIST.equals(command)) { - if (!missingEntities.isEmpty()) { - System.err.println("Missing required argument(s): " + COMMA_JOINER.join(missingEntities)); - Main.exit(-1); - } + checkEntities(missingEntities); newListSchema(url, ignore, metalake, catalog).handle(); return; } String schema = name.getSchemaName(); - if (schema == null) { - missingEntities.add(CommandEntities.SCHEMA); - } - - if (!missingEntities.isEmpty()) { - System.err.println("Missing required argument(s): " + COMMA_JOINER.join(missingEntities)); - Main.exit(-1); - } + if (schema == null) missingEntities.add(CommandEntities.SCHEMA); + checkEntities(missingEntities); switch (command) { case CommandActions.DETAILS: @@ -421,33 +414,20 @@ private void handleTableCommand() { String schema = name.getSchemaName(); Command.setAuthenticationMode(auth, userName); - List missingEntities = - Stream.of( - catalog == null ? CommandEntities.CATALOG : null, - schema == null ? CommandEntities.SCHEMA : null) - .filter(Objects::nonNull) - .collect(Collectors.toList()); + List missingEntities = Lists.newArrayList(); + if (catalog == null) missingEntities.add(CommandEntities.CATALOG); + if (schema == null) missingEntities.add(CommandEntities.SCHEMA); // Handle CommandActions.LIST action separately as it doesn't require the `table` if (CommandActions.LIST.equals(command)) { - if (!missingEntities.isEmpty()) { - System.err.println( - "Missing required argument(s): " + Joiner.on(", ").join(missingEntities)); - Main.exit(-1); - } + checkEntities(missingEntities); newListTables(url, ignore, metalake, catalog, schema).handle(); return; } String table = name.getTableName(); - if (table == null) { - missingEntities.add(CommandEntities.TABLE); - } - - if (!missingEntities.isEmpty()) { - System.err.println("Missing required argument(s): " + Joiner.on(", ").join(missingEntities)); - Main.exit(-1); - } + if (table == null) missingEntities.add(CommandEntities.TABLE); + checkEntities(missingEntities); switch (command) { case CommandActions.DETAILS: @@ -527,7 +507,7 @@ protected void handleUserCommand() { if (user == null && !CommandActions.LIST.equals(command)) { System.err.println(ErrorMessages.MISSING_USER); - return; + Main.exit(-1); } switch (command) { @@ -588,7 +568,7 @@ protected void handleGroupCommand() { if (group == null && !CommandActions.LIST.equals(command)) { System.err.println(ErrorMessages.MISSING_GROUP); - return; + Main.exit(-1); } switch (command) { @@ -647,6 +627,13 @@ protected void handleTagCommand() { Command.setAuthenticationMode(auth, userName); String[] tags = line.getOptionValues(GravitinoOptions.TAG); + if (tags == null + && !((CommandActions.REMOVE.equals(command) && line.hasOption(GravitinoOptions.FORCE)) + || CommandActions.LIST.equals(command))) { + System.err.println(ErrorMessages.MISSING_TAG); + Main.exit(-1); + } + if (tags != null) { tags = Arrays.stream(tags).distinct().toArray(String[]::new); } @@ -790,12 +777,20 @@ private void handleColumnCommand() { Command.setAuthenticationMode(auth, userName); + List missingEntities = Lists.newArrayList(); + if (catalog == null) missingEntities.add(CommandEntities.CATALOG); + if (schema == null) missingEntities.add(CommandEntities.SCHEMA); + if (table == null) missingEntities.add(CommandEntities.TABLE); + if (CommandActions.LIST.equals(command)) { + checkEntities(missingEntities); newListColumns(url, ignore, metalake, catalog, schema, table).handle(); return; } String column = name.getColumnName(); + if (column == null) missingEntities.add(CommandEntities.COLUMN); + checkEntities(missingEntities); switch (command) { case CommandActions.DETAILS: @@ -965,12 +960,19 @@ private void handleTopicCommand() { Command.setAuthenticationMode(auth, userName); + List missingEntities = Lists.newArrayList(); + if (catalog == null) missingEntities.add(CommandEntities.CATALOG); + if (schema == null) missingEntities.add(CommandEntities.SCHEMA); + if (CommandActions.LIST.equals(command)) { + checkEntities(missingEntities); newListTopics(url, ignore, metalake, catalog, schema).handle(); return; } String topic = name.getTopicName(); + if (topic == null) missingEntities.add(CommandEntities.TOPIC); + checkEntities(missingEntities); switch (command) { case CommandActions.DETAILS: @@ -1040,12 +1042,20 @@ private void handleFilesetCommand() { Command.setAuthenticationMode(auth, userName); + List missingEntities = Lists.newArrayList(); + if (catalog == null) missingEntities.add(CommandEntities.CATALOG); + if (schema == null) missingEntities.add(CommandEntities.SCHEMA); + + // Handle CommandActions.LIST action separately as it doesn't require the `fileset` if (CommandActions.LIST.equals(command)) { + checkEntities(missingEntities); newListFilesets(url, ignore, metalake, catalog, schema).handle(); return; } String fileset = name.getFilesetName(); + if (fileset == null) missingEntities.add(CommandEntities.FILESET); + checkEntities(missingEntities); switch (command) { case CommandActions.DETAILS: @@ -1183,4 +1193,11 @@ public String getAuth() { return null; } + + private void checkEntities(List entities) { + if (!entities.isEmpty()) { + System.err.println("Missing required argument(s): " + COMMA_JOINER.join(entities)); + Main.exit(-1); + } + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java index d751d671731..44e5537955f 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; @@ -30,6 +31,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; @@ -37,6 +39,7 @@ import org.apache.gravitino.cli.commands.CatalogDetails; import org.apache.gravitino.cli.commands.CatalogDisable; import org.apache.gravitino.cli.commands.CatalogEnable; +import org.apache.gravitino.cli.commands.Command; import org.apache.gravitino.cli.commands.CreateCatalog; import org.apache.gravitino.cli.commands.DeleteCatalog; import org.apache.gravitino.cli.commands.ListCatalogProperties; @@ -318,6 +321,36 @@ void testUpdateCatalogNameCommand() { verify(mockUpdateName).handle(); } + @Test + @SuppressWarnings("DefaultCharset") + void testCatalogDetailsCommandWithoutCatalog() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(false); + + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.DETAILS)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newCatalogDetails( + GravitinoCommandLine.DEFAULT_URL, + false, + Command.OUTPUT_FORMAT_TABLE, + "metalake_demo", + "catalog"); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + "Missing --name option." + + "\n" + + "Missing required argument(s): " + + CommandEntities.CATALOG); + } + @Test void testEnableCatalogCommand() { CatalogEnable mockEnable = mock(CatalogEnable.class); diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java index 2eb4c536480..b6159343ef0 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java @@ -28,9 +28,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.base.Joiner; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.AddColumn; @@ -64,6 +66,11 @@ void setUp() { System.setErr(new PrintStream(errContent)); } + @AfterEach + void restoreExitFlg() { + Main.useExit = true; + } + @AfterEach public void restoreStreams() { System.setOut(originalOut); @@ -435,4 +442,208 @@ void testUpdateColumnDefault() { commandLine.handleCommandLine(); verify(mockUpdateDefault).handle(); } + + @Test + @SuppressWarnings("DefaultCharset") + void testDeleteColumnCommandWithoutCatalog() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(CommandEntities.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.COLUMN, CommandActions.DELETE)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newDeleteColumn( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ") + .join( + Arrays.asList( + CommandEntities.CATALOG, + CommandEntities.SCHEMA, + CommandEntities.TABLE, + CommandEntities.COLUMN))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testDeleteColumnCommandWithoutSchema() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(CommandEntities.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.COLUMN, CommandActions.DELETE)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newDeleteColumn( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ") + .join( + Arrays.asList( + CommandEntities.SCHEMA, CommandEntities.TABLE, CommandEntities.COLUMN))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testDeleteColumnCommandWithoutTable() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(CommandEntities.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.COLUMN, CommandActions.DELETE)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newDeleteColumn( + GravitinoCommandLine.DEFAULT_URL, + false, + "metalake_demo", + "catalog", + "schema", + null, + null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.TABLE, CommandEntities.COLUMN))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testDeleteColumnCommandWithoutColumn() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(CommandEntities.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema.users"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.COLUMN, CommandActions.DELETE)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newDeleteColumn( + GravitinoCommandLine.DEFAULT_URL, + false, + "metalake_demo", + "catalog", + "schema", + "users", + null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.COLUMN))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testListColumnCommandWithoutCatalog() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(CommandEntities.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.COLUMN, CommandActions.LIST)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newListColumns( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ") + .join( + Arrays.asList( + CommandEntities.CATALOG, CommandEntities.SCHEMA, CommandEntities.TABLE))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testListColumnCommandWithoutSchema() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(CommandEntities.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.COLUMN, CommandActions.LIST)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newListColumns( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.SCHEMA, CommandEntities.TABLE))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testListColumnCommandWithoutTable() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(CommandEntities.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.COLUMN, CommandActions.LIST)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newListColumns( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + CommandEntities.TABLE); + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java index 314e118c7d7..b46b73cc3dd 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java @@ -19,14 +19,22 @@ package org.apache.gravitino.cli; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.base.Joiner; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.CreateFileset; @@ -38,17 +46,35 @@ import org.apache.gravitino.cli.commands.SetFilesetProperty; import org.apache.gravitino.cli.commands.UpdateFilesetComment; import org.apache.gravitino.cli.commands.UpdateFilesetName; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class TestFilesetCommands { private CommandLine mockCommandLine; private Options mockOptions; + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; @BeforeEach void setUp() { mockCommandLine = mock(CommandLine.class); mockOptions = mock(Options.class); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + } + + @AfterEach + void restoreExitFlg() { + Main.useExit = true; + } + + @AfterEach + public void restoreStreams() { + System.setOut(originalOut); + System.setErr(originalErr); } @Test @@ -322,4 +348,133 @@ void testRemoveFilesetPropertyCommand() { commandLine.handleCommandLine(); verify(mockSetProperties).handle(); } + + @Test + @SuppressWarnings("DefaultCharset") + void testListFilesetCommandWithoutCatalog() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.FILESET, CommandActions.LIST)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newListFilesets(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.CATALOG, CommandEntities.SCHEMA))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testListFilesetCommandWithoutSchema() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.FILESET, CommandActions.LIST)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newListFilesets(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.SCHEMA))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testFilesetDetailCommandWithoutCatalog() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.FILESET, CommandActions.DETAILS)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newFilesetDetails( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ") + .join( + Arrays.asList( + CommandEntities.CATALOG, CommandEntities.SCHEMA, CommandEntities.FILESET))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testFilesetDetailCommandWithoutSchema() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.FILESET, CommandActions.DETAILS)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newFilesetDetails( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.SCHEMA, CommandEntities.FILESET))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testFilesetDetailCommandWithoutFileset() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.FILESET, CommandActions.DETAILS)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newFilesetDetails( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.FILESET))); + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java index 3f1c4a4cb1e..98e3ea910fb 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java @@ -19,12 +19,18 @@ package org.apache.gravitino.cli; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.AddRoleToGroup; @@ -34,17 +40,35 @@ import org.apache.gravitino.cli.commands.GroupDetails; import org.apache.gravitino.cli.commands.ListGroups; import org.apache.gravitino.cli.commands.RemoveRoleFromGroup; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class TestGroupCommands { private CommandLine mockCommandLine; private Options mockOptions; + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; @BeforeEach void setUp() { mockCommandLine = mock(CommandLine.class); mockOptions = mock(Options.class); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + } + + @AfterEach + void restoreExitFlg() { + Main.useExit = true; + } + + @AfterEach + public void restoreStreams() { + System.setOut(originalOut); + System.setErr(originalErr); } @Test @@ -260,4 +284,23 @@ void testAddRolesToGroupCommand() { verify(mockAddSecondRole).handle(); verify(mockAddFirstRole).handle(); } + + @Test + @SuppressWarnings("DefaultCharset") + void testDeleteGroupCommandWithoutGroupOption() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.GROUP)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.GROUP, CommandActions.DELETE)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newDeleteGroup(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals(output, ErrorMessages.MISSING_GROUP); + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestMain.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestMain.java index 377e569aa53..1d1ffded0ff 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestMain.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestMain.java @@ -192,7 +192,6 @@ public void CreateTagWithNoTag() { assertTrue(errContent.toString().contains(ErrorMessages.TAG_EMPTY)); // Expect error } - @Test @SuppressWarnings("DefaultCharset") public void DeleteTagWithNoTag() { String[] args = {"tag", "delete", "--metalake", "metalake_test_no_tag", "-f"}; diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java index 32c289cfd85..c4a8223dd48 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java @@ -19,8 +19,8 @@ package org.apache.gravitino.cli; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -30,6 +30,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.CreateTable; @@ -451,14 +452,15 @@ void testListTableWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newListTables(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null); - assertTrue( - errContent - .toString() - .contains( - "Missing required argument(s): " - + CommandEntities.CATALOG - + ", " - + CommandEntities.SCHEMA)); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + CommandEntities.CATALOG + + ", " + + CommandEntities.SCHEMA); } @Test @@ -478,8 +480,13 @@ void testListTableWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newListTables(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null); - assertTrue( - errContent.toString().contains("Missing required argument(s): " + CommandEntities.SCHEMA)); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + CommandEntities.SCHEMA); } @Test @@ -498,16 +505,17 @@ void testDetailTableWithoutCatalog() { verify(commandLine, never()) .newTableDetails( GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null); - assertTrue( - errContent - .toString() - .contains( - "Missing required argument(s): " - + CommandEntities.CATALOG - + ", " - + CommandEntities.SCHEMA - + ", " - + CommandEntities.TABLE)); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + CommandEntities.CATALOG + + ", " + + CommandEntities.SCHEMA + + ", " + + CommandEntities.TABLE); } @Test @@ -526,14 +534,15 @@ void testDetailTableWithoutSchema() { verify(commandLine, never()) .newTableDetails( GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null); - assertTrue( - errContent - .toString() - .contains( - "Missing required argument(s): " - + CommandEntities.SCHEMA - + ", " - + CommandEntities.TABLE)); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + CommandEntities.SCHEMA + + ", " + + CommandEntities.TABLE); } @Test @@ -554,7 +563,12 @@ void testDetailTableWithoutTable() { verify(commandLine, never()) .newTableDetails( GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); - assertTrue( - errContent.toString().contains("Missing required argument(s): " + CommandEntities.TABLE)); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + CommandEntities.TABLE); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java index 58beb02a8d8..8d7ce17bd31 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java @@ -19,15 +19,21 @@ package org.apache.gravitino.cli; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.CreateTag; @@ -43,6 +49,7 @@ import org.apache.gravitino.cli.commands.UntagEntity; import org.apache.gravitino.cli.commands.UpdateTagComment; import org.apache.gravitino.cli.commands.UpdateTagName; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -51,11 +58,28 @@ class TestTagCommands { private CommandLine mockCommandLine; private Options mockOptions; + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; @BeforeEach void setUp() { mockCommandLine = mock(CommandLine.class); mockOptions = mock(Options.class); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + } + + @AfterEach + void restoreExitFlg() { + Main.useExit = true; + } + + @AfterEach + public void restoreStreams() { + System.setOut(originalOut); + System.setErr(originalErr); } @Test @@ -528,4 +552,22 @@ public boolean matches(String[] argument) { commandLine.handleCommandLine(); verify(mockUntagEntity).handle(); } + + @Test + void testDeleteTagCommandWithoutTagOption() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.TAG)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TAG, CommandActions.REMOVE)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newDeleteTag(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals(output, ErrorMessages.MISSING_TAG); + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java index 50b580eaf72..7fa2e453f32 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java @@ -19,12 +19,20 @@ package org.apache.gravitino.cli; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.base.Joiner; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.CreateTopic; @@ -35,17 +43,35 @@ import org.apache.gravitino.cli.commands.SetTopicProperty; import org.apache.gravitino.cli.commands.TopicDetails; import org.apache.gravitino.cli.commands.UpdateTopicComment; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class TestTopicCommands { private CommandLine mockCommandLine; private Options mockOptions; + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; @BeforeEach void setUp() { mockCommandLine = mock(CommandLine.class); mockOptions = mock(Options.class); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + } + + @AfterEach + void restoreExitFlg() { + Main.useExit = true; + } + + @AfterEach + public void restoreStreams() { + System.setOut(originalOut); + System.setErr(originalErr); } @Test @@ -271,4 +297,132 @@ void testRemoveTopicPropertyCommand() { commandLine.handleCommandLine(); verify(mockSetProperties).handle(); } + + @Test + @SuppressWarnings("DefaultCharset") + void testListTopicCommandWithoutCatalog() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.LIST)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newListTopics(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.CATALOG, CommandEntities.SCHEMA))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testListTopicCommandWithoutSchema() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.LIST)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newListTopics(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.SCHEMA))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testTopicDetailsCommandWithoutCatalog() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.DETAILS)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newTopicDetails( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MISSING_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ") + .join( + Arrays.asList( + CommandEntities.CATALOG, CommandEntities.SCHEMA, CommandEntities.TOPIC))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testTopicDetailsCommandWithoutSchema() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.DETAILS)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newTopicDetails( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.SCHEMA, CommandEntities.TOPIC))); + } + + @Test + @SuppressWarnings("DefaultCharset") + void testTopicDetailsCommandWithoutTopic() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.DETAILS)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newTopicDetails( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "schema", null, null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals( + output, + ErrorMessages.MALFORMED_NAME + + "\n" + + "Missing required argument(s): " + + Joiner.on(", ").join(Arrays.asList(CommandEntities.TOPIC))); + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java index e8a1864b9ff..e8630ce9755 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java @@ -19,12 +19,18 @@ package org.apache.gravitino.cli; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.AddRoleToUser; @@ -34,17 +40,35 @@ import org.apache.gravitino.cli.commands.RemoveRoleFromUser; import org.apache.gravitino.cli.commands.UserAudit; import org.apache.gravitino.cli.commands.UserDetails; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class TestUserCommands { private CommandLine mockCommandLine; private Options mockOptions; + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final ByteArrayOutputStream errContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + private final PrintStream originalErr = System.err; @BeforeEach void setUp() { mockCommandLine = mock(CommandLine.class); mockOptions = mock(Options.class); + System.setOut(new PrintStream(outContent)); + System.setErr(new PrintStream(errContent)); + } + + @AfterEach + void restoreExitFlg() { + Main.useExit = true; + } + + @AfterEach + public void restoreStreams() { + System.setOut(originalOut); + System.setErr(originalErr); } @Test @@ -262,4 +286,22 @@ void testAddRolesToUserCommand() { verify(mockAddFirstRole).handle(); verify(mockAddSecondRole).handle(); } + + @Test + void testDeleteUserWithoutUserOption() { + Main.useExit = false; + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.USER)).thenReturn(false); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.DELETE)); + + assertThrows(RuntimeException.class, commandLine::handleCommandLine); + verify(commandLine, never()) + .newDeleteUser(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", null); + String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); + assertEquals(output, ErrorMessages.MISSING_USER); + } }