Repository: accumulo Updated Branches: refs/heads/1.6 7ccae952c -> 7f8ef553d refs/heads/master c51d424b9 -> e7d0397cf
ACCUMULO-3341 Make deletetable remove any tables in the accumulo namespace before attempting deletion. Also fixed the test package from 'command' to 'commands'. Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/7f8ef553 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/7f8ef553 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/7f8ef553 Branch: refs/heads/1.6 Commit: 7f8ef553da765221d714bece239d3294495fb79e Parents: 7ccae95 Author: Josh Elser <els...@apache.org> Authored: Thu Nov 20 11:27:25 2014 -0500 Committer: Josh Elser <els...@apache.org> Committed: Thu Nov 20 11:27:25 2014 -0500 ---------------------------------------------------------------------- .../util/shell/commands/DeleteTableCommand.java | 23 +++ .../util/shell/commands/TableOperation.java | 16 +- .../shell/command/FormatterCommandTest.java | 184 ------------------- .../util/shell/command/HistoryCommandTest.java | 90 --------- .../shell/commands/DeleteTableCommandTest.java | 42 +++++ .../shell/commands/FormatterCommandTest.java | 184 +++++++++++++++++++ .../util/shell/commands/HistoryCommandTest.java | 90 +++++++++ 7 files changed, 354 insertions(+), 275 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/7f8ef553/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java index a5aa32a..636a45e 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java +++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommand.java @@ -16,12 +16,22 @@ */ package org.apache.accumulo.core.util.shell.commands; +import java.util.Iterator; +import java.util.Set; + +import org.apache.accumulo.core.client.impl.Namespaces; +import org.apache.accumulo.core.client.impl.Tables; +import org.apache.accumulo.core.util.Pair; import org.apache.accumulo.core.util.shell.Shell; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DeleteTableCommand extends TableOperation { + private static final Logger log = LoggerFactory.getLogger(DeleteTableCommand.class); + private Option forceOpt; @Override @@ -57,4 +67,17 @@ public class DeleteTableCommand extends TableOperation { opts.addOption(forceOpt); return opts; } + + @Override + protected void pruneTables(String pattern, Set<String> tables) { + Iterator<String> tableNames = tables.iterator(); + while (tableNames.hasNext()) { + String table = tableNames.next(); + Pair<String,String> qualifiedName = Tables.qualify(table); + if (Namespaces.ACCUMULO_NAMESPACE.equals(qualifiedName.getFirst())) { + log.trace("Removing table from deletion set: {}", table); + tableNames.remove(); + } + } + } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/7f8ef553/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java index 27946b8..06539c2 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java +++ b/core/src/main/java/org/apache/accumulo/core/util/shell/commands/TableOperation.java @@ -44,10 +44,12 @@ public abstract class TableOperation extends Command { // populate the tableSet set with the tables you want to operate on final SortedSet<String> tableSet = new TreeSet<String>(); if (cl.hasOption(optTablePattern.getOpt())) { + String tablePattern = cl.getOptionValue(optTablePattern.getOpt()); for (String table : shellState.getConnector().tableOperations().list()) - if (table.matches(cl.getOptionValue(optTablePattern.getOpt()))) { + if (table.matches(tablePattern)) { tableSet.add(table); } + pruneTables(tablePattern, tableSet); } else if (cl.hasOption(optTableName.getOpt())) { tableSet.add(cl.getOptionValue(optTableName.getOpt())); } else if (cl.hasOption(optNamespace.getOpt())) { @@ -92,6 +94,18 @@ public abstract class TableOperation extends Command { return 0; } + /** + * Allows implementation to remove certain tables from the set of tables to be operated on. + * + * @param pattern + * The pattern which tables were selected using + * @param tables + * A reference to the Set of tables to be operated on + */ + protected void pruneTables(String pattern, Set<String> tables) { + // Default no pruning + } + protected abstract void doTableOp(Shell shellState, String tableName) throws Exception; @Override http://git-wip-us.apache.org/repos/asf/accumulo/blob/7f8ef553/core/src/test/java/org/apache/accumulo/core/util/shell/command/FormatterCommandTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/shell/command/FormatterCommandTest.java b/core/src/test/java/org/apache/accumulo/core/util/shell/command/FormatterCommandTest.java deleted file mode 100644 index 091ef75..0000000 --- a/core/src/test/java/org/apache/accumulo/core/util/shell/command/FormatterCommandTest.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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.accumulo.core.util.shell.command; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.Map.Entry; - -import org.apache.accumulo.core.client.AccumuloException; -import org.apache.accumulo.core.client.AccumuloSecurityException; -import org.apache.accumulo.core.client.TableExistsException; -import org.apache.accumulo.core.client.mock.MockShell; -import org.apache.accumulo.core.data.Key; -import org.apache.accumulo.core.data.Value; -import org.apache.accumulo.core.util.format.Formatter; -import org.apache.accumulo.core.util.shell.Shell; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.junit.Assert; -import org.junit.Test; - -/** - * Uses the MockShell to test the shell output with Formatters - */ -public class FormatterCommandTest { - ByteArrayOutputStream out = null; - InputStream in = null; - - @Test - public void test() throws IOException, AccumuloException, AccumuloSecurityException, TableExistsException, ClassNotFoundException { - // Keep the Shell AUDIT log off the test output - Logger.getLogger(Shell.class).setLevel(Level.WARN); - - final String[] args = new String[] {"--fake", "-u", "root", "-p", ""}; - - final String[] commands = createCommands(); - - in = MockShell.makeCommands(commands); - out = new ByteArrayOutputStream(); - - final MockShell shell = new MockShell(in, out); - shell.config(args); - - // Can't call createtable in the shell with MockAccumulo - shell.getConnector().tableOperations().create("test"); - - try { - shell.start(); - } catch (Exception e) { - Assert.fail("Exception while running commands: " + e.getMessage()); - } - - shell.getReader().flush(); - - final String[] output = new String(out.toByteArray()).split("\n\r"); - - boolean formatterOn = false; - - final String[] expectedDefault = new String[] {"row cf:cq [] 1234abcd", "row cf1:cq1 [] 9876fedc", "row2 cf:cq [] 13579bdf", - "row2 cf1:cq [] 2468ace"}; - - final String[] expectedFormatted = new String[] {"row cf:cq [] 0x31 0x32 0x33 0x34 0x61 0x62 0x63 0x64", - "row cf1:cq1 [] 0x39 0x38 0x37 0x36 0x66 0x65 0x64 0x63", "row2 cf:cq [] 0x31 0x33 0x35 0x37 0x39 0x62 0x64 0x66", - "row2 cf1:cq [] 0x32 0x34 0x36 0x38 0x61 0x63 0x65"}; - - int outputIndex = 0; - while (outputIndex < output.length) { - final String line = output[outputIndex]; - - if (line.startsWith("root@mock-instance")) { - if (line.contains("formatter")) { - formatterOn = true; - } - - outputIndex++; - } else if (line.startsWith("row")) { - int expectedIndex = 0; - String[] comparisonData; - - // Pick the type of data we expect (formatted or default) - if (formatterOn) { - comparisonData = expectedFormatted; - } else { - comparisonData = expectedDefault; - } - - // Ensure each output is what we expected - while (expectedIndex + outputIndex < output.length && expectedIndex < expectedFormatted.length) { - Assert.assertEquals(comparisonData[expectedIndex].trim(), output[expectedIndex + outputIndex].trim()); - expectedIndex++; - } - - outputIndex += expectedIndex; - } - } - } - - private String[] createCommands() { - return new String[] {"table test", "insert row cf cq 1234abcd", "insert row cf1 cq1 9876fedc", "insert row2 cf cq 13579bdf", "insert row2 cf1 cq 2468ace", - "scan", "formatter -t test -f org.apache.accumulo.core.util.shell.command.FormatterCommandTest$HexFormatter", "scan"}; - } - - /** - * <p> - * Simple <code>Formatter</code> that will convert each character in the Value from decimal to hexadecimal. Will automatically skip over characters in the - * value which do not fall within the [0-9,a-f] range. - * </p> - * - * <p> - * Example: <code>'0'</code> will be displayed as <code>'0x30'</code> - * </p> - */ - public static class HexFormatter implements Formatter { - private Iterator<Entry<Key,Value>> iter = null; - private boolean printTs = false; - - private final static String tab = "\t"; - private final static String newline = "\n"; - - public HexFormatter() {} - - @Override - public boolean hasNext() { - return this.iter.hasNext(); - } - - @Override - public String next() { - final Entry<Key,Value> entry = iter.next(); - - String key; - - // Observe the timestamps - if (printTs) { - key = entry.getKey().toString(); - } else { - key = entry.getKey().toStringNoTime(); - } - - final Value v = entry.getValue(); - - // Approximate how much space we'll need - final StringBuilder sb = new StringBuilder(key.length() + v.getSize() * 5); - - sb.append(key).append(tab); - - for (byte b : v.get()) { - if ((b >= 48 && b <= 57) || (b >= 97 || b <= 102)) { - sb.append(String.format("0x%x ", Integer.valueOf(b))); - } - } - - sb.append(newline); - - return sb.toString(); - } - - @Override - public void remove() {} - - @Override - public void initialize(final Iterable<Entry<Key,Value>> scanner, final boolean printTimestamps) { - this.iter = scanner.iterator(); - this.printTs = printTimestamps; - } - } - -} http://git-wip-us.apache.org/repos/asf/accumulo/blob/7f8ef553/core/src/test/java/org/apache/accumulo/core/util/shell/command/HistoryCommandTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/shell/command/HistoryCommandTest.java b/core/src/test/java/org/apache/accumulo/core/util/shell/command/HistoryCommandTest.java deleted file mode 100644 index 4d379cc..0000000 --- a/core/src/test/java/org/apache/accumulo/core/util/shell/command/HistoryCommandTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.accumulo.core.util.shell.command; - -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import jline.console.ConsoleReader; -import jline.console.history.History; -import jline.console.history.MemoryHistory; - -import org.apache.accumulo.core.util.shell.Shell; -import org.apache.accumulo.core.util.shell.commands.HistoryCommand; -import org.apache.commons.cli.CommandLine; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - -public class HistoryCommandTest { - - HistoryCommand command; - CommandLine cl; - - ByteArrayOutputStream baos; - ConsoleReader reader; - Shell shell; - - @Before - public void setUp() throws Exception { - command = new HistoryCommand(); - command.getOptions(); // Make sure everything is initialized - - cl = createMock(CommandLine.class); - expect(cl.hasOption("c")).andReturn(false); - expect(cl.hasOption("np")).andReturn(true); - replay(cl); - - History history = new MemoryHistory(); - history.add("foo"); - history.add("bar"); - - baos = new ByteArrayOutputStream(); - - String input = String.format("!1%n"); // Construct a platform dependent new-line - reader = new ConsoleReader(new ByteArrayInputStream(input.getBytes()), baos); - reader.setHistory(history); - - shell = new Shell(reader, null); - } - - @Test - public void testCorrectNumbering() throws IOException { - command.execute("", cl, shell); - reader.flush(); - - assertTrue(baos.toString().contains("2: bar")); - } - - @Test - public void testEventExpansion() throws IOException { - // If we use an unsupported terminal, then history expansion doesn't work because JLine can't do magic buffer manipulations. - // This has been observed to be the case on certain versions of Eclipse. However, mvn is usually fine. - Assume.assumeTrue(reader.getTerminal().isSupported()); - - reader.readLine(); - - assertTrue(baos.toString().trim().endsWith("foo")); - } - -} http://git-wip-us.apache.org/repos/asf/accumulo/blob/7f8ef553/core/src/test/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommandTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommandTest.java b/core/src/test/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommandTest.java new file mode 100644 index 0000000..ce75173 --- /dev/null +++ b/core/src/test/java/org/apache/accumulo/core/util/shell/commands/DeleteTableCommandTest.java @@ -0,0 +1,42 @@ +/* + * 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.accumulo.core.util.shell.commands; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.apache.accumulo.core.metadata.MetadataTable; +import org.apache.accumulo.core.metadata.RootTable; +import org.junit.Assert; +import org.junit.Test; + +/** + * + */ +public class DeleteTableCommandTest { + + @Test + public void removeAccumuloNamespaceTables() { + Set<String> tables = new HashSet<String>(Arrays.asList(MetadataTable.NAME, RootTable.NAME, "a1", "a2")); + DeleteTableCommand cmd = new DeleteTableCommand(); + cmd.pruneTables("a.*", tables); + + Assert.assertEquals(new HashSet<String>(Arrays.asList("a1", "a2")), tables); + } + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/7f8ef553/core/src/test/java/org/apache/accumulo/core/util/shell/commands/FormatterCommandTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/shell/commands/FormatterCommandTest.java b/core/src/test/java/org/apache/accumulo/core/util/shell/commands/FormatterCommandTest.java new file mode 100644 index 0000000..5611e56 --- /dev/null +++ b/core/src/test/java/org/apache/accumulo/core/util/shell/commands/FormatterCommandTest.java @@ -0,0 +1,184 @@ +/* + * 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.accumulo.core.util.shell.commands; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map.Entry; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.TableExistsException; +import org.apache.accumulo.core.client.mock.MockShell; +import org.apache.accumulo.core.data.Key; +import org.apache.accumulo.core.data.Value; +import org.apache.accumulo.core.util.format.Formatter; +import org.apache.accumulo.core.util.shell.Shell; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.Assert; +import org.junit.Test; + +/** + * Uses the MockShell to test the shell output with Formatters + */ +public class FormatterCommandTest { + ByteArrayOutputStream out = null; + InputStream in = null; + + @Test + public void test() throws IOException, AccumuloException, AccumuloSecurityException, TableExistsException, ClassNotFoundException { + // Keep the Shell AUDIT log off the test output + Logger.getLogger(Shell.class).setLevel(Level.WARN); + + final String[] args = new String[] {"--fake", "-u", "root", "-p", ""}; + + final String[] commands = createCommands(); + + in = MockShell.makeCommands(commands); + out = new ByteArrayOutputStream(); + + final MockShell shell = new MockShell(in, out); + shell.config(args); + + // Can't call createtable in the shell with MockAccumulo + shell.getConnector().tableOperations().create("test"); + + try { + shell.start(); + } catch (Exception e) { + Assert.fail("Exception while running commands: " + e.getMessage()); + } + + shell.getReader().flush(); + + final String[] output = new String(out.toByteArray()).split("\n\r"); + + boolean formatterOn = false; + + final String[] expectedDefault = new String[] {"row cf:cq [] 1234abcd", "row cf1:cq1 [] 9876fedc", "row2 cf:cq [] 13579bdf", + "row2 cf1:cq [] 2468ace"}; + + final String[] expectedFormatted = new String[] {"row cf:cq [] 0x31 0x32 0x33 0x34 0x61 0x62 0x63 0x64", + "row cf1:cq1 [] 0x39 0x38 0x37 0x36 0x66 0x65 0x64 0x63", "row2 cf:cq [] 0x31 0x33 0x35 0x37 0x39 0x62 0x64 0x66", + "row2 cf1:cq [] 0x32 0x34 0x36 0x38 0x61 0x63 0x65"}; + + int outputIndex = 0; + while (outputIndex < output.length) { + final String line = output[outputIndex]; + + if (line.startsWith("root@mock-instance")) { + if (line.contains("formatter")) { + formatterOn = true; + } + + outputIndex++; + } else if (line.startsWith("row")) { + int expectedIndex = 0; + String[] comparisonData; + + // Pick the type of data we expect (formatted or default) + if (formatterOn) { + comparisonData = expectedFormatted; + } else { + comparisonData = expectedDefault; + } + + // Ensure each output is what we expected + while (expectedIndex + outputIndex < output.length && expectedIndex < expectedFormatted.length) { + Assert.assertEquals(comparisonData[expectedIndex].trim(), output[expectedIndex + outputIndex].trim()); + expectedIndex++; + } + + outputIndex += expectedIndex; + } + } + } + + private String[] createCommands() { + return new String[] {"table test", "insert row cf cq 1234abcd", "insert row cf1 cq1 9876fedc", "insert row2 cf cq 13579bdf", "insert row2 cf1 cq 2468ace", + "scan", "formatter -t test -f org.apache.accumulo.core.util.shell.command.FormatterCommandTest$HexFormatter", "scan"}; + } + + /** + * <p> + * Simple <code>Formatter</code> that will convert each character in the Value from decimal to hexadecimal. Will automatically skip over characters in the + * value which do not fall within the [0-9,a-f] range. + * </p> + * + * <p> + * Example: <code>'0'</code> will be displayed as <code>'0x30'</code> + * </p> + */ + public static class HexFormatter implements Formatter { + private Iterator<Entry<Key,Value>> iter = null; + private boolean printTs = false; + + private final static String tab = "\t"; + private final static String newline = "\n"; + + public HexFormatter() {} + + @Override + public boolean hasNext() { + return this.iter.hasNext(); + } + + @Override + public String next() { + final Entry<Key,Value> entry = iter.next(); + + String key; + + // Observe the timestamps + if (printTs) { + key = entry.getKey().toString(); + } else { + key = entry.getKey().toStringNoTime(); + } + + final Value v = entry.getValue(); + + // Approximate how much space we'll need + final StringBuilder sb = new StringBuilder(key.length() + v.getSize() * 5); + + sb.append(key).append(tab); + + for (byte b : v.get()) { + if ((b >= 48 && b <= 57) || (b >= 97 || b <= 102)) { + sb.append(String.format("0x%x ", Integer.valueOf(b))); + } + } + + sb.append(newline); + + return sb.toString(); + } + + @Override + public void remove() {} + + @Override + public void initialize(final Iterable<Entry<Key,Value>> scanner, final boolean printTimestamps) { + this.iter = scanner.iterator(); + this.printTs = printTimestamps; + } + } + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/7f8ef553/core/src/test/java/org/apache/accumulo/core/util/shell/commands/HistoryCommandTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/shell/commands/HistoryCommandTest.java b/core/src/test/java/org/apache/accumulo/core/util/shell/commands/HistoryCommandTest.java new file mode 100644 index 0000000..878e2df --- /dev/null +++ b/core/src/test/java/org/apache/accumulo/core/util/shell/commands/HistoryCommandTest.java @@ -0,0 +1,90 @@ +/* + * 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.accumulo.core.util.shell.commands; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import jline.console.ConsoleReader; +import jline.console.history.History; +import jline.console.history.MemoryHistory; + +import org.apache.accumulo.core.util.shell.Shell; +import org.apache.accumulo.core.util.shell.commands.HistoryCommand; +import org.apache.commons.cli.CommandLine; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +public class HistoryCommandTest { + + HistoryCommand command; + CommandLine cl; + + ByteArrayOutputStream baos; + ConsoleReader reader; + Shell shell; + + @Before + public void setUp() throws Exception { + command = new HistoryCommand(); + command.getOptions(); // Make sure everything is initialized + + cl = createMock(CommandLine.class); + expect(cl.hasOption("c")).andReturn(false); + expect(cl.hasOption("np")).andReturn(true); + replay(cl); + + History history = new MemoryHistory(); + history.add("foo"); + history.add("bar"); + + baos = new ByteArrayOutputStream(); + + String input = String.format("!1%n"); // Construct a platform dependent new-line + reader = new ConsoleReader(new ByteArrayInputStream(input.getBytes()), baos); + reader.setHistory(history); + + shell = new Shell(reader, null); + } + + @Test + public void testCorrectNumbering() throws IOException { + command.execute("", cl, shell); + reader.flush(); + + assertTrue(baos.toString().contains("2: bar")); + } + + @Test + public void testEventExpansion() throws IOException { + // If we use an unsupported terminal, then history expansion doesn't work because JLine can't do magic buffer manipulations. + // This has been observed to be the case on certain versions of Eclipse. However, mvn is usually fine. + Assume.assumeTrue(reader.getTerminal().isSupported()); + + reader.readLine(); + + assertTrue(baos.toString().trim().endsWith("foo")); + } + +}