You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by md...@apache.org on 2014/03/25 19:23:05 UTC
[1/3] git commit: ACCUMULO-2503 add formatter tests
Repository: accumulo
Updated Branches:
refs/heads/1.6.0-SNAPSHOT d77fd6fd2 -> c56ef2eec
refs/heads/master 4eb5237e2 -> a749fad02
ACCUMULO-2503 add formatter tests
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/c56ef2ee
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/c56ef2ee
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/c56ef2ee
Branch: refs/heads/1.6.0-SNAPSHOT
Commit: c56ef2eec1f62e940cb9f137bfd0b2821aa478e7
Parents: d77fd6f
Author: Mike Drob <md...@cloudera.com>
Authored: Wed Mar 19 19:12:47 2014 -0400
Committer: Mike Drob <md...@cloudera.com>
Committed: Tue Mar 25 14:00:08 2014 -0400
----------------------------------------------------------------------
.../core/util/format/AggregatingFormatter.java | 52 ++++++
.../core/util/format/BinaryFormatter.java | 89 ++-------
.../core/util/format/DefaultFormatter.java | 42 +++--
.../core/util/format/DeleterFormatter.java | 3 +
.../core/util/format/FormatterFactory.java | 4 +
.../accumulo/core/util/format/HexFormatter.java | 8 +-
.../ShardedTableDistributionFormatter.java | 16 +-
.../util/format/StatisticsDisplayFormatter.java | 16 +-
.../util/format/DateStringFormatterTest.java | 61 +++++++
.../core/util/format/DefaultFormatterTest.java | 62 +++++++
.../core/util/format/DeleterFormatterTest.java | 179 +++++++++++++++++++
.../core/util/format/FormatterFactoryTest.java | 45 +++++
.../core/util/format/HexFormatterTest.java | 88 +++++++++
.../ShardedTableDistributionFormatterTest.java | 66 +++++++
.../format/StatisticsDisplayFormatterTest.java | 64 +++++++
core/src/test/resources/log4j.properties | 1 +
16 files changed, 681 insertions(+), 115 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java
new file mode 100644
index 0000000..e0791eb
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.format;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * Formatter that will aggregate entries for various display purposes.
+ */
+public abstract class AggregatingFormatter extends DefaultFormatter {
+ @Override
+ public String next() {
+ Iterator<Entry<Key,Value>> si = super.getScannerIterator();
+ checkState(true);
+ while (si.hasNext())
+ aggregateStats(si.next());
+ return getStats();
+ }
+
+ /**
+ * Generate statistics from each {@link Entry}, called for each entry to be iterated over.
+ *
+ * @param next
+ * the next entry to aggregate
+ */
+ protected abstract void aggregateStats(Entry<Key,Value> next);
+
+ /**
+ * Finalize the aggregation and return the result. Called once at the end.
+ *
+ * @return the aggregation results, suitable for printing to the console
+ */
+ protected abstract String getStats();
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
index 5021d66..b31df18 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
@@ -16,7 +16,6 @@
*/
package org.apache.accumulo.core.util.format;
-import java.util.Iterator;
import java.util.Map.Entry;
import org.apache.accumulo.core.data.Key;
@@ -24,66 +23,43 @@ import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.security.ColumnVisibility;
import org.apache.hadoop.io.Text;
-public class BinaryFormatter implements Formatter {
- private Iterator<Entry<Key,Value>> si;
- private boolean doTimestamps;
+public class BinaryFormatter extends DefaultFormatter {
private static int showLength;
- @Override
- public void initialize(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps) {
- checkState(si, false);
- si = scanner.iterator();
- doTimestamps = printTimestamps;
- }
-
- public boolean hasNext() {
- checkState(si, true);
- return si.hasNext();
- }
-
public String next() {
- checkState(si, true);
- return formatEntry(si.next(), doTimestamps);
- }
-
- public void remove() {
- checkState(si, true);
- si.remove();
- }
-
- static void checkState(Iterator<Entry<Key,Value>> si, boolean expectInitialized) {
- if (expectInitialized && si == null)
- throw new IllegalStateException("Not initialized");
- if (!expectInitialized && si != null)
- throw new IllegalStateException("Already initialized");
+ checkState(true);
+ return formatEntry(getScannerIterator().next(), isDoTimestamps());
}
// this should be replaced with something like Record.toString();
+ // it would be great if we were able to combine code with DefaultFormatter.formatEntry, but that currently does not respect the showLength option.
public static String formatEntry(Entry<Key,Value> entry, boolean showTimestamps) {
StringBuilder sb = new StringBuilder();
+ Key key = entry.getKey();
+
// append row
- appendText(sb, entry.getKey().getRow()).append(" ");
-
+ appendText(sb, key.getRow()).append(" ");
+
// append column family
- appendText(sb, entry.getKey().getColumnFamily()).append(":");
-
+ appendText(sb, key.getColumnFamily()).append(":");
+
// append column qualifier
- appendText(sb, entry.getKey().getColumnQualifier()).append(" ");
-
+ appendText(sb, key.getColumnQualifier()).append(" ");
+
// append visibility expression
- sb.append(new ColumnVisibility(entry.getKey().getColumnVisibility()));
+ sb.append(new ColumnVisibility(key.getColumnVisibility()));
// append timestamp
if (showTimestamps)
sb.append(" ").append(entry.getKey().getTimestamp());
// append value
- if (entry.getValue() != null && entry.getValue().getSize() > 0) {
+ Value value = entry.getValue();
+ if (value != null && value.getSize() > 0) {
sb.append("\t");
- appendValue(sb, entry.getValue());
+ appendValue(sb, value);
}
-
return sb.toString();
}
@@ -92,41 +68,12 @@ public class BinaryFormatter implements Formatter {
}
static StringBuilder appendValue(StringBuilder sb, Value value) {
-
return appendBytes(sb, value.get(), 0, value.get().length);
}
static StringBuilder appendBytes(StringBuilder sb, byte ba[], int offset, int len) {
- if (len > showLength) {
- for (int i = 0; i < showLength; i++) {
- int c = 0xff & ba[offset + i];
- if (c == '\\')
- sb.append("\\\\");
- else if (c >= 32 && c <= 126)
- sb.append((char) c);
- else
- sb.append("\\x").append(String.format("%02X", c));
- }
- return sb;
- }
-
- else {
- for (int i = 0; i < len; i++) {
-
- int c = 0xff & ba[offset + i];
- if (c == '\\')
- sb.append("\\\\");
- else if (c >= 32 && c <= 126)
- sb.append((char) c);
- else
- sb.append("\\x").append(String.format("%02X", c));
- }
- return sb;
- }
- }
-
- public Iterator<Entry<Key,Value>> getScannerIterator() {
- return si;
+ int length = Math.min(len, showLength);
+ return DefaultFormatter.appendBytes(sb, ba, offset, length);
}
public static void getlength(int length) {
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
index ee4a220..acd4ba1 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
@@ -56,13 +56,13 @@ public class DefaultFormatter implements Formatter {
@Override
public void initialize(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps) {
- checkState(si, false);
+ checkState(false);
si = scanner.iterator();
doTimestamps = printTimestamps;
}
public boolean hasNext() {
- checkState(si, true);
+ checkState(true);
return si.hasNext();
}
@@ -77,22 +77,22 @@ public class DefaultFormatter implements Formatter {
}
protected String next(DateFormat timestampFormat) {
- checkState(si, true);
+ checkState(true);
return formatEntry(si.next(), timestampFormat);
}
public void remove() {
- checkState(si, true);
+ checkState(true);
si.remove();
}
- static void checkState(Iterator<Entry<Key,Value>> si, boolean expectInitialized) {
+ protected void checkState(boolean expectInitialized) {
if (expectInitialized && si == null)
throw new IllegalStateException("Not initialized");
if (!expectInitialized && si != null)
throw new IllegalStateException("Already initialized");
}
-
+
// this should be replaced with something like Record.toString();
public static String formatEntry(Entry<Key,Value> entry, boolean showTimestamps) {
DateFormat timestampFormat = null;
@@ -106,6 +106,7 @@ public class DefaultFormatter implements Formatter {
/* so a new date object doesn't get created for every record in the scan result */
private static ThreadLocal<Date> tmpDate = new ThreadLocal<Date>() {
+ @Override
protected Date initialValue() {
return new Date();
}
@@ -114,32 +115,37 @@ public class DefaultFormatter implements Formatter {
public static String formatEntry(Entry<Key,Value> entry, DateFormat timestampFormat) {
StringBuilder sb = new StringBuilder();
+ Key key = entry.getKey();
+
// append row
- appendText(sb, entry.getKey().getRow()).append(" ");
-
+ appendText(sb, key.getRow()).append(" ");
+
// append column family
- appendText(sb, entry.getKey().getColumnFamily()).append(":");
-
+ appendText(sb, key.getColumnFamily()).append(":");
+
// append column qualifier
- appendText(sb, entry.getKey().getColumnQualifier()).append(" ");
-
+ appendText(sb, key.getColumnQualifier()).append(" ");
+
// append visibility expression
- sb.append(new ColumnVisibility(entry.getKey().getColumnVisibility()));
+ sb.append(new ColumnVisibility(key.getColumnVisibility()));
// append timestamp
if (timestampFormat != null) {
tmpDate.get().setTime(entry.getKey().getTimestamp());
sb.append(" ").append(timestampFormat.format(tmpDate.get()));
}
+
+ Value value = entry.getValue();
+
// append value
- if (entry.getValue() != null && entry.getValue().getSize() > 0) {
+ if (value != null && value.getSize() > 0) {
sb.append("\t");
- appendValue(sb, entry.getValue());
+ appendValue(sb, value);
}
return sb.toString();
}
-
+
static StringBuilder appendText(StringBuilder sb, Text t) {
return appendBytes(sb, t.getBytes(), 0, t.getLength());
}
@@ -164,4 +170,8 @@ public class DefaultFormatter implements Formatter {
public Iterator<Entry<Key,Value>> getScannerIterator() {
return si;
}
+
+ protected boolean isDoTimestamps() {
+ return doTimestamps;
+ }
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
index 8547f12..7ac0510 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
@@ -63,6 +63,9 @@ public class DeleterFormatter extends DefaultFormatter {
return true;
}
+ /**
+ * @return null, because the iteration will provide prompts and handle deletes internally.
+ */
@Override
public String next() {
Entry<Key,Value> next = getScannerIterator().next();
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
index 5451843..27299ee 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
@@ -40,4 +40,8 @@ public class FormatterFactory {
public static Formatter getDefaultFormatter(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps) {
return getFormatter(DefaultFormatter.class, scanner, printTimestamps);
}
+
+ private FormatterFactory() {
+ // prevent instantiation
+ }
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
index 1def712..b636278 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
@@ -116,21 +116,21 @@ public class HexFormatter implements Formatter, ScanInterpreter {
@Override
public Text interpretBeginRow(Text row) {
- return new Text(toBinary(row.toString()));
+ return interpretRow(row);
}
@Override
public Text interpretEndRow(Text row) {
- return new Text(toBinary(row.toString()));
+ return interpretRow(row);
}
@Override
public Text interpretColumnFamily(Text cf) {
- return new Text(toBinary(cf.toString()));
+ return interpretRow(cf);
}
@Override
public Text interpretColumnQualifier(Text cq) {
- return new Text(toBinary(cq.toString()));
+ return interpretRow(cq);
}
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
index 577167a..f81209f 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
@@ -18,7 +18,6 @@ package org.apache.accumulo.core.util.format;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -33,20 +32,12 @@ import org.apache.accumulo.core.data.Value;
*
* scan -b tableId -c ~tab:loc
*/
-public class ShardedTableDistributionFormatter extends DefaultFormatter {
+public class ShardedTableDistributionFormatter extends AggregatingFormatter {
private Map<String,HashSet<String>> countsByDay = new HashMap<String,HashSet<String>>();
@Override
- public String next() {
- Iterator<Entry<Key,Value>> si = super.getScannerIterator();
- checkState(si, true);
- while (si.hasNext())
- aggregateStats(si.next());
- return getStats();
- }
-
- private void aggregateStats(Entry<Key,Value> entry) {
+ protected void aggregateStats(Entry<Key,Value> entry) {
if (entry.getKey().getColumnFamily().toString().equals("~tab") && entry.getKey().getColumnQualifier().toString().equals("loc")) {
// The row for the sharded table should look like: <tableId>;yyyyMMhh_N
String row = entry.getKey().getRow().toString();
@@ -65,7 +56,8 @@ public class ShardedTableDistributionFormatter extends DefaultFormatter {
}
}
- private String getStats() {
+ @Override
+ protected String getStats() {
StringBuilder buf = new StringBuilder();
buf.append("DAY \t\tSERVERS\n");
buf.append("------\t\t-------\n");
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
index dd9de6c..98d4d28 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
@@ -17,7 +17,6 @@
package org.apache.accumulo.core.util.format;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -28,22 +27,14 @@ import org.apache.accumulo.core.data.Value;
* Does not show contents from scan, only displays statistics. Beware that this work is being done client side and this was developed as a utility for
* debugging. If used on large result sets it will likely fail.
*/
-public class StatisticsDisplayFormatter extends DefaultFormatter {
+public class StatisticsDisplayFormatter extends AggregatingFormatter {
private Map<String,Long> classifications = new HashMap<String,Long>();
private Map<String,Long> columnFamilies = new HashMap<String,Long>();
private Map<String,Long> columnQualifiers = new HashMap<String,Long>();
private long total = 0;
@Override
- public String next() {
- Iterator<Entry<Key,Value>> si = super.getScannerIterator();
- checkState(si, true);
- while (si.hasNext())
- aggregateStats(si.next());
- return getStats();
- }
-
- private void aggregateStats(Entry<Key,Value> entry) {
+ protected void aggregateStats(Entry<Key,Value> entry) {
String key;
Long count;
@@ -62,7 +53,8 @@ public class StatisticsDisplayFormatter extends DefaultFormatter {
++total;
}
- private String getStats() {
+ @Override
+ protected String getStats() {
StringBuilder buf = new StringBuilder();
buf.append("CLASSIFICATIONS:\n");
buf.append("----------------\n");
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java
new file mode 100644
index 0000000..69b2e11
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DateStringFormatterTest {
+ DateStringFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ formatter = new DateStringFormatter();
+ data = new TreeMap<Key,Value>();
+ data.put(new Key("", "", "", 0), new Value());
+ }
+
+ @Test
+ public void testTimestamps() {
+ formatter.initialize(data.entrySet(), true);
+
+ assertTrue(formatter.hasNext());
+ assertTrue(formatter.next().endsWith("1969/12/31 19:00:00.000"));
+ }
+
+ @Test
+ public void testNoTimestamps() {
+ data.put(new Key("", "", "", 1), new Value());
+
+ assertEquals(2, data.size());
+
+ formatter.initialize(data.entrySet(), false);
+
+ assertEquals(formatter.next(), formatter.next());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java
new file mode 100644
index 0000000..dd4d93f
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.Text;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DefaultFormatterTest {
+
+ DefaultFormatter df;
+ Iterable<Entry<Key,Value>> empty = Collections.<Key,Value> emptyMap().entrySet();
+
+ @Before
+ public void setUp() {
+ df = new DefaultFormatter();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testDoubleInitialize() {
+ df.initialize(empty, true);
+ df.initialize(empty, true);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNextBeforeInitialize() {
+ df.hasNext();
+ }
+
+ @Test
+ public void testAppendBytes() {
+ StringBuilder sb = new StringBuilder();
+ byte[] data = new byte[] { 0, '\\', 'x', -0x01 };
+
+ DefaultFormatter.appendValue(sb, new Value());
+ assertEquals("", sb.toString());
+
+ DefaultFormatter.appendText(sb, new Text(data));
+ assertEquals("\\x00\\\\x\\xFF", sb.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java
new file mode 100644
index 0000000..4daf676
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.format;
+
+import static org.apache.accumulo.core.Constants.UTF8;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+import jline.console.ConsoleReader;
+
+import org.apache.accumulo.core.client.BatchWriter;
+import org.apache.accumulo.core.client.MutationsRejectedException;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DeleterFormatterTest {
+ DeleterFormatter formatter;
+ Map<Key,Value> data;
+ BatchWriter writer;
+ BatchWriter exceptionWriter;
+ Shell shellState;
+
+ ByteArrayOutputStream baos;
+ ConsoleReader reader;
+
+ SettableInputStream input;
+
+ class SettableInputStream extends InputStream {
+ ByteArrayInputStream bais;
+
+ @Override
+ public int read() throws IOException {
+ return bais.read();
+ }
+
+ public void set(String in) {
+ bais = new ByteArrayInputStream(in.getBytes(UTF8));
+ }
+
+ public void set(byte... in) {
+ bais = new ByteArrayInputStream(in);
+ }
+ };
+
+ @Before
+ public void setUp() throws IOException, MutationsRejectedException {
+ input = new SettableInputStream();
+ baos = new ByteArrayOutputStream();
+
+ MutationsRejectedException mre = createMock(MutationsRejectedException.class);
+
+ writer = createNiceMock(BatchWriter.class);
+ exceptionWriter = createNiceMock(BatchWriter.class);
+ exceptionWriter.close();
+ expectLastCall().andThrow(mre);
+ exceptionWriter.addMutation(anyObject(Mutation.class));
+ expectLastCall().andThrow(mre);
+
+ shellState = createNiceMock(Shell.class);
+
+ reader = new ConsoleReader(input, baos);
+ expect(shellState.getReader()).andReturn(reader).anyTimes();
+
+ replay(writer, exceptionWriter, shellState);
+
+ data = new TreeMap<Key,Value>();
+ data.put(new Key("r", "cf", "cq"), new Value("value".getBytes(UTF8)));
+ }
+
+ @Test
+ public void testEmpty() {
+ formatter = new DeleterFormatter(writer, Collections.<Key,Value> emptyMap().entrySet(), true, shellState, true);
+ assertFalse(formatter.hasNext());
+ }
+
+ @Test
+ public void testSingle() throws IOException {
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, true);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+
+ verify("[DELETED]", " r ", "cf", "cq", "value");
+ }
+
+ @Test
+ public void testNo() throws IOException {
+ input.set("no\n");
+ data.put(new Key("z"), new Value("v2".getBytes(UTF8)));
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+
+ verify("[SKIPPED]", " r ", "cf", "cq", "value");
+
+ assertTrue(formatter.hasNext());
+ }
+
+ @Test
+ public void testNoConfirmation() throws IOException {
+ input.set((byte) -1);
+ data.put(new Key("z"), new Value("v2".getBytes(UTF8)));
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+
+ verify("[SKIPPED]", " r ", "cf", "cq", "value");
+
+ assertFalse(formatter.hasNext());
+ }
+
+ @Test
+ public void testYes() throws IOException {
+ input.set("y\nyes\n");
+ data.put(new Key("z"), new Value("v2".getBytes(UTF8)));
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+ verify("[DELETED]", " r ", "cf", "cq", "value");
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+ verify("[DELETED]", " z ", "v2");
+ }
+
+ @Test
+ public void testMutationException() {
+ formatter = new DeleterFormatter(exceptionWriter, data.entrySet(), true, shellState, true);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+ assertFalse(formatter.hasNext());
+ }
+
+ private void verify(String... chunks) throws IOException {
+ reader.flush();
+
+ String output = baos.toString();
+ for (String chunk : chunks) {
+ assertTrue(output.contains(chunk));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java
new file mode 100644
index 0000000..d379dee
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FormatterFactoryTest {
+
+ Iterable<Entry<Key,Value>> scanner;
+
+ @Before
+ public void setUp() {
+ scanner = Collections.<Key,Value> emptyMap().entrySet();
+ }
+
+ @Test
+ public void testGetDefaultFormatter() {
+ Formatter defaultFormatter = FormatterFactory.getDefaultFormatter(scanner, true);
+ Formatter bogusFormatter = FormatterFactory.getFormatter(Formatter.class, scanner, true);
+ assertEquals(defaultFormatter.getClass(), bogusFormatter.getClass());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java
new file mode 100644
index 0000000..7f4f3e5
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.Text;
+import org.junit.Before;
+import org.junit.Test;
+
+public class HexFormatterTest {
+ HexFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ data = new TreeMap<Key,Value>();
+ formatter = new HexFormatter();
+ }
+
+ @Test
+ public void testInitialize() {
+ data.put(new Key(), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ assertTrue(formatter.hasNext());
+ assertEquals(" " + " " + " [" + "] ", formatter.next());
+ }
+
+ @Test
+ public void testInterpretRow() {
+ assertEquals(new Text(), formatter.interpretRow(new Text()));
+ assertEquals(new Text("\0"), formatter.interpretRow(new Text("0")));
+ }
+
+
+ @Test
+ public void testRoundTripRows() {
+ Text bytes = new Text(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
+ data.put(new Key(bytes), new Value());
+
+ formatter.initialize(data.entrySet(), false);
+
+ String row = formatter.next().split(" ")[0];
+ assertEquals("0001-0203-0405-0607-0809-0a0b-0c0d-0e0f", row);
+ assertEquals(bytes, formatter.interpretRow(new Text(row)));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInterpretBadRow0() {
+ formatter.interpretRow(new Text("!"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInterpretBadRow1() {
+ formatter.interpretRow(new Text("z"));
+ }
+
+ @Test
+ public void testTimestamps() {
+ long now = System.currentTimeMillis();
+ data.put(new Key("", "", "", now), new Value());
+ formatter.initialize(data.entrySet(), true);
+ String entry = formatter.next().split("\\s+")[2];
+ assertEquals(now, Long.valueOf(entry).longValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java
new file mode 100644
index 0000000..1707dda
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ShardedTableDistributionFormatterTest {
+ ShardedTableDistributionFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ data = new TreeMap<Key,Value>();
+ formatter = new ShardedTableDistributionFormatter();
+ }
+
+ @Test
+ public void testInitialize() {
+ data.put(new Key(), new Value());
+ data.put(new Key("r", "~tab"), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ assertTrue(formatter.hasNext());
+ formatter.next();
+ assertFalse(formatter.hasNext());
+ }
+
+ @Test
+ public void testAggregate() {
+ data.put(new Key("t", "~tab", "loc"), new Value("srv1".getBytes(Constants.UTF8)));
+ data.put(new Key("t;19700101", "~tab", "loc", 0), new Value("srv1".getBytes(Constants.UTF8)));
+ data.put(new Key("t;19700101", "~tab", "loc", 1), new Value("srv2".getBytes(Constants.UTF8)));
+
+ formatter.initialize(data.entrySet(), false);
+
+ String[] result = formatter.next().split("\n");
+ assertTrue(result[2].endsWith("\t1"));
+ assertTrue(result[3].endsWith("\t2"));
+ assertFalse(formatter.hasNext());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java
new file mode 100644
index 0000000..93c948c
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class StatisticsDisplayFormatterTest {
+ StatisticsDisplayFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ data = new TreeMap<Key,Value>();
+ formatter = new StatisticsDisplayFormatter();
+ }
+
+ @Test
+ public void testInitialize() {
+ data.put(new Key(), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ assertTrue(formatter.hasNext());
+ }
+
+ @Test
+ public void testAggregate() {
+ data.put(new Key("", "", "", 1), new Value());
+ data.put(new Key("", "", "", 2), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ String[] output = formatter.next().split("\n");
+ assertTrue(output[2].endsWith(": 1"));
+ assertTrue(output[5].endsWith(": 1"));
+ assertTrue(output[8].endsWith(": 1"));
+ assertEquals("2 entries matched.", output[9]);
+
+ assertFalse(formatter.hasNext());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/core/src/test/resources/log4j.properties b/core/src/test/resources/log4j.properties
index dfc93bf..9f968f8 100644
--- a/core/src/test/resources/log4j.properties
+++ b/core/src/test/resources/log4j.properties
@@ -25,3 +25,4 @@ log4j.logger.org.apache.commons.vfs2.impl.DefaultFileSystemManager=WARN
log4j.logger.org.apache.hadoop.mapred=ERROR
log4j.logger.org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter=ERROR
log4j.logger.org.apache.hadoop.util.ProcessTree=ERROR
+log4j.logger.org.apache.accumulo.core.util.format=FATAL
[3/3] git commit: Merge branch '1.6.0-SNAPSHOT'
Posted by md...@apache.org.
Merge branch '1.6.0-SNAPSHOT'
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/a749fad0
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/a749fad0
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/a749fad0
Branch: refs/heads/master
Commit: a749fad02d0290361a311fae63600746005d5f26
Parents: 4eb5237 c56ef2e
Author: Mike Drob <md...@cloudera.com>
Authored: Tue Mar 25 14:14:03 2014 -0400
Committer: Mike Drob <md...@cloudera.com>
Committed: Tue Mar 25 14:14:03 2014 -0400
----------------------------------------------------------------------
.../core/util/format/AggregatingFormatter.java | 52 ++++++
.../core/util/format/BinaryFormatter.java | 89 ++-------
.../core/util/format/DefaultFormatter.java | 42 +++--
.../core/util/format/DeleterFormatter.java | 3 +
.../core/util/format/FormatterFactory.java | 4 +
.../accumulo/core/util/format/HexFormatter.java | 8 +-
.../ShardedTableDistributionFormatter.java | 16 +-
.../util/format/StatisticsDisplayFormatter.java | 16 +-
.../util/format/DateStringFormatterTest.java | 61 +++++++
.../core/util/format/DefaultFormatterTest.java | 62 +++++++
.../core/util/format/DeleterFormatterTest.java | 179 +++++++++++++++++++
.../core/util/format/FormatterFactoryTest.java | 45 +++++
.../core/util/format/HexFormatterTest.java | 88 +++++++++
.../ShardedTableDistributionFormatterTest.java | 66 +++++++
.../format/StatisticsDisplayFormatterTest.java | 64 +++++++
core/src/test/resources/log4j.properties | 1 +
16 files changed, 681 insertions(+), 115 deletions(-)
----------------------------------------------------------------------
[2/3] git commit: ACCUMULO-2503 add formatter tests
Posted by md...@apache.org.
ACCUMULO-2503 add formatter tests
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/c56ef2ee
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/c56ef2ee
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/c56ef2ee
Branch: refs/heads/master
Commit: c56ef2eec1f62e940cb9f137bfd0b2821aa478e7
Parents: d77fd6f
Author: Mike Drob <md...@cloudera.com>
Authored: Wed Mar 19 19:12:47 2014 -0400
Committer: Mike Drob <md...@cloudera.com>
Committed: Tue Mar 25 14:00:08 2014 -0400
----------------------------------------------------------------------
.../core/util/format/AggregatingFormatter.java | 52 ++++++
.../core/util/format/BinaryFormatter.java | 89 ++-------
.../core/util/format/DefaultFormatter.java | 42 +++--
.../core/util/format/DeleterFormatter.java | 3 +
.../core/util/format/FormatterFactory.java | 4 +
.../accumulo/core/util/format/HexFormatter.java | 8 +-
.../ShardedTableDistributionFormatter.java | 16 +-
.../util/format/StatisticsDisplayFormatter.java | 16 +-
.../util/format/DateStringFormatterTest.java | 61 +++++++
.../core/util/format/DefaultFormatterTest.java | 62 +++++++
.../core/util/format/DeleterFormatterTest.java | 179 +++++++++++++++++++
.../core/util/format/FormatterFactoryTest.java | 45 +++++
.../core/util/format/HexFormatterTest.java | 88 +++++++++
.../ShardedTableDistributionFormatterTest.java | 66 +++++++
.../format/StatisticsDisplayFormatterTest.java | 64 +++++++
core/src/test/resources/log4j.properties | 1 +
16 files changed, 681 insertions(+), 115 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java
new file mode 100644
index 0000000..e0791eb
--- /dev/null
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/AggregatingFormatter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.format;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+
+/**
+ * Formatter that will aggregate entries for various display purposes.
+ */
+public abstract class AggregatingFormatter extends DefaultFormatter {
+ @Override
+ public String next() {
+ Iterator<Entry<Key,Value>> si = super.getScannerIterator();
+ checkState(true);
+ while (si.hasNext())
+ aggregateStats(si.next());
+ return getStats();
+ }
+
+ /**
+ * Generate statistics from each {@link Entry}, called for each entry to be iterated over.
+ *
+ * @param next
+ * the next entry to aggregate
+ */
+ protected abstract void aggregateStats(Entry<Key,Value> next);
+
+ /**
+ * Finalize the aggregation and return the result. Called once at the end.
+ *
+ * @return the aggregation results, suitable for printing to the console
+ */
+ protected abstract String getStats();
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
index 5021d66..b31df18 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java
@@ -16,7 +16,6 @@
*/
package org.apache.accumulo.core.util.format;
-import java.util.Iterator;
import java.util.Map.Entry;
import org.apache.accumulo.core.data.Key;
@@ -24,66 +23,43 @@ import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.security.ColumnVisibility;
import org.apache.hadoop.io.Text;
-public class BinaryFormatter implements Formatter {
- private Iterator<Entry<Key,Value>> si;
- private boolean doTimestamps;
+public class BinaryFormatter extends DefaultFormatter {
private static int showLength;
- @Override
- public void initialize(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps) {
- checkState(si, false);
- si = scanner.iterator();
- doTimestamps = printTimestamps;
- }
-
- public boolean hasNext() {
- checkState(si, true);
- return si.hasNext();
- }
-
public String next() {
- checkState(si, true);
- return formatEntry(si.next(), doTimestamps);
- }
-
- public void remove() {
- checkState(si, true);
- si.remove();
- }
-
- static void checkState(Iterator<Entry<Key,Value>> si, boolean expectInitialized) {
- if (expectInitialized && si == null)
- throw new IllegalStateException("Not initialized");
- if (!expectInitialized && si != null)
- throw new IllegalStateException("Already initialized");
+ checkState(true);
+ return formatEntry(getScannerIterator().next(), isDoTimestamps());
}
// this should be replaced with something like Record.toString();
+ // it would be great if we were able to combine code with DefaultFormatter.formatEntry, but that currently does not respect the showLength option.
public static String formatEntry(Entry<Key,Value> entry, boolean showTimestamps) {
StringBuilder sb = new StringBuilder();
+ Key key = entry.getKey();
+
// append row
- appendText(sb, entry.getKey().getRow()).append(" ");
-
+ appendText(sb, key.getRow()).append(" ");
+
// append column family
- appendText(sb, entry.getKey().getColumnFamily()).append(":");
-
+ appendText(sb, key.getColumnFamily()).append(":");
+
// append column qualifier
- appendText(sb, entry.getKey().getColumnQualifier()).append(" ");
-
+ appendText(sb, key.getColumnQualifier()).append(" ");
+
// append visibility expression
- sb.append(new ColumnVisibility(entry.getKey().getColumnVisibility()));
+ sb.append(new ColumnVisibility(key.getColumnVisibility()));
// append timestamp
if (showTimestamps)
sb.append(" ").append(entry.getKey().getTimestamp());
// append value
- if (entry.getValue() != null && entry.getValue().getSize() > 0) {
+ Value value = entry.getValue();
+ if (value != null && value.getSize() > 0) {
sb.append("\t");
- appendValue(sb, entry.getValue());
+ appendValue(sb, value);
}
-
return sb.toString();
}
@@ -92,41 +68,12 @@ public class BinaryFormatter implements Formatter {
}
static StringBuilder appendValue(StringBuilder sb, Value value) {
-
return appendBytes(sb, value.get(), 0, value.get().length);
}
static StringBuilder appendBytes(StringBuilder sb, byte ba[], int offset, int len) {
- if (len > showLength) {
- for (int i = 0; i < showLength; i++) {
- int c = 0xff & ba[offset + i];
- if (c == '\\')
- sb.append("\\\\");
- else if (c >= 32 && c <= 126)
- sb.append((char) c);
- else
- sb.append("\\x").append(String.format("%02X", c));
- }
- return sb;
- }
-
- else {
- for (int i = 0; i < len; i++) {
-
- int c = 0xff & ba[offset + i];
- if (c == '\\')
- sb.append("\\\\");
- else if (c >= 32 && c <= 126)
- sb.append((char) c);
- else
- sb.append("\\x").append(String.format("%02X", c));
- }
- return sb;
- }
- }
-
- public Iterator<Entry<Key,Value>> getScannerIterator() {
- return si;
+ int length = Math.min(len, showLength);
+ return DefaultFormatter.appendBytes(sb, ba, offset, length);
}
public static void getlength(int length) {
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
index ee4a220..acd4ba1 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java
@@ -56,13 +56,13 @@ public class DefaultFormatter implements Formatter {
@Override
public void initialize(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps) {
- checkState(si, false);
+ checkState(false);
si = scanner.iterator();
doTimestamps = printTimestamps;
}
public boolean hasNext() {
- checkState(si, true);
+ checkState(true);
return si.hasNext();
}
@@ -77,22 +77,22 @@ public class DefaultFormatter implements Formatter {
}
protected String next(DateFormat timestampFormat) {
- checkState(si, true);
+ checkState(true);
return formatEntry(si.next(), timestampFormat);
}
public void remove() {
- checkState(si, true);
+ checkState(true);
si.remove();
}
- static void checkState(Iterator<Entry<Key,Value>> si, boolean expectInitialized) {
+ protected void checkState(boolean expectInitialized) {
if (expectInitialized && si == null)
throw new IllegalStateException("Not initialized");
if (!expectInitialized && si != null)
throw new IllegalStateException("Already initialized");
}
-
+
// this should be replaced with something like Record.toString();
public static String formatEntry(Entry<Key,Value> entry, boolean showTimestamps) {
DateFormat timestampFormat = null;
@@ -106,6 +106,7 @@ public class DefaultFormatter implements Formatter {
/* so a new date object doesn't get created for every record in the scan result */
private static ThreadLocal<Date> tmpDate = new ThreadLocal<Date>() {
+ @Override
protected Date initialValue() {
return new Date();
}
@@ -114,32 +115,37 @@ public class DefaultFormatter implements Formatter {
public static String formatEntry(Entry<Key,Value> entry, DateFormat timestampFormat) {
StringBuilder sb = new StringBuilder();
+ Key key = entry.getKey();
+
// append row
- appendText(sb, entry.getKey().getRow()).append(" ");
-
+ appendText(sb, key.getRow()).append(" ");
+
// append column family
- appendText(sb, entry.getKey().getColumnFamily()).append(":");
-
+ appendText(sb, key.getColumnFamily()).append(":");
+
// append column qualifier
- appendText(sb, entry.getKey().getColumnQualifier()).append(" ");
-
+ appendText(sb, key.getColumnQualifier()).append(" ");
+
// append visibility expression
- sb.append(new ColumnVisibility(entry.getKey().getColumnVisibility()));
+ sb.append(new ColumnVisibility(key.getColumnVisibility()));
// append timestamp
if (timestampFormat != null) {
tmpDate.get().setTime(entry.getKey().getTimestamp());
sb.append(" ").append(timestampFormat.format(tmpDate.get()));
}
+
+ Value value = entry.getValue();
+
// append value
- if (entry.getValue() != null && entry.getValue().getSize() > 0) {
+ if (value != null && value.getSize() > 0) {
sb.append("\t");
- appendValue(sb, entry.getValue());
+ appendValue(sb, value);
}
return sb.toString();
}
-
+
static StringBuilder appendText(StringBuilder sb, Text t) {
return appendBytes(sb, t.getBytes(), 0, t.getLength());
}
@@ -164,4 +170,8 @@ public class DefaultFormatter implements Formatter {
public Iterator<Entry<Key,Value>> getScannerIterator() {
return si;
}
+
+ protected boolean isDoTimestamps() {
+ return doTimestamps;
+ }
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
index 8547f12..7ac0510 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/DeleterFormatter.java
@@ -63,6 +63,9 @@ public class DeleterFormatter extends DefaultFormatter {
return true;
}
+ /**
+ * @return null, because the iteration will provide prompts and handle deletes internally.
+ */
@Override
public String next() {
Entry<Key,Value> next = getScannerIterator().next();
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
index 5451843..27299ee 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java
@@ -40,4 +40,8 @@ public class FormatterFactory {
public static Formatter getDefaultFormatter(Iterable<Entry<Key,Value>> scanner, boolean printTimestamps) {
return getFormatter(DefaultFormatter.class, scanner, printTimestamps);
}
+
+ private FormatterFactory() {
+ // prevent instantiation
+ }
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
index 1def712..b636278 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java
@@ -116,21 +116,21 @@ public class HexFormatter implements Formatter, ScanInterpreter {
@Override
public Text interpretBeginRow(Text row) {
- return new Text(toBinary(row.toString()));
+ return interpretRow(row);
}
@Override
public Text interpretEndRow(Text row) {
- return new Text(toBinary(row.toString()));
+ return interpretRow(row);
}
@Override
public Text interpretColumnFamily(Text cf) {
- return new Text(toBinary(cf.toString()));
+ return interpretRow(cf);
}
@Override
public Text interpretColumnQualifier(Text cq) {
- return new Text(toBinary(cq.toString()));
+ return interpretRow(cq);
}
}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
index 577167a..f81209f 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatter.java
@@ -18,7 +18,6 @@ package org.apache.accumulo.core.util.format;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -33,20 +32,12 @@ import org.apache.accumulo.core.data.Value;
*
* scan -b tableId -c ~tab:loc
*/
-public class ShardedTableDistributionFormatter extends DefaultFormatter {
+public class ShardedTableDistributionFormatter extends AggregatingFormatter {
private Map<String,HashSet<String>> countsByDay = new HashMap<String,HashSet<String>>();
@Override
- public String next() {
- Iterator<Entry<Key,Value>> si = super.getScannerIterator();
- checkState(si, true);
- while (si.hasNext())
- aggregateStats(si.next());
- return getStats();
- }
-
- private void aggregateStats(Entry<Key,Value> entry) {
+ protected void aggregateStats(Entry<Key,Value> entry) {
if (entry.getKey().getColumnFamily().toString().equals("~tab") && entry.getKey().getColumnQualifier().toString().equals("loc")) {
// The row for the sharded table should look like: <tableId>;yyyyMMhh_N
String row = entry.getKey().getRow().toString();
@@ -65,7 +56,8 @@ public class ShardedTableDistributionFormatter extends DefaultFormatter {
}
}
- private String getStats() {
+ @Override
+ protected String getStats() {
StringBuilder buf = new StringBuilder();
buf.append("DAY \t\tSERVERS\n");
buf.append("------\t\t-------\n");
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
index dd9de6c..98d4d28 100644
--- a/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatter.java
@@ -17,7 +17,6 @@
package org.apache.accumulo.core.util.format;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -28,22 +27,14 @@ import org.apache.accumulo.core.data.Value;
* Does not show contents from scan, only displays statistics. Beware that this work is being done client side and this was developed as a utility for
* debugging. If used on large result sets it will likely fail.
*/
-public class StatisticsDisplayFormatter extends DefaultFormatter {
+public class StatisticsDisplayFormatter extends AggregatingFormatter {
private Map<String,Long> classifications = new HashMap<String,Long>();
private Map<String,Long> columnFamilies = new HashMap<String,Long>();
private Map<String,Long> columnQualifiers = new HashMap<String,Long>();
private long total = 0;
@Override
- public String next() {
- Iterator<Entry<Key,Value>> si = super.getScannerIterator();
- checkState(si, true);
- while (si.hasNext())
- aggregateStats(si.next());
- return getStats();
- }
-
- private void aggregateStats(Entry<Key,Value> entry) {
+ protected void aggregateStats(Entry<Key,Value> entry) {
String key;
Long count;
@@ -62,7 +53,8 @@ public class StatisticsDisplayFormatter extends DefaultFormatter {
++total;
}
- private String getStats() {
+ @Override
+ protected String getStats() {
StringBuilder buf = new StringBuilder();
buf.append("CLASSIFICATIONS:\n");
buf.append("----------------\n");
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java
new file mode 100644
index 0000000..69b2e11
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DateStringFormatterTest {
+ DateStringFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ formatter = new DateStringFormatter();
+ data = new TreeMap<Key,Value>();
+ data.put(new Key("", "", "", 0), new Value());
+ }
+
+ @Test
+ public void testTimestamps() {
+ formatter.initialize(data.entrySet(), true);
+
+ assertTrue(formatter.hasNext());
+ assertTrue(formatter.next().endsWith("1969/12/31 19:00:00.000"));
+ }
+
+ @Test
+ public void testNoTimestamps() {
+ data.put(new Key("", "", "", 1), new Value());
+
+ assertEquals(2, data.size());
+
+ formatter.initialize(data.entrySet(), false);
+
+ assertEquals(formatter.next(), formatter.next());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java
new file mode 100644
index 0000000..dd4d93f
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.Text;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DefaultFormatterTest {
+
+ DefaultFormatter df;
+ Iterable<Entry<Key,Value>> empty = Collections.<Key,Value> emptyMap().entrySet();
+
+ @Before
+ public void setUp() {
+ df = new DefaultFormatter();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testDoubleInitialize() {
+ df.initialize(empty, true);
+ df.initialize(empty, true);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNextBeforeInitialize() {
+ df.hasNext();
+ }
+
+ @Test
+ public void testAppendBytes() {
+ StringBuilder sb = new StringBuilder();
+ byte[] data = new byte[] { 0, '\\', 'x', -0x01 };
+
+ DefaultFormatter.appendValue(sb, new Value());
+ assertEquals("", sb.toString());
+
+ DefaultFormatter.appendText(sb, new Text(data));
+ assertEquals("\\x00\\\\x\\xFF", sb.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java
new file mode 100644
index 0000000..4daf676
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/DeleterFormatterTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.format;
+
+import static org.apache.accumulo.core.Constants.UTF8;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+import jline.console.ConsoleReader;
+
+import org.apache.accumulo.core.client.BatchWriter;
+import org.apache.accumulo.core.client.MutationsRejectedException;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Mutation;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.core.util.shell.Shell;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DeleterFormatterTest {
+ DeleterFormatter formatter;
+ Map<Key,Value> data;
+ BatchWriter writer;
+ BatchWriter exceptionWriter;
+ Shell shellState;
+
+ ByteArrayOutputStream baos;
+ ConsoleReader reader;
+
+ SettableInputStream input;
+
+ class SettableInputStream extends InputStream {
+ ByteArrayInputStream bais;
+
+ @Override
+ public int read() throws IOException {
+ return bais.read();
+ }
+
+ public void set(String in) {
+ bais = new ByteArrayInputStream(in.getBytes(UTF8));
+ }
+
+ public void set(byte... in) {
+ bais = new ByteArrayInputStream(in);
+ }
+ };
+
+ @Before
+ public void setUp() throws IOException, MutationsRejectedException {
+ input = new SettableInputStream();
+ baos = new ByteArrayOutputStream();
+
+ MutationsRejectedException mre = createMock(MutationsRejectedException.class);
+
+ writer = createNiceMock(BatchWriter.class);
+ exceptionWriter = createNiceMock(BatchWriter.class);
+ exceptionWriter.close();
+ expectLastCall().andThrow(mre);
+ exceptionWriter.addMutation(anyObject(Mutation.class));
+ expectLastCall().andThrow(mre);
+
+ shellState = createNiceMock(Shell.class);
+
+ reader = new ConsoleReader(input, baos);
+ expect(shellState.getReader()).andReturn(reader).anyTimes();
+
+ replay(writer, exceptionWriter, shellState);
+
+ data = new TreeMap<Key,Value>();
+ data.put(new Key("r", "cf", "cq"), new Value("value".getBytes(UTF8)));
+ }
+
+ @Test
+ public void testEmpty() {
+ formatter = new DeleterFormatter(writer, Collections.<Key,Value> emptyMap().entrySet(), true, shellState, true);
+ assertFalse(formatter.hasNext());
+ }
+
+ @Test
+ public void testSingle() throws IOException {
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, true);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+
+ verify("[DELETED]", " r ", "cf", "cq", "value");
+ }
+
+ @Test
+ public void testNo() throws IOException {
+ input.set("no\n");
+ data.put(new Key("z"), new Value("v2".getBytes(UTF8)));
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+
+ verify("[SKIPPED]", " r ", "cf", "cq", "value");
+
+ assertTrue(formatter.hasNext());
+ }
+
+ @Test
+ public void testNoConfirmation() throws IOException {
+ input.set((byte) -1);
+ data.put(new Key("z"), new Value("v2".getBytes(UTF8)));
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+
+ verify("[SKIPPED]", " r ", "cf", "cq", "value");
+
+ assertFalse(formatter.hasNext());
+ }
+
+ @Test
+ public void testYes() throws IOException {
+ input.set("y\nyes\n");
+ data.put(new Key("z"), new Value("v2".getBytes(UTF8)));
+ formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+ verify("[DELETED]", " r ", "cf", "cq", "value");
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+ verify("[DELETED]", " z ", "v2");
+ }
+
+ @Test
+ public void testMutationException() {
+ formatter = new DeleterFormatter(exceptionWriter, data.entrySet(), true, shellState, true);
+
+ assertTrue(formatter.hasNext());
+ assertNull(formatter.next());
+ assertFalse(formatter.hasNext());
+ }
+
+ private void verify(String... chunks) throws IOException {
+ reader.flush();
+
+ String output = baos.toString();
+ for (String chunk : chunks) {
+ assertTrue(output.contains(chunk));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java
new file mode 100644
index 0000000..d379dee
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class FormatterFactoryTest {
+
+ Iterable<Entry<Key,Value>> scanner;
+
+ @Before
+ public void setUp() {
+ scanner = Collections.<Key,Value> emptyMap().entrySet();
+ }
+
+ @Test
+ public void testGetDefaultFormatter() {
+ Formatter defaultFormatter = FormatterFactory.getDefaultFormatter(scanner, true);
+ Formatter bogusFormatter = FormatterFactory.getFormatter(Formatter.class, scanner, true);
+ assertEquals(defaultFormatter.getClass(), bogusFormatter.getClass());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java
new file mode 100644
index 0000000..7f4f3e5
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.apache.hadoop.io.Text;
+import org.junit.Before;
+import org.junit.Test;
+
+public class HexFormatterTest {
+ HexFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ data = new TreeMap<Key,Value>();
+ formatter = new HexFormatter();
+ }
+
+ @Test
+ public void testInitialize() {
+ data.put(new Key(), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ assertTrue(formatter.hasNext());
+ assertEquals(" " + " " + " [" + "] ", formatter.next());
+ }
+
+ @Test
+ public void testInterpretRow() {
+ assertEquals(new Text(), formatter.interpretRow(new Text()));
+ assertEquals(new Text("\0"), formatter.interpretRow(new Text("0")));
+ }
+
+
+ @Test
+ public void testRoundTripRows() {
+ Text bytes = new Text(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
+ data.put(new Key(bytes), new Value());
+
+ formatter.initialize(data.entrySet(), false);
+
+ String row = formatter.next().split(" ")[0];
+ assertEquals("0001-0203-0405-0607-0809-0a0b-0c0d-0e0f", row);
+ assertEquals(bytes, formatter.interpretRow(new Text(row)));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInterpretBadRow0() {
+ formatter.interpretRow(new Text("!"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInterpretBadRow1() {
+ formatter.interpretRow(new Text("z"));
+ }
+
+ @Test
+ public void testTimestamps() {
+ long now = System.currentTimeMillis();
+ data.put(new Key("", "", "", now), new Value());
+ formatter.initialize(data.entrySet(), true);
+ String entry = formatter.next().split("\\s+")[2];
+ assertEquals(now, Long.valueOf(entry).longValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java
new file mode 100644
index 0000000..1707dda
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ShardedTableDistributionFormatterTest {
+ ShardedTableDistributionFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ data = new TreeMap<Key,Value>();
+ formatter = new ShardedTableDistributionFormatter();
+ }
+
+ @Test
+ public void testInitialize() {
+ data.put(new Key(), new Value());
+ data.put(new Key("r", "~tab"), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ assertTrue(formatter.hasNext());
+ formatter.next();
+ assertFalse(formatter.hasNext());
+ }
+
+ @Test
+ public void testAggregate() {
+ data.put(new Key("t", "~tab", "loc"), new Value("srv1".getBytes(Constants.UTF8)));
+ data.put(new Key("t;19700101", "~tab", "loc", 0), new Value("srv1".getBytes(Constants.UTF8)));
+ data.put(new Key("t;19700101", "~tab", "loc", 1), new Value("srv2".getBytes(Constants.UTF8)));
+
+ formatter.initialize(data.entrySet(), false);
+
+ String[] result = formatter.next().split("\n");
+ assertTrue(result[2].endsWith("\t1"));
+ assertTrue(result[3].endsWith("\t2"));
+ assertFalse(formatter.hasNext());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java
new file mode 100644
index 0000000..93c948c
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.format;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Value;
+import org.junit.Before;
+import org.junit.Test;
+
+public class StatisticsDisplayFormatterTest {
+ StatisticsDisplayFormatter formatter;
+
+ Map<Key,Value> data;
+
+ @Before
+ public void setUp() {
+ data = new TreeMap<Key,Value>();
+ formatter = new StatisticsDisplayFormatter();
+ }
+
+ @Test
+ public void testInitialize() {
+ data.put(new Key(), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ assertTrue(formatter.hasNext());
+ }
+
+ @Test
+ public void testAggregate() {
+ data.put(new Key("", "", "", 1), new Value());
+ data.put(new Key("", "", "", 2), new Value());
+ formatter.initialize(data.entrySet(), false);
+
+ String[] output = formatter.next().split("\n");
+ assertTrue(output[2].endsWith(": 1"));
+ assertTrue(output[5].endsWith(": 1"));
+ assertTrue(output[8].endsWith(": 1"));
+ assertEquals("2 entries matched.", output[9]);
+
+ assertFalse(formatter.hasNext());
+ }
+}
http://git-wip-us.apache.org/repos/asf/accumulo/blob/c56ef2ee/core/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/core/src/test/resources/log4j.properties b/core/src/test/resources/log4j.properties
index dfc93bf..9f968f8 100644
--- a/core/src/test/resources/log4j.properties
+++ b/core/src/test/resources/log4j.properties
@@ -25,3 +25,4 @@ log4j.logger.org.apache.commons.vfs2.impl.DefaultFileSystemManager=WARN
log4j.logger.org.apache.hadoop.mapred=ERROR
log4j.logger.org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter=ERROR
log4j.logger.org.apache.hadoop.util.ProcessTree=ERROR
+log4j.logger.org.apache.accumulo.core.util.format=FATAL