You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by jd...@apache.org on 2016/07/25 17:15:15 UTC
[10/36] incubator-kudu git commit: [java-client] repackage to
org.apache.kudu (Part 1)
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
new file mode 100644
index 0000000..4915a18
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java
@@ -0,0 +1,628 @@
+// 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.kududb.client;
+
+import com.google.common.base.Preconditions;
+import org.junit.Assert;
+import org.junit.Test;
+import org.kududb.ColumnSchema;
+import org.kududb.Type;
+
+import static org.kududb.client.KuduPredicate.ComparisonOp.EQUAL;
+import static org.kududb.client.KuduPredicate.ComparisonOp.GREATER;
+import static org.kududb.client.KuduPredicate.ComparisonOp.GREATER_EQUAL;
+import static org.kududb.client.KuduPredicate.ComparisonOp.LESS;
+import static org.kududb.client.KuduPredicate.ComparisonOp.LESS_EQUAL;
+import static org.kududb.client.KuduPredicate.PredicateType.RANGE;
+
+public class TestKuduPredicate {
+
+ private static final ColumnSchema boolCol =
+ new ColumnSchema.ColumnSchemaBuilder("bool", Type.BOOL).build();
+
+ private static final ColumnSchema byteCol =
+ new ColumnSchema.ColumnSchemaBuilder("byte", Type.INT8).build();
+
+ private static final ColumnSchema shortCol =
+ new ColumnSchema.ColumnSchemaBuilder("short", Type.INT16).build();
+
+ private static final ColumnSchema intCol =
+ new ColumnSchema.ColumnSchemaBuilder("int", Type.INT32).build();
+
+ private static final ColumnSchema longCol =
+ new ColumnSchema.ColumnSchemaBuilder("long", Type.INT64).build();
+
+ private static final ColumnSchema floatCol =
+ new ColumnSchema.ColumnSchemaBuilder("float", Type.FLOAT).build();
+
+ private static final ColumnSchema doubleCol =
+ new ColumnSchema.ColumnSchemaBuilder("double", Type.DOUBLE).build();
+
+ private static final ColumnSchema stringCol =
+ new ColumnSchema.ColumnSchemaBuilder("string", Type.STRING).build();
+
+ private static final ColumnSchema binaryCol =
+ new ColumnSchema.ColumnSchemaBuilder("binary", Type.BINARY).build();
+
+ private static KuduPredicate intRange(int lower, int upper) {
+ Preconditions.checkArgument(lower < upper);
+ return new KuduPredicate(RANGE, intCol, Bytes.fromInt(lower), Bytes.fromInt(upper));
+ }
+
+ private void testMerge(KuduPredicate a,
+ KuduPredicate b,
+ KuduPredicate expected) {
+
+ Assert.assertEquals(expected, a.merge(b));
+ Assert.assertEquals(expected, b.merge(a));
+ }
+
+ /**
+ * Tests merges on all types of integer predicates.
+ */
+ @Test
+ public void testMergeInt() {
+
+ // Equality + Equality
+
+ // |
+ // |
+ // =
+ // |
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0));
+ // |
+ // |
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 1),
+ KuduPredicate.none(intCol));
+
+ // Range + Equality
+
+ // [-------->
+ // |
+ // =
+ // |
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 10),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 10));
+
+ // [-------->
+ // |
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 10),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0),
+ KuduPredicate.none(intCol));
+
+ // <--------)
+ // |
+ // =
+ // |
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, LESS, 10),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 5),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 5));
+
+ // <--------)
+ // |
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, LESS, 0),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 10),
+ KuduPredicate.none(intCol));
+
+ // Unbounded Range + Unbounded Range
+
+ // [--------> AND
+ // [-------->
+ // =
+ // [-------->
+
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0));
+
+ // [--------> AND
+ // [----->
+ // =
+ // [----->
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 5),
+ KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 5));
+
+ // <--------) AND
+ // <--------)
+ // =
+ // <--------)
+
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, LESS, 0),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 0),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 0));
+
+ // <--------) AND
+ // <----)
+ // =
+ // <----)
+
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, LESS, 0),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, -10),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, -10));
+
+ // [--------> AND
+ // <-------)
+ // =
+ // [----)
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 10),
+ intRange(0, 10));
+
+ // [-----> AND
+ // <----)
+ // =
+ // |
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 5),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 6),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 5));
+
+ // [-----> AND
+ // <---)
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 5),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 5),
+ KuduPredicate.none(intCol));
+
+ // [-----> AND
+ // <---)
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 5),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 3),
+ KuduPredicate.none(intCol));
+
+ // Range + Range
+
+ // [--------) AND
+ // [--------)
+ // =
+ // [--------)
+
+ testMerge(intRange(0, 10),
+ intRange(0, 10),
+ intRange(0, 10));
+
+ // [--------) AND
+ // [----)
+ // =
+ // [----)
+ testMerge(intRange(0, 10),
+ intRange(0, 5),
+ intRange(0, 5));
+
+ // [--------) AND
+ // [----)
+ // =
+ // [----)
+ testMerge(intRange(0, 10),
+ intRange(3, 8),
+ intRange(3, 8));
+
+ // [-----) AND
+ // [------)
+ // =
+ // [---)
+ testMerge(intRange(0, 8),
+ intRange(3, 10),
+ intRange(3, 8));
+ // [--) AND
+ // [---)
+ // =
+ // None
+ testMerge(intRange(0, 5),
+ intRange(5, 10),
+ KuduPredicate.none(intCol));
+
+ // [--) AND
+ // [---)
+ // =
+ // None
+ testMerge(intRange(0, 3),
+ intRange(5, 10),
+ KuduPredicate.none(intCol));
+
+ // Lower Bound + Range
+
+ // [------------>
+ // [---)
+ // =
+ // [---)
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0),
+ intRange(5, 10),
+ intRange(5, 10));
+
+ // [------------>
+ // [--------)
+ // =
+ // [--------)
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 5),
+ intRange(5, 10),
+ intRange(5, 10));
+
+ // [------------>
+ // [--------)
+ // =
+ // [---)
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 5),
+ intRange(0, 10),
+ intRange(5, 10));
+
+ // [------->
+ // [-----)
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 10),
+ intRange(0, 5),
+ KuduPredicate.none(intCol));
+
+ // Upper Bound + Range
+
+ // <------------)
+ // [---)
+ // =
+ // [---)
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, LESS, 10),
+ intRange(3, 8),
+ intRange(3, 8));
+
+ // <------------)
+ // [--------)
+ // =
+ // [--------)
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, LESS, 10),
+ intRange(5, 10),
+ intRange(5, 10));
+
+
+ // <------------)
+ // [--------)
+ // =
+ // [----)
+ testMerge(KuduPredicate.newComparisonPredicate(intCol, LESS, 5),
+ intRange(0, 10),
+ intRange(0, 5));
+
+ // Range + Equality
+
+ // [---) AND
+ // |
+ // =
+ // None
+ testMerge(intRange(3, 5),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 1),
+ KuduPredicate.none(intCol));
+
+ // [---) AND
+ // |
+ // =
+ // |
+ testMerge(intRange(0, 5),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0));
+
+ // [---) AND
+ // |
+ // =
+ // |
+ testMerge(intRange(0, 5),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 3),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 3));
+
+ // [---) AND
+ // |
+ // =
+ // None
+ testMerge(intRange(0, 5),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 5),
+ KuduPredicate.none(intCol));
+
+ // [---) AND
+ // |
+ // =
+ // None
+ testMerge(intRange(0, 5),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 7),
+ KuduPredicate.none(intCol));
+
+ // None
+
+ // None AND
+ // [---->
+ // =
+ // None
+ testMerge(KuduPredicate.none(intCol),
+ KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 0),
+ KuduPredicate.none(intCol));
+ // None AND
+ // <----)
+ // =
+ // None
+ testMerge(KuduPredicate.none(intCol),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 0),
+ KuduPredicate.none(intCol));
+
+ // None AND
+ // [----)
+ // =
+ // None
+ testMerge(KuduPredicate.none(intCol),
+ intRange(3, 7),
+ KuduPredicate.none(intCol));
+
+ // None AND
+ // |
+ // =
+ // None
+ testMerge(KuduPredicate.none(intCol),
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, 5),
+ KuduPredicate.none(intCol));
+
+ // None AND
+ // None
+ // =
+ // None
+ testMerge(KuduPredicate.none(intCol),
+ KuduPredicate.none(intCol),
+ KuduPredicate.none(intCol));
+ }
+
+ /**
+ * Tests tricky merges on a var length type.
+ */
+ @Test
+ public void testMergeString() {
+
+ // [----->
+ // <-----)
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(stringCol, GREATER_EQUAL, "b\0"),
+ KuduPredicate.newComparisonPredicate(stringCol, LESS, "b"),
+ KuduPredicate.none(stringCol));
+
+ // [----->
+ // <-----)
+ // =
+ // None
+ testMerge(KuduPredicate.newComparisonPredicate(stringCol, GREATER_EQUAL, "b"),
+ KuduPredicate.newComparisonPredicate(stringCol, LESS, "b"),
+ KuduPredicate.none(stringCol));
+
+ // [----->
+ // <----)
+ // =
+ // |
+ testMerge(KuduPredicate.newComparisonPredicate(stringCol, GREATER_EQUAL, "b"),
+ KuduPredicate.newComparisonPredicate(stringCol, LESS, "b\0"),
+ KuduPredicate.newComparisonPredicate(stringCol, EQUAL, "b"));
+
+ // [----->
+ // <-----)
+ // =
+ // [--)
+ testMerge(KuduPredicate.newComparisonPredicate(stringCol, GREATER_EQUAL, "a"),
+ KuduPredicate.newComparisonPredicate(stringCol, LESS, "a\0\0"),
+ new KuduPredicate(RANGE, stringCol,
+ Bytes.fromString("a"), Bytes.fromString("a\0\0")));
+ }
+
+ @Test
+ public void testBoolean() {
+
+ // b >= false
+ Assert.assertEquals(KuduPredicate.newIsNotNullPredicate(boolCol),
+ KuduPredicate.newComparisonPredicate(boolCol, GREATER_EQUAL, false));
+ // b > false
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, true),
+ KuduPredicate.newComparisonPredicate(boolCol, GREATER, false));
+ // b = false
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, false),
+ KuduPredicate.newComparisonPredicate(boolCol, EQUAL, false));
+ // b < false
+ Assert.assertEquals(KuduPredicate.none(boolCol),
+ KuduPredicate.newComparisonPredicate(boolCol, LESS, false));
+ // b <= false
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, false),
+ KuduPredicate.newComparisonPredicate(boolCol, LESS_EQUAL, false));
+
+ // b >= true
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, true),
+ KuduPredicate.newComparisonPredicate(boolCol, GREATER_EQUAL, true));
+ // b > true
+ Assert.assertEquals(KuduPredicate.none(boolCol),
+ KuduPredicate.newComparisonPredicate(boolCol, GREATER, true));
+ // b = true
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, true),
+ KuduPredicate.newComparisonPredicate(boolCol, EQUAL, true));
+ // b < true
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, false),
+ KuduPredicate.newComparisonPredicate(boolCol, LESS, true));
+ // b <= true
+ Assert.assertEquals(KuduPredicate.newIsNotNullPredicate(boolCol),
+ KuduPredicate.newComparisonPredicate(boolCol, LESS_EQUAL, true));
+ }
+
+ /**
+ * Tests basic predicate merges across all types.
+ */
+ @Test
+ public void testAllTypesMerge() {
+
+ testMerge(KuduPredicate.newComparisonPredicate(boolCol, GREATER_EQUAL, false),
+ KuduPredicate.newComparisonPredicate(boolCol, LESS, true),
+ new KuduPredicate(KuduPredicate.PredicateType.EQUALITY,
+ boolCol,
+ Bytes.fromBoolean(false),
+ null));
+
+ testMerge(KuduPredicate.newComparisonPredicate(boolCol, GREATER_EQUAL, false),
+ KuduPredicate.newComparisonPredicate(boolCol, LESS_EQUAL, true),
+ KuduPredicate.newIsNotNullPredicate(boolCol));
+
+ testMerge(KuduPredicate.newComparisonPredicate(byteCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(byteCol, LESS, 10),
+ new KuduPredicate(RANGE,
+ byteCol,
+ new byte[] { (byte) 0 },
+ new byte[] { (byte) 10 }));
+
+ testMerge(KuduPredicate.newComparisonPredicate(shortCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(shortCol, LESS, 10),
+ new KuduPredicate(RANGE,
+ shortCol,
+ Bytes.fromShort((short) 0),
+ Bytes.fromShort((short) 10)));
+
+ testMerge(KuduPredicate.newComparisonPredicate(longCol, GREATER_EQUAL, 0),
+ KuduPredicate.newComparisonPredicate(longCol, LESS, 10),
+ new KuduPredicate(RANGE,
+ longCol,
+ Bytes.fromLong(0),
+ Bytes.fromLong(10)));
+
+ testMerge(KuduPredicate.newComparisonPredicate(floatCol, GREATER_EQUAL, 123.45f),
+ KuduPredicate.newComparisonPredicate(floatCol, LESS, 678.90f),
+ new KuduPredicate(RANGE,
+ floatCol,
+ Bytes.fromFloat(123.45f),
+ Bytes.fromFloat(678.90f)));
+
+ testMerge(KuduPredicate.newComparisonPredicate(doubleCol, GREATER_EQUAL, 123.45),
+ KuduPredicate.newComparisonPredicate(doubleCol, LESS, 678.90),
+ new KuduPredicate(RANGE,
+ doubleCol,
+ Bytes.fromDouble(123.45),
+ Bytes.fromDouble(678.90)));
+
+ testMerge(KuduPredicate.newComparisonPredicate(binaryCol, GREATER_EQUAL,
+ new byte[] { 0, 1, 2, 3, 4, 5, 6 }),
+ KuduPredicate.newComparisonPredicate(binaryCol, LESS, new byte[] { 10 }),
+ new KuduPredicate(RANGE,
+ binaryCol,
+ new byte[] { 0, 1, 2, 3, 4, 5, 6 },
+ new byte[] { 10 }));
+ }
+
+ @Test
+ public void testLessEqual() {
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(byteCol, LESS_EQUAL, 10),
+ KuduPredicate.newComparisonPredicate(byteCol, LESS, 11));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(shortCol, LESS_EQUAL, 10),
+ KuduPredicate.newComparisonPredicate(shortCol, LESS, 11));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(intCol, LESS_EQUAL, 10),
+ KuduPredicate.newComparisonPredicate(intCol, LESS, 11));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(longCol, LESS_EQUAL, 10),
+ KuduPredicate.newComparisonPredicate(longCol, LESS, 11));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(floatCol, LESS_EQUAL, 12.345f),
+ KuduPredicate.newComparisonPredicate(floatCol, LESS, Math.nextAfter(12.345f, Float.POSITIVE_INFINITY)));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, LESS_EQUAL, 12.345),
+ KuduPredicate.newComparisonPredicate(doubleCol, LESS, Math.nextAfter(12.345, Float.POSITIVE_INFINITY)));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(stringCol, LESS_EQUAL, "a"),
+ KuduPredicate.newComparisonPredicate(stringCol, LESS, "a\0"));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(binaryCol, LESS_EQUAL, new byte[] { (byte) 10 }),
+ KuduPredicate.newComparisonPredicate(binaryCol, LESS, new byte[] { (byte) 10, (byte) 0 }));
+
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(byteCol, LESS_EQUAL, Byte.MAX_VALUE),
+ KuduPredicate.newIsNotNullPredicate(byteCol));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(shortCol, LESS_EQUAL, Short.MAX_VALUE),
+ KuduPredicate.newIsNotNullPredicate(shortCol));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(intCol, LESS_EQUAL, Integer.MAX_VALUE),
+ KuduPredicate.newIsNotNullPredicate(intCol));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(longCol, LESS_EQUAL, Long.MAX_VALUE),
+ KuduPredicate.newIsNotNullPredicate(longCol));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(floatCol, LESS_EQUAL, Float.MAX_VALUE),
+ KuduPredicate.newComparisonPredicate(floatCol, LESS, Float.POSITIVE_INFINITY));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(floatCol, LESS_EQUAL, Float.POSITIVE_INFINITY),
+ KuduPredicate.newIsNotNullPredicate(floatCol));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, LESS_EQUAL, Double.MAX_VALUE),
+ KuduPredicate.newComparisonPredicate(doubleCol, LESS, Double.POSITIVE_INFINITY));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, LESS_EQUAL, Double.POSITIVE_INFINITY),
+ KuduPredicate.newIsNotNullPredicate(doubleCol));
+ }
+
+ @Test
+ public void testGreater() {
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(byteCol, GREATER_EQUAL, 11),
+ KuduPredicate.newComparisonPredicate(byteCol, GREATER, 10));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(shortCol, GREATER_EQUAL, 11),
+ KuduPredicate.newComparisonPredicate(shortCol, GREATER, 10));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 11),
+ KuduPredicate.newComparisonPredicate(intCol, GREATER, 10));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(longCol, GREATER_EQUAL, 11),
+ KuduPredicate.newComparisonPredicate(longCol, GREATER, 10));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(floatCol, GREATER_EQUAL, Math.nextAfter(12.345f, Float.MAX_VALUE)),
+ KuduPredicate.newComparisonPredicate(floatCol, GREATER, 12.345f));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, GREATER_EQUAL, Math.nextAfter(12.345, Float.MAX_VALUE)),
+ KuduPredicate.newComparisonPredicate(doubleCol, GREATER, 12.345));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(stringCol, GREATER_EQUAL, "a\0"),
+ KuduPredicate.newComparisonPredicate(stringCol, GREATER, "a"));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(binaryCol, GREATER_EQUAL, new byte[] { (byte) 10, (byte) 0 }),
+ KuduPredicate.newComparisonPredicate(binaryCol, GREATER, new byte[] { (byte) 10 }));
+
+ Assert.assertEquals(KuduPredicate.none(byteCol),
+ KuduPredicate.newComparisonPredicate(byteCol, GREATER, Byte.MAX_VALUE));
+ Assert.assertEquals(KuduPredicate.none(shortCol),
+ KuduPredicate.newComparisonPredicate(shortCol, GREATER, Short.MAX_VALUE));
+ Assert.assertEquals(KuduPredicate.none(intCol),
+ KuduPredicate.newComparisonPredicate(intCol, GREATER, Integer.MAX_VALUE));
+ Assert.assertEquals(KuduPredicate.none(longCol),
+ KuduPredicate.newComparisonPredicate(longCol, GREATER, Long.MAX_VALUE));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(floatCol, GREATER_EQUAL, Float.POSITIVE_INFINITY),
+ KuduPredicate.newComparisonPredicate(floatCol, GREATER, Float.MAX_VALUE));
+ Assert.assertEquals(KuduPredicate.none(floatCol),
+ KuduPredicate.newComparisonPredicate(floatCol, GREATER, Float.POSITIVE_INFINITY));
+ Assert.assertEquals(KuduPredicate.newComparisonPredicate(doubleCol, GREATER_EQUAL, Double.POSITIVE_INFINITY),
+ KuduPredicate.newComparisonPredicate(doubleCol, GREATER, Double.MAX_VALUE));
+ Assert.assertEquals(KuduPredicate.none(doubleCol),
+ KuduPredicate.newComparisonPredicate(doubleCol, GREATER, Double.POSITIVE_INFINITY));
+ }
+
+ @Test
+ public void testToString() {
+ Assert.assertEquals("`bool` = true",
+ KuduPredicate.newComparisonPredicate(boolCol, EQUAL, true).toString());
+ Assert.assertEquals("`byte` = 11",
+ KuduPredicate.newComparisonPredicate(byteCol, EQUAL, 11).toString());
+ Assert.assertEquals("`short` = 11",
+ KuduPredicate.newComparisonPredicate(shortCol, EQUAL, 11).toString());
+ Assert.assertEquals("`int` = -123",
+ KuduPredicate.newComparisonPredicate(intCol, EQUAL, -123).toString());
+ Assert.assertEquals("`long` = 5454",
+ KuduPredicate.newComparisonPredicate(longCol, EQUAL, 5454).toString());
+ Assert.assertEquals("`float` = 123.456",
+ KuduPredicate.newComparisonPredicate(floatCol, EQUAL, 123.456f).toString());
+ Assert.assertEquals("`double` = 123.456",
+ KuduPredicate.newComparisonPredicate(doubleCol, EQUAL, 123.456).toString());
+ Assert.assertEquals("`string` = \"my string\"",
+ KuduPredicate.newComparisonPredicate(stringCol, EQUAL, "my string").toString());
+ Assert.assertEquals("`binary` = 0xAB01CD", KuduPredicate.newComparisonPredicate(
+ binaryCol, EQUAL, new byte[] { (byte) 0xAB, (byte) 0x01, (byte) 0xCD }).toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduSession.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduSession.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduSession.java
new file mode 100644
index 0000000..df2367f
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduSession.java
@@ -0,0 +1,337 @@
+// 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.kududb.client;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+import static org.junit.Assert.*;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestKuduSession extends BaseKuduTest {
+ @Rule
+ public TestName name = new TestName();
+
+ private KuduTable table;
+
+ @Test(timeout = 100000)
+ public void testBasicOps() throws Exception {
+ String tableName = name.getMethodName();
+ table = createTable(tableName, basicSchema, getBasicCreateTableOptions());
+
+ KuduSession session = syncClient.newSession();
+ for (int i = 0; i < 10; i++) {
+ session.apply(createInsert(i));
+ }
+ assertEquals(10, countRowsInScan(client.newScannerBuilder(table).build()));
+
+ OperationResponse resp = session.apply(createInsert(0));
+ assertTrue(resp.hasRowError());
+
+ session.setFlushMode(SessionConfiguration.FlushMode.MANUAL_FLUSH);
+
+ for (int i = 10; i < 20; i++) {
+ session.apply(createInsert(i));
+ }
+ session.flush();
+ assertEquals(20, countRowsInScan(client.newScannerBuilder(table).build()));
+ }
+
+ @Test(timeout = 100000)
+ public void testIgnoreAllDuplicateRows() throws Exception {
+ String tableName = name.getMethodName();
+ table = createTable(tableName, basicSchema, getBasicCreateTableOptions());
+
+ KuduSession session = syncClient.newSession();
+ session.setIgnoreAllDuplicateRows(true);
+ for (int i = 0; i < 10; i++) {
+ session.apply(createInsert(i));
+ }
+ for (SessionConfiguration.FlushMode mode : SessionConfiguration.FlushMode.values()) {
+ session.setFlushMode(mode);
+ for (int i = 0; i < 10; i++) {
+ OperationResponse resp = session.apply(createInsert(i));
+ if (mode == SessionConfiguration.FlushMode.AUTO_FLUSH_SYNC) {
+ assertFalse(resp.hasRowError());
+ }
+ }
+ if (mode == SessionConfiguration.FlushMode.MANUAL_FLUSH) {
+ List<OperationResponse> responses = session.flush();
+ for (OperationResponse resp : responses) {
+ assertFalse(resp.hasRowError());
+ }
+ } else if (mode == SessionConfiguration.FlushMode.AUTO_FLUSH_BACKGROUND) {
+ while (session.hasPendingOperations()) {
+ Thread.sleep(100);
+ }
+ assertEquals(0, session.countPendingErrors());
+ }
+ }
+ }
+
+ @Test(timeout = 100000)
+ public void testBatchWithSameRow() throws Exception {
+ String tableName = name.getMethodName();
+ table = createTable(tableName, basicSchema, getBasicCreateTableOptions());
+
+ KuduSession session = syncClient.newSession();
+ session.setFlushMode(SessionConfiguration.FlushMode.MANUAL_FLUSH);
+
+ // Insert 25 rows, one per batch, along with 50 updates for each, and a delete at the end,
+ // while also clearing the cache between each batch half the time. The delete is added here
+ // so that a misplaced update would fail if it happens later than its delete.
+ for (int i = 0; i < 25; i++) {
+ session.apply(createInsert(i));
+ for (int j = 0; j < 50; j++) {
+ Update update = table.newUpdate();
+ PartialRow row = update.getRow();
+ row.addInt(basicSchema.getColumnByIndex(0).getName(), i);
+ row.addInt(basicSchema.getColumnByIndex(1).getName(), 1000);
+ session.apply(update);
+ }
+ Delete del = table.newDelete();
+ PartialRow row = del.getRow();
+ row.addInt(basicSchema.getColumnByIndex(0).getName(), i);
+ session.apply(del);
+ session.flush();
+ if (i % 2 == 0) {
+ client.emptyTabletsCacheForTable(table.getTableId());
+ }
+ }
+ assertEquals(0, countRowsInScan(client.newScannerBuilder(table).build()));
+ }
+
+ /**
+ * Regression test for KUDU-1226. Calls to session.flush() concurrent with AUTO_FLUSH_BACKGROUND
+ * can end up giving ConvertBatchToListOfResponsesCB a list with nulls if a tablet was already
+ * flushed. Only happens with multiple tablets.
+ */
+ @Test(timeout = 10000)
+ public void testConcurrentFlushes() throws Exception {
+ String tableName = name.getMethodName();
+ CreateTableOptions builder = getBasicCreateTableOptions();
+ int numTablets = 4;
+ int numRowsPerTablet = 100;
+
+ // Create a 4 tablets table split on 1000, 2000, and 3000.
+ for (int i = 1; i < numTablets; i++) {
+ PartialRow split = basicSchema.newPartialRow();
+ split.addInt(0, i * numRowsPerTablet);
+ builder.addSplitRow(split);
+ }
+ table = createTable(tableName, basicSchema, builder);
+
+ // Configure the session to background flush as often as it can (every 1ms).
+ KuduSession session = syncClient.newSession();
+ session.setFlushMode(SessionConfiguration.FlushMode.AUTO_FLUSH_BACKGROUND);
+ session.setFlushInterval(1);
+
+ // Fill each tablet in parallel 1 by 1 then flush. Without the fix this would quickly get an
+ // NPE.
+ for (int i = 0; i < numRowsPerTablet; i++) {
+ for (int j = 0; j < numTablets; j++) {
+ session.apply(createInsert(i + (numRowsPerTablet * j)));
+ }
+ session.flush();
+ }
+ }
+
+ @Test(timeout = 10000)
+ public void testOverWritingValues() throws Exception {
+ String tableName = name.getMethodName();
+ table = createTable(tableName, basicSchema, getBasicCreateTableOptions());
+ KuduSession session = syncClient.newSession();
+ Insert insert = createInsert(0);
+ PartialRow row = insert.getRow();
+
+ // Overwrite all the normal columns.
+ int magicNumber = 9999;
+ row.addInt(1, magicNumber);
+ row.addInt(2, magicNumber);
+ row.addBoolean(4, false);
+ // Spam the string column since it's backed by an array.
+ for (int i = 0; i <= magicNumber; i++) {
+ row.addString(3, i + "");
+ }
+ // We're supposed to keep a constant size.
+ assertEquals(5, row.getVarLengthData().size());
+ session.apply(insert);
+
+ KuduScanner scanner = syncClient.newScannerBuilder(table).build();
+ RowResult rr = scanner.nextRows().next();
+ assertEquals(magicNumber, rr.getInt(1));
+ assertEquals(magicNumber, rr.getInt(2));
+ assertEquals(magicNumber + "", rr.getString(3));
+ assertEquals(false, rr.getBoolean(4));
+
+ // Test setting a value post-apply.
+ try {
+ row.addInt(1, 0);
+ fail("Row should be frozen and throw");
+ } catch (IllegalStateException ex) {
+ // Ok.
+ }
+ }
+
+ @Test(timeout = 10000)
+ public void testUpsert() throws Exception {
+ String tableName = name.getMethodName();
+ table = createTable(tableName, basicSchema, getBasicCreateTableOptions());
+ KuduSession session = syncClient.newSession();
+
+ // Test an Upsert that acts as an Insert.
+ assertFalse(session.apply(createUpsert(1, 1, false)).hasRowError());
+
+ List<String> rowStrings = scanTableToStrings(table);
+ assertEquals(1, rowStrings.size());
+ assertEquals(
+ "INT32 key=1, INT32 column1_i=1, INT32 column2_i=3, " +
+ "STRING column3_s=a string, BOOL column4_b=true",
+ rowStrings.get(0));
+
+ // Test an Upsert that acts as an Update.
+ assertFalse(session.apply(createUpsert(1, 2, false)).hasRowError());
+ rowStrings = scanTableToStrings(table);
+ assertEquals(
+ "INT32 key=1, INT32 column1_i=2, INT32 column2_i=3, " +
+ "STRING column3_s=a string, BOOL column4_b=true",
+ rowStrings.get(0));
+ }
+
+ @Test(timeout = 10000)
+ public void testInsertManualFlushNonCoveredRange() throws Exception {
+ String tableName = name.getMethodName();
+ CreateTableOptions createOptions = getBasicTableOptionsWithNonCoveredRange();
+ createOptions.setNumReplicas(1);
+ syncClient.createTable(tableName, basicSchema, createOptions);
+ KuduTable table = syncClient.openTable(tableName);
+
+ KuduSession session = syncClient.newSession();
+ session.setFlushMode(SessionConfiguration.FlushMode.MANUAL_FLUSH);
+
+ // Insert in reverse sorted order so that more table location lookups occur
+ // (the extra results in table location lookups always occur past the inserted key).
+ List<Integer> nonCoveredKeys = ImmutableList.of(350, 300, 199, 150, 100, -1, -50);
+ for (int key : nonCoveredKeys) {
+ assertNull(session.apply(createBasicSchemaInsert(table, key)));
+ }
+ List<OperationResponse> results = session.flush();
+ assertEquals(nonCoveredKeys.size(), results.size());
+ for (OperationResponse result : results) {
+ assertTrue(result.hasRowError());
+ assertTrue(result.getRowError().getErrorStatus().isNotFound());
+ }
+
+ // Insert a batch of some valid and some invalid.
+ for (int key = 90; key < 110; key++) {
+ session.apply(createBasicSchemaInsert(table, key));
+ }
+ results = session.flush();
+
+ int failures = 0;
+ for (OperationResponse result : results) {
+ if (result.hasRowError()) {
+ failures++;
+ assertTrue(result.getRowError().getErrorStatus().isNotFound());
+ }
+ }
+ assertEquals(10, failures);
+ }
+
+ @Test(timeout = 10000)
+ public void testInsertAutoFlushSyncNonCoveredRange() throws Exception {
+ String tableName = name.getMethodName();
+ CreateTableOptions createOptions = getBasicTableOptionsWithNonCoveredRange();
+ createOptions.setNumReplicas(1);
+ syncClient.createTable(tableName, basicSchema, createOptions);
+ KuduTable table = syncClient.openTable(tableName);
+
+ KuduSession session = syncClient.newSession();
+ session.setFlushMode(SessionConfiguration.FlushMode.AUTO_FLUSH_SYNC);
+
+ List<Integer> nonCoveredKeys = ImmutableList.of(350, 300, 199, 150, 100, -1, -50);
+ for (int key : nonCoveredKeys) {
+ try {
+ session.apply(createBasicSchemaInsert(table, key));
+ fail("apply should have thrown");
+ } catch (KuduException e) {
+ assertTrue(e.getStatus().isNotFound());
+ }
+ }
+ }
+
+ @Test(timeout = 10000)
+ public void testInsertAutoFlushBackgrounNonCoveredRange() throws Exception {
+ String tableName = name.getMethodName();
+ CreateTableOptions createOptions = getBasicTableOptionsWithNonCoveredRange();
+ createOptions.setNumReplicas(1);
+ syncClient.createTable(tableName, basicSchema, createOptions);
+ KuduTable table = syncClient.openTable(tableName);
+
+ AsyncKuduSession session = client.newSession();
+ session.setFlushMode(SessionConfiguration.FlushMode.AUTO_FLUSH_BACKGROUND);
+
+ List<Integer> nonCoveredKeys = ImmutableList.of(350, 300, 199, 150, 100, -1, -50);
+ for (int key : nonCoveredKeys) {
+ OperationResponse result = session.apply(createBasicSchemaInsert(table, key)).join(5000);
+ assertTrue(result.hasRowError());
+ assertTrue(result.getRowError().getErrorStatus().isNotFound());
+ }
+
+ RowErrorsAndOverflowStatus errors = session.getPendingErrors();
+ assertEquals(nonCoveredKeys.size(), errors.getRowErrors().length);
+ for (RowError error : errors.getRowErrors()) {
+ assertTrue(error.getErrorStatus().isNotFound());
+ }
+
+ // Insert a batch of some valid and some invalid.
+ for (int key = 90; key < 110; key++) {
+ session.apply(createBasicSchemaInsert(table, key));
+ }
+ session.flush();
+
+ errors = session.getPendingErrors();
+ assertEquals(10, errors.getRowErrors().length);
+ for (RowError error : errors.getRowErrors()) {
+ assertTrue(error.getErrorStatus().isNotFound());
+ }
+ }
+
+ private Insert createInsert(int key) {
+ return createBasicSchemaInsert(table, key);
+ }
+
+ private Upsert createUpsert(int key, int secondVal, boolean hasNull) {
+ Upsert upsert = table.newUpsert();
+ PartialRow row = upsert.getRow();
+ row.addInt(0, key);
+ row.addInt(1, secondVal);
+ row.addInt(2, 3);
+ if (hasNull) {
+ row.setNull(3);
+ } else {
+ row.addString(3, "a string");
+ }
+ row.addBoolean(4, true);
+ return upsert;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java
new file mode 100644
index 0000000..4e41a29
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduTable.java
@@ -0,0 +1,301 @@
+// 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.kududb.client;
+
+import org.junit.Rule;
+import org.junit.rules.TestName;
+import org.kududb.ColumnSchema;
+import org.kududb.Schema;
+import org.kududb.Type;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class TestKuduTable extends BaseKuduTest {
+ private static final Logger LOG = LoggerFactory.getLogger(TestKuduTable.class);
+
+ @Rule
+ public TestName name = new TestName();
+
+ private static Schema schema = getBasicSchema();
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ BaseKuduTest.setUpBeforeClass();
+ }
+
+ @Test(timeout = 100000)
+ public void testAlterTable() throws Exception {
+ String tableName = name.getMethodName();
+ createTable(tableName, basicSchema, getBasicCreateTableOptions());
+ try {
+
+ // Add a col.
+ AlterTableOptions ato = new AlterTableOptions().addColumn("testaddint", Type.INT32, 4);
+ submitAlterAndCheck(ato, tableName);
+
+ // Rename that col.
+ ato = new AlterTableOptions().renameColumn("testaddint", "newtestaddint");
+ submitAlterAndCheck(ato, tableName);
+
+ // Delete it.
+ ato = new AlterTableOptions().dropColumn("newtestaddint");
+ submitAlterAndCheck(ato, tableName);
+
+ String newTableName = tableName +"new";
+
+ // Rename our table.
+ ato = new AlterTableOptions().renameTable(newTableName);
+ submitAlterAndCheck(ato, tableName, newTableName);
+
+ // Rename it back.
+ ato = new AlterTableOptions().renameTable(tableName);
+ submitAlterAndCheck(ato, newTableName, tableName);
+
+ // Try adding two columns, where one is nullable.
+ ato = new AlterTableOptions()
+ .addColumn("testaddmulticolnotnull", Type.INT32, 4)
+ .addNullableColumn("testaddmulticolnull", Type.STRING);
+ submitAlterAndCheck(ato, tableName);
+
+
+ // Try altering a table that doesn't exist.
+ String nonExistingTableName = "table_does_not_exist";
+ try {
+ syncClient.alterTable(nonExistingTableName, ato);
+ fail("Shouldn't be able to alter a table that doesn't exist");
+ } catch (KuduException ex) {
+ assertTrue(ex.getStatus().isNotFound());
+ }
+
+ try {
+ syncClient.isAlterTableDone(nonExistingTableName);
+ fail("Shouldn't be able to query if an alter table is done here");
+ } catch (KuduException ex) {
+ assertTrue(ex.getStatus().isNotFound());
+ }
+ } finally {
+ // Normally Java tests accumulate tables without issue, deleting them all
+ // when shutting down the mini cluster at the end of every test class.
+ // However, testGetLocations below expects a certain table count, so
+ // we'll delete our table to ensure there's no interaction between them.
+ syncClient.deleteTable(tableName);
+ }
+ }
+
+ /**
+ * Helper method to submit an Alter and wait for it to happen, using the default table name to
+ * check.
+ */
+ private void submitAlterAndCheck(AlterTableOptions ato, String tableToAlter)
+ throws Exception {
+ submitAlterAndCheck(ato, tableToAlter, tableToAlter);
+ }
+
+ private void submitAlterAndCheck(AlterTableOptions ato,
+ String tableToAlter, String tableToCheck) throws
+ Exception {
+ if (masterHostPorts.size() > 1) {
+ LOG.info("Alter table is not yet supported with multiple masters. Specify " +
+ "-DnumMasters=1 on the command line to start a single-master cluster to run this test.");
+ return;
+ }
+ AlterTableResponse alterResponse = syncClient.alterTable(tableToAlter, ato);
+ boolean done = syncClient.isAlterTableDone(tableToCheck);
+ assertTrue(done);
+ }
+
+ /**
+ * Test creating tables of different sizes and see that we get the correct number of tablets back
+ * @throws Exception
+ */
+ @Test
+ public void testGetLocations() throws Exception {
+ String table1 = name.getMethodName() + System.currentTimeMillis();
+
+ // Test a non-existing table
+ try {
+ openTable(table1);
+ fail("Should receive an exception since the table doesn't exist");
+ } catch (Exception ex) {
+ // expected
+ }
+ // Test with defaults
+ String tableWithDefault = name.getMethodName() + "WithDefault" + System.currentTimeMillis();
+ CreateTableOptions builder = getBasicCreateTableOptions();
+ List<ColumnSchema> columns = new ArrayList<ColumnSchema>(schema.getColumnCount());
+ int defaultInt = 30;
+ String defaultString = "data";
+ for (ColumnSchema columnSchema : schema.getColumns()) {
+
+ Object defaultValue;
+
+ if (columnSchema.getType() == Type.INT32) {
+ defaultValue = defaultInt;
+ } else if (columnSchema.getType() == Type.BOOL) {
+ defaultValue = true;
+ } else {
+ defaultValue = defaultString;
+ }
+ columns.add(
+ new ColumnSchema.ColumnSchemaBuilder(columnSchema.getName(), columnSchema.getType())
+ .key(columnSchema.isKey())
+ .nullable(columnSchema.isNullable())
+ .defaultValue(defaultValue).build());
+ }
+ Schema schemaWithDefault = new Schema(columns);
+ KuduTable kuduTable = createTable(tableWithDefault, schemaWithDefault, builder);
+ assertEquals(defaultInt, kuduTable.getSchema().getColumnByIndex(0).getDefaultValue());
+ assertEquals(defaultString,
+ kuduTable.getSchema().getColumnByIndex(columns.size() - 2).getDefaultValue());
+ assertEquals(true,
+ kuduTable.getSchema().getColumnByIndex(columns.size() - 1).getDefaultValue());
+
+ // Make sure the table's schema includes column IDs.
+ assertTrue(kuduTable.getSchema().hasColumnIds());
+
+ // Test we can open a table that was already created.
+ openTable(tableWithDefault);
+
+ // Test splitting and reading those splits
+ KuduTable kuduTableWithoutDefaults = createTableWithSplitsAndTest(0);
+ // finish testing read defaults
+ assertNull(kuduTableWithoutDefaults.getSchema().getColumnByIndex(0).getDefaultValue());
+ createTableWithSplitsAndTest(3);
+ createTableWithSplitsAndTest(10);
+
+ KuduTable table = createTableWithSplitsAndTest(30);
+
+ List<LocatedTablet>tablets = table.getTabletsLocations(null, getKeyInBytes(9), DEFAULT_SLEEP);
+ assertEquals(9, tablets.size());
+ assertEquals(9, table.asyncGetTabletsLocations(null, getKeyInBytes(9), DEFAULT_SLEEP).join().size());
+
+ tablets = table.getTabletsLocations(getKeyInBytes(0), getKeyInBytes(9), DEFAULT_SLEEP);
+ assertEquals(9, tablets.size());
+ assertEquals(9, table.asyncGetTabletsLocations(getKeyInBytes(0), getKeyInBytes(9), DEFAULT_SLEEP).join().size());
+
+ tablets = table.getTabletsLocations(getKeyInBytes(5), getKeyInBytes(9), DEFAULT_SLEEP);
+ assertEquals(4, tablets.size());
+ assertEquals(4, table.asyncGetTabletsLocations(getKeyInBytes(5), getKeyInBytes(9), DEFAULT_SLEEP).join().size());
+
+ tablets = table.getTabletsLocations(getKeyInBytes(5), getKeyInBytes(14), DEFAULT_SLEEP);
+ assertEquals(9, tablets.size());
+ assertEquals(9, table.asyncGetTabletsLocations(getKeyInBytes(5), getKeyInBytes(14), DEFAULT_SLEEP).join().size());
+
+ tablets = table.getTabletsLocations(getKeyInBytes(5), getKeyInBytes(31), DEFAULT_SLEEP);
+ assertEquals(26, tablets.size());
+ assertEquals(26, table.asyncGetTabletsLocations(getKeyInBytes(5), getKeyInBytes(31), DEFAULT_SLEEP).join().size());
+
+ tablets = table.getTabletsLocations(getKeyInBytes(5), null, DEFAULT_SLEEP);
+ assertEquals(26, tablets.size());
+ assertEquals(26, table.asyncGetTabletsLocations(getKeyInBytes(5), null, DEFAULT_SLEEP).join().size());
+
+ tablets = table.getTabletsLocations(null, getKeyInBytes(10000), DEFAULT_SLEEP);
+ assertEquals(31, tablets.size());
+ assertEquals(31, table.asyncGetTabletsLocations(null, getKeyInBytes(10000), DEFAULT_SLEEP).join().size());
+
+ tablets = table.getTabletsLocations(getKeyInBytes(20), getKeyInBytes(10000), DEFAULT_SLEEP);
+ assertEquals(11, tablets.size());
+ assertEquals(11, table.asyncGetTabletsLocations(getKeyInBytes(20), getKeyInBytes(10000), DEFAULT_SLEEP).join().size());
+
+ // Test listing tables.
+ assertEquals(0, client.getTablesList(table1).join(DEFAULT_SLEEP).getTablesList().size());
+ assertEquals(1, client.getTablesList(tableWithDefault)
+ .join(DEFAULT_SLEEP).getTablesList().size());
+ assertEquals(5, client.getTablesList().join(DEFAULT_SLEEP).getTablesList().size());
+ assertFalse(client.getTablesList(tableWithDefault).
+ join(DEFAULT_SLEEP).getTablesList().isEmpty());
+
+ assertFalse(client.tableExists(table1).join(DEFAULT_SLEEP));
+ assertTrue(client.tableExists(tableWithDefault).join(DEFAULT_SLEEP));
+ }
+
+ @Test(timeout = 100000)
+ public void testLocateTableNonCoveringRange() throws Exception {
+ String tableName = name.getMethodName();
+ syncClient.createTable(tableName, basicSchema, getBasicTableOptionsWithNonCoveredRange());
+ KuduTable table = syncClient.openTable(tableName);
+
+ List<LocatedTablet> tablets;
+
+ // all tablets
+ tablets = table.getTabletsLocations(null, null, 100000);
+ assertEquals(3, tablets.size());
+ assertArrayEquals(getKeyInBytes(0), tablets.get(0).getPartition().getPartitionKeyStart());
+ assertArrayEquals(getKeyInBytes(50), tablets.get(0).getPartition().getPartitionKeyEnd());
+ assertArrayEquals(getKeyInBytes(50), tablets.get(1).getPartition().getPartitionKeyStart());
+ assertArrayEquals(getKeyInBytes(100), tablets.get(1).getPartition().getPartitionKeyEnd());
+ assertArrayEquals(getKeyInBytes(200), tablets.get(2).getPartition().getPartitionKeyStart());
+ assertArrayEquals(getKeyInBytes(300), tablets.get(2).getPartition().getPartitionKeyEnd());
+
+ // key < 50
+ tablets = table.getTabletsLocations(null, getKeyInBytes(50), 100000);
+ assertEquals(1, tablets.size());
+ assertArrayEquals(getKeyInBytes(0), tablets.get(0).getPartition().getPartitionKeyStart());
+ assertArrayEquals(getKeyInBytes(50), tablets.get(0).getPartition().getPartitionKeyEnd());
+
+ // key >= 300
+ tablets = table.getTabletsLocations(getKeyInBytes(300), null, 100000);
+ assertEquals(0, tablets.size());
+
+ // key >= 299
+ tablets = table.getTabletsLocations(getKeyInBytes(299), null, 100000);
+ assertEquals(1, tablets.size());
+ assertArrayEquals(getKeyInBytes(200), tablets.get(0).getPartition().getPartitionKeyStart());
+ assertArrayEquals(getKeyInBytes(300), tablets.get(0).getPartition().getPartitionKeyEnd());
+
+ // key >= 150 && key < 250
+ tablets = table.getTabletsLocations(getKeyInBytes(150), getKeyInBytes(250), 100000);
+ assertEquals(1, tablets.size());
+ assertArrayEquals(getKeyInBytes(200), tablets.get(0).getPartition().getPartitionKeyStart());
+ assertArrayEquals(getKeyInBytes(300), tablets.get(0).getPartition().getPartitionKeyEnd());
+ }
+
+ public byte[] getKeyInBytes(int i) {
+ PartialRow row = schema.newPartialRow();
+ row.addInt(0, i);
+ return row.encodePrimaryKey();
+ }
+
+ public KuduTable createTableWithSplitsAndTest(int splitsCount) throws Exception {
+ String tableName = name.getMethodName() + System.currentTimeMillis();
+ CreateTableOptions builder = getBasicCreateTableOptions();
+
+ if (splitsCount != 0) {
+ for (int i = 1; i <= splitsCount; i++) {
+ PartialRow row = schema.newPartialRow();
+ row.addInt(0, i);
+ builder.addSplitRow(row);
+ }
+ }
+ KuduTable table = createTable(tableName, schema, builder);
+
+ List<LocatedTablet> tablets = table.getTabletsLocations(DEFAULT_SLEEP);
+ assertEquals(splitsCount + 1, tablets.size());
+ assertEquals(splitsCount + 1, table.asyncGetTabletsLocations(DEFAULT_SLEEP).join().size());
+ for (LocatedTablet tablet : tablets) {
+ assertEquals(3, tablet.getReplicas().size());
+ }
+ return table;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java
new file mode 100644
index 0000000..49ac502
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestLeaderFailover.java
@@ -0,0 +1,69 @@
+// 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.kududb.client;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TestLeaderFailover extends BaseKuduTest {
+
+ private static final String TABLE_NAME =
+ TestLeaderFailover.class.getName() + "-" + System.currentTimeMillis();
+ private static KuduTable table;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ BaseKuduTest.setUpBeforeClass();
+
+ CreateTableOptions builder = getBasicCreateTableOptions();
+ createTable(TABLE_NAME, basicSchema, builder);
+
+ table = openTable(TABLE_NAME);
+ }
+
+ /**
+ * This test writes 3 rows, kills the leader, then tries to write another 3 rows. Finally it
+ * counts to make sure we have 6 of them.
+ *
+ * This test won't run if we didn't start the cluster.
+ */
+ @Test(timeout = 100000)
+ public void testFailover() throws Exception {
+ KuduSession session = syncClient.newSession();
+ for (int i = 0; i < 3; i++) {
+ session.apply(createBasicSchemaInsert(table, i));
+ }
+
+ // Make sure the rows are in there before messing things up.
+ AsyncKuduScanner scanner = client.newScannerBuilder(table).build();
+ assertEquals(3, countRowsInScan(scanner));
+
+ killTabletLeader(table);
+
+ for (int i = 3; i < 6; i++) {
+ OperationResponse resp = session.apply(createBasicSchemaInsert(table, i));
+ if (resp.hasRowError()) {
+ fail("Encountered a row error " + resp.getRowError());
+ }
+ }
+
+ scanner = client.newScannerBuilder(table).build();
+ assertEquals(6, countRowsInScan(scanner));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestMasterFailover.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestMasterFailover.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestMasterFailover.java
new file mode 100644
index 0000000..2f91a6e
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestMasterFailover.java
@@ -0,0 +1,72 @@
+// 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.kududb.client;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
+
+
+/**
+ * Tests {@link AsyncKuduClient} with multiple masters.
+ */
+public class TestMasterFailover extends BaseKuduTest {
+ private static final Logger LOG = LoggerFactory.getLogger(TestMasterFailover.class);
+ private static final String TABLE_NAME =
+ TestMasterFailover.class.getName() + "-" + System.currentTimeMillis();
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ BaseKuduTest.setUpBeforeClass();
+ createTable(TABLE_NAME, basicSchema, getBasicCreateTableOptions());
+ }
+
+ /**
+ * This test is disabled as we're not supporting multi-master just yet.
+ */
+ @Test(timeout = 30000)
+ @Ignore
+ public void testKillLeader() throws Exception {
+ int countMasters = masterHostPorts.size();
+ if (countMasters < 3) {
+ LOG.info("This test requires at least 3 master servers, but only " + countMasters +
+ " are specified.");
+ return;
+ }
+ killMasterLeader();
+
+ // Test that we can open a previously created table after killing the leader master.
+ KuduTable table = openTable(TABLE_NAME);
+ assertEquals(0, countRowsInScan(client.newScannerBuilder(table).build()));
+
+ // Test that we can create a new table when one of the masters is down.
+ String newTableName = TABLE_NAME + "-afterLeaderIsDead";
+ createTable(newTableName, basicSchema, new CreateTableOptions());
+ table = openTable(newTableName);
+ assertEquals(0, countRowsInScan(client.newScannerBuilder(table).build()));
+
+ // Test that we can initialize a client when one of the masters specified in the
+ // connection string is down.
+ AsyncKuduClient newClient = new AsyncKuduClient.AsyncKuduClientBuilder(masterAddresses).build();
+ table = newClient.openTable(newTableName).join(DEFAULT_SLEEP);
+ assertEquals(0, countRowsInScan(newClient.newScannerBuilder(table).build()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestMiniKuduCluster.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestMiniKuduCluster.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestMiniKuduCluster.java
new file mode 100644
index 0000000..82ffacb
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestMiniKuduCluster.java
@@ -0,0 +1,116 @@
+/**
+ * Licensed 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. See accompanying LICENSE file.
+ */
+package org.kududb.client;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class TestMiniKuduCluster {
+
+ private static final int NUM_TABLET_SERVERS = 3;
+ private static final int DEFAULT_NUM_MASTERS = 1;
+
+ private MiniKuduCluster cluster;
+
+ @Before
+ public void before() throws Exception {
+ cluster = new MiniKuduCluster.MiniKuduClusterBuilder()
+ .numMasters(DEFAULT_NUM_MASTERS)
+ .numTservers(NUM_TABLET_SERVERS)
+ .build();
+ assertTrue(cluster.waitForTabletServers(NUM_TABLET_SERVERS));
+ }
+
+ @After
+ public void after() {
+ if (cluster != null) {
+ cluster.shutdown();
+ }
+ }
+
+ @Test(timeout = 50000)
+ public void test() throws Exception {
+
+ assertEquals(DEFAULT_NUM_MASTERS, cluster.getMasterProcesses().size());
+ assertEquals(NUM_TABLET_SERVERS, cluster.getTabletServerProcesses().size());
+
+ {
+ // Kill the master.
+ int masterPort = cluster.getMasterProcesses().keySet().iterator().next();
+ testPort(masterPort, true, 1000);
+ cluster.killMasterOnPort(masterPort);
+
+ testPort(masterPort, false, 2000);
+
+ // Restart the master.
+ cluster.restartDeadMasterOnPort(masterPort);
+
+ // Test we can reach it.
+ testPort(masterPort, true, 3000);
+ }
+
+
+ {
+ // Kill the first TS.
+ int tsPort = cluster.getTabletServerProcesses().keySet().iterator().next();
+ testPort(tsPort, true, 1000);
+ cluster.killTabletServerOnPort(tsPort);
+
+ testPort(tsPort, false, 2000);
+
+ // Restart it.
+ cluster.restartDeadTabletServerOnPort(tsPort);
+
+ testPort(tsPort, true, 3000);
+ }
+
+ assertEquals(DEFAULT_NUM_MASTERS, cluster.getMasterProcesses().size());
+ assertEquals(NUM_TABLET_SERVERS, cluster.getTabletServerProcesses().size());
+ }
+
+ /**
+ * Test without the specified is open or closed, waiting up to a certain time.
+ * The longer you expect it might for the socket to become open or closed.
+ * @param port the port to test
+ * @param testIsOpen true if we should want it to be open, false if we want it closed
+ * @param timeout how long we're willing to wait before it happens
+ * @throws InterruptedException
+ */
+ private void testPort(int port, boolean testIsOpen, long timeout) throws InterruptedException {
+ DeadlineTracker tracker = new DeadlineTracker();
+ while (tracker.getElapsedMillis() < timeout) {
+ try {
+ Socket socket = new Socket(TestUtils.getUniqueLocalhost(), port);
+ socket.close();
+ if (testIsOpen) {
+ return;
+ }
+ } catch (IOException e) {
+ if (!testIsOpen) {
+ return;
+ }
+ }
+ Thread.sleep(200);
+ }
+ fail("Port " + port + " is still " + (testIsOpen ? "closed " : "open"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestOperation.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestOperation.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestOperation.java
new file mode 100644
index 0000000..f305fbf
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestOperation.java
@@ -0,0 +1,166 @@
+// 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.kududb.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+
+import org.junit.Test;
+import org.kududb.ColumnSchema;
+import org.kududb.Schema;
+import org.kududb.Type;
+import org.kududb.WireProtocol.RowOperationsPB;
+import org.kududb.client.Operation.ChangeType;
+import org.kududb.tserver.Tserver.WriteRequestPBOrBuilder;
+import org.mockito.Mockito;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Longs;
+
+/**
+ * Unit tests for Operation
+ */
+public class TestOperation {
+
+ private Schema createManyStringsSchema() {
+ ArrayList<ColumnSchema> columns = new ArrayList<ColumnSchema>(4);
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c0", Type.STRING).key(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c1", Type.STRING).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c2", Type.STRING).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c3", Type.STRING).nullable(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c4", Type.STRING).nullable(true).build());
+ return new Schema(columns);
+ }
+
+ @Test
+ public void testSetStrings() {
+ KuduTable table = Mockito.mock(KuduTable.class);
+ Mockito.doReturn(createManyStringsSchema()).when(table).getSchema();
+ Insert insert = new Insert(table);
+ PartialRow row = insert.getRow();
+ row.addString("c0", "c0_val");
+ row.addString("c2", "c2_val");
+ row.addString("c1", "c1_val");
+ row.addString("c3", "c3_val");
+ row.addString("c4", "c4_val");
+
+ {
+ WriteRequestPBOrBuilder pb =
+ Operation.createAndFillWriteRequestPB(ImmutableList.<Operation>of(insert));
+ RowOperationsPB rowOps = pb.getRowOperations();
+ assertEquals(6 * 5, rowOps.getIndirectData().size());
+ assertEquals("c0_valc1_valc2_valc3_valc4_val", rowOps.getIndirectData().toStringUtf8());
+ byte[] rows = rowOps.getRows().toByteArray();
+ assertEquals(ChangeType.INSERT.toEncodedByte(), rows[0]);
+ // The "isset" bitset should have 5 bits set
+ assertEquals(0x1f, rows[1]);
+ // The "null" bitset should have no bits set
+ assertEquals(0, rows[2]);
+
+ // Check the strings.
+ int offset = 3;
+ for (int i = 0; i <= 4; i++) {
+ // The offset into the indirect buffer
+ assertEquals(6 * i, Bytes.getLong(rows, offset));
+ offset += Longs.BYTES;
+ // The length of the pointed-to string.
+ assertEquals(6, Bytes.getLong(rows, offset));
+ offset += Longs.BYTES;
+ }
+
+ // Should have used up whole buffer.
+ assertEquals(rows.length, offset);
+ }
+
+ // Setting a field to NULL should add to the null bitmap and remove
+ // the old value from the indirect buffer.
+ row.setNull("c3");
+ {
+ WriteRequestPBOrBuilder pb =
+ Operation.createAndFillWriteRequestPB(ImmutableList.<Operation>of(insert));
+ RowOperationsPB rowOps = pb.getRowOperations();
+ assertEquals(6 * 4, rowOps.getIndirectData().size());
+ assertEquals("c0_valc1_valc2_valc4_val", rowOps.getIndirectData().toStringUtf8());
+ byte[] rows = rowOps.getRows().toByteArray();
+ assertEquals(ChangeType.INSERT.toEncodedByte(), rows[0]);
+ // The "isset" bitset should have 5 bits set
+ assertEquals(0x1f, rows[1]);
+ // The "null" bitset should have 1 bit set for the null column
+ assertEquals(1 << 3, rows[2]);
+
+ // Check the strings.
+ int offset = 3;
+ int indirOffset = 0;
+ for (int i = 0; i <= 4; i++) {
+ if (i == 3) continue;
+ // The offset into the indirect buffer
+ assertEquals(indirOffset, Bytes.getLong(rows, offset));
+ indirOffset += 6;
+ offset += Longs.BYTES;
+ // The length of the pointed-to string.
+ assertEquals(6, Bytes.getLong(rows, offset));
+ offset += Longs.BYTES;
+ }
+ // Should have used up whole buffer.
+ assertEquals(rows.length, offset);
+ }
+ }
+
+ private Schema createAllTypesKeySchema() {
+ ArrayList<ColumnSchema> columns = new ArrayList<ColumnSchema>(7);
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c0", Type.INT8).key(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c1", Type.INT16).key(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c2", Type.INT32).key(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c3", Type.INT64).key(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c4", Type.TIMESTAMP).key(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c5", Type.STRING).key(true).build());
+ columns.add(new ColumnSchema.ColumnSchemaBuilder("c6", Type.BINARY).key(true).build());
+ return new Schema(columns);
+ }
+
+ @Test
+ public void testRowKeyStringify() {
+ KuduTable table = Mockito.mock(KuduTable.class);
+ Mockito.doReturn(createAllTypesKeySchema()).when(table).getSchema();
+ Insert insert = new Insert(table);
+ PartialRow row = insert.getRow();
+ row.addByte("c0", (byte) 1);
+ row.addShort("c1", (short) 2);
+ row.addInt("c2", 3);
+ row.addLong("c3", 4);
+ row.addLong("c4", 5);
+ row.addString("c5", "c5_val");
+ row.addBinary("c6", Bytes.fromString("c6_val"));
+
+ assertEquals("(int8 c0=1, int16 c1=2, int32 c2=3, int64 c3=4, timestamp c4=5, string" +
+ " c5=c5_val, binary c6=\"c6_val\")",
+ insert.getRow().stringifyRowKey());
+
+ // Test an incomplete row key.
+ insert = new Insert(table);
+ row = insert.getRow();
+ row.addByte("c0", (byte) 1);
+ try {
+ row.stringifyRowKey();
+ fail("Should not be able to stringifyRowKey when not all keys are specified");
+ } catch (IllegalStateException ise) {
+ // Expected.
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestRequestTracker.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRequestTracker.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRequestTracker.java
new file mode 100644
index 0000000..7528de6
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRequestTracker.java
@@ -0,0 +1,74 @@
+// 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.kududb.client;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class TestRequestTracker {
+
+ @Test(timeout = 10000)
+ public void test() {
+ RequestTracker tracker = new RequestTracker("test");
+
+ // A new tracker should have no incomplete RPCs.
+ assertEquals(RequestTracker.NO_SEQ_NO, tracker.firstIncomplete());
+
+ int max = 10;
+
+ for (int i = 0; i < max; i++) {
+ tracker.newSeqNo();
+ }
+
+ // The first RPC is the incomplete one.
+ assertEquals(1, tracker.firstIncomplete());
+
+ // Mark the first as complete, incomplete should advance by 1.
+ tracker.rpcCompleted(1);
+ assertEquals(2, tracker.firstIncomplete());
+
+ // Mark the RPC in the middle as complete, first incomplete doesn't change.
+ tracker.rpcCompleted(5);
+ assertEquals(2, tracker.firstIncomplete());
+
+ // Mark the first half as complete.
+ // Note that we're also testing that rpcCompleted is idempotent.
+ for (int i = 1; i < max / 2; i++) {
+ tracker.rpcCompleted(i);
+ }
+
+ assertEquals(6, tracker.firstIncomplete());
+
+ // Get a few more sequence numbers.
+ long lastSeqNo = 0;
+ for (int i = max / 2; i <= max; i++) {
+ lastSeqNo = tracker.newSeqNo();
+ }
+
+ // Mark them all as complete except the last one.
+ while (tracker.firstIncomplete() != lastSeqNo) {
+ tracker.rpcCompleted(tracker.firstIncomplete());
+ }
+
+ assertEquals(lastSeqNo, tracker.firstIncomplete());
+ tracker.rpcCompleted(lastSeqNo);
+
+ // Test that we get back to NO_SEQ_NO after marking them all.
+ assertEquals(RequestTracker.NO_SEQ_NO, tracker.firstIncomplete());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java
new file mode 100644
index 0000000..90d11aa
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowErrors.java
@@ -0,0 +1,98 @@
+// 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.kududb.client;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestRowErrors extends BaseKuduTest {
+
+ private static KuduTable table;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ BaseKuduTest.setUpBeforeClass();
+
+ }
+
+ @Test(timeout = 100000)
+ public void singleTabletTest() throws Exception {
+ String tableName = TestRowErrors.class.getName() + "-" + System.currentTimeMillis();
+ createTable(tableName, basicSchema, getBasicCreateTableOptions());
+ table = openTable(tableName);
+ AsyncKuduSession session = client.newSession();
+
+ // Insert 3 rows to play with.
+ for (int i = 0; i < 3; i++) {
+ session.apply(createInsert(i)).join(DEFAULT_SLEEP);
+ }
+
+ // Try a single dupe row insert with AUTO_FLUSH_SYNC.
+ Insert dupeForZero = createInsert(0);
+ OperationResponse resp = session.apply(dupeForZero).join(DEFAULT_SLEEP);
+ assertTrue(resp.hasRowError());
+ assertTrue(resp.getRowError().getOperation() == dupeForZero);
+
+ // Now try inserting two dupes and one good row, make sure we get only two errors back.
+ dupeForZero = createInsert(0);
+ Insert dupeForTwo = createInsert(2);
+ session.setFlushMode(AsyncKuduSession.FlushMode.MANUAL_FLUSH);
+ session.apply(dupeForZero);
+ session.apply(dupeForTwo);
+ session.apply(createInsert(4));
+
+ List<OperationResponse> responses = session.flush().join(DEFAULT_SLEEP);
+ List<RowError> errors = OperationResponse.collectErrors(responses);
+ assertEquals(2, errors.size());
+ assertTrue(errors.get(0).getOperation() == dupeForZero);
+ assertTrue(errors.get(1).getOperation() == dupeForTwo);
+ }
+
+ /**
+ * Test collecting errors from multiple tablets.
+ * @throws Exception
+ */
+ @Test(timeout = 100000)
+ public void multiTabletTest() throws Exception {
+ String tableName = TestRowErrors.class.getName() + "-" + System.currentTimeMillis();
+ createFourTabletsTableWithNineRows(tableName);
+ table = openTable(tableName);
+ KuduSession session = syncClient.newSession();
+ session.setFlushMode(KuduSession.FlushMode.AUTO_FLUSH_BACKGROUND);
+
+ int dupRows = 3;
+ session.apply(createInsert(12));
+ session.apply(createInsert(22));
+ session.apply(createInsert(32));
+
+ session.flush();
+
+ RowErrorsAndOverflowStatus reos = session.getPendingErrors();
+ assertEquals(dupRows, reos.getRowErrors().length);
+ assertEquals(0, session.countPendingErrors());
+ }
+
+ private Insert createInsert(int key) {
+ return createBasicSchemaInsert(table, key);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/5c305689/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
new file mode 100644
index 0000000..1b302c1
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRowResult.java
@@ -0,0 +1,129 @@
+// 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.kududb.client;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.kududb.Type;
+
+import java.nio.ByteBuffer;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TestRowResult extends BaseKuduTest {
+
+ // Generate a unique table name
+ private static final String TABLE_NAME =
+ TestRowResult.class.getName() + "-" + System.currentTimeMillis();
+
+ private static KuduTable table;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ BaseKuduTest.setUpBeforeClass();
+ createTable(TABLE_NAME, allTypesSchema, getAllTypesCreateTableOptions());
+ table = openTable(TABLE_NAME);
+ }
+
+ @Test(timeout = 10000)
+ public void test() throws Exception {
+ Insert insert = table.newInsert();
+ PartialRow row = insert.getRow();
+
+ row.addByte(0, (byte) 1);
+ row.addShort(1, (short) 2);
+ row.addInt(2, 3);
+ row.addLong(3, 4l);
+ row.addBoolean(4, true);
+ row.addFloat(5, 5.6f);
+ row.addDouble(6, 7.8);
+ row.addString(7, "string-value");
+ row.addBinary(8, "binary-array".getBytes());
+ ByteBuffer bb = ByteBuffer.wrap("binary-bytebuffer".getBytes());
+ bb.position(7); // We're only inserting the bytebuffer part of the original array.
+ row.addBinary(9, bb);
+ row.setNull(10);
+ row.addLong(11, 11l);
+
+ KuduSession session = syncClient.newSession();
+ session.apply(insert);
+
+ KuduScanner scanner = syncClient.newScannerBuilder(table).build();
+ while (scanner.hasMoreRows()) {
+ RowResultIterator it = scanner.nextRows();
+ assertTrue(it.hasNext());
+ RowResult rr = it.next();
+
+ assertEquals((byte) 1, rr.getByte(0));
+ assertEquals((byte) 1, rr.getByte(allTypesSchema.getColumnByIndex(0).getName()));
+
+ assertEquals((short) 2, rr.getShort(1));
+ assertEquals((short) 2, rr.getShort(allTypesSchema.getColumnByIndex(1).getName()));
+
+ assertEquals(3, rr.getInt(2));
+ assertEquals(3, rr.getInt(allTypesSchema.getColumnByIndex(2).getName()));
+
+ assertEquals(4, rr.getLong(3));
+ assertEquals(4, rr.getLong(allTypesSchema.getColumnByIndex(3).getName()));
+
+ assertEquals(true, rr.getBoolean(4));
+ assertEquals(true, rr.getBoolean(allTypesSchema.getColumnByIndex(4).getName()));
+
+ assertEquals(5.6f, rr.getFloat(5), .001f);
+ assertEquals(5.6f, rr.getFloat(allTypesSchema.getColumnByIndex(5).getName()), .001f);
+
+ assertEquals(7.8, rr.getDouble(6), .001);
+ assertEquals(7.8, rr.getDouble(allTypesSchema.getColumnByIndex(6).getName()), .001f);
+
+ assertEquals("string-value", rr.getString(7));
+ assertEquals("string-value", rr.getString(allTypesSchema.getColumnByIndex(7).getName()));
+
+ assertArrayEquals("binary-array".getBytes(), rr.getBinaryCopy(8));
+ assertArrayEquals("binary-array".getBytes(),
+ rr.getBinaryCopy(allTypesSchema.getColumnByIndex(8).getName()));
+
+ ByteBuffer buffer = rr.getBinary(8);
+ assertEquals(buffer, rr.getBinary(allTypesSchema.getColumnByIndex(8).getName()));
+ byte[] binaryValue = new byte[buffer.remaining()];
+ buffer.get(binaryValue);
+ assertArrayEquals("binary-array".getBytes(), binaryValue);
+
+ assertArrayEquals("bytebuffer".getBytes(), rr.getBinaryCopy(9));
+
+ assertEquals(true, rr.isNull(10));
+ assertEquals(true, rr.isNull(allTypesSchema.getColumnByIndex(10).getName()));
+
+ assertEquals(11, rr.getLong(11));
+ assertEquals(11, rr.getLong(allTypesSchema.getColumnByIndex(11).getName()));
+
+ // We test with the column name once since it's the same method for all types, unlike above.
+ assertEquals(Type.INT8, rr.getColumnType(allTypesSchema.getColumnByIndex(0).getName()));
+ assertEquals(Type.INT8, rr.getColumnType(0));
+ assertEquals(Type.INT16, rr.getColumnType(1));
+ assertEquals(Type.INT32, rr.getColumnType(2));
+ assertEquals(Type.INT64, rr.getColumnType(3));
+ assertEquals(Type.BOOL, rr.getColumnType(4));
+ assertEquals(Type.FLOAT, rr.getColumnType(5));
+ assertEquals(Type.DOUBLE, rr.getColumnType(6));
+ assertEquals(Type.STRING, rr.getColumnType(7));
+ assertEquals(Type.BINARY, rr.getColumnType(8));
+ assertEquals(Type.TIMESTAMP, rr.getColumnType(11));
+ }
+ }
+}