Repository: kudu
Updated Branches:
  refs/heads/master d1f53cc32 -> 4a0417018


KUDU-2033 (part 1). Add write and stop/start in a loop to TestLeaderFailover

TestLeaderFailover is made more robust by adding a write loop in which
the tablet leader is killed and restarted. The main idea is to check
that the writes complete and can be read after the leader is killed.
Done in a loop so we can be sure that we stay stable through multiple
stops and restarts of the leader tablet.

Change-Id: Ie93a15084a4c4c0748dc74c005b8313f443a5ba9
Reviewed-on: http://gerrit.cloudera.org:8080/7456
Reviewed-by: Mike Percy <mpe...@apache.org>
Tested-by: Mike Percy <mpe...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/4a041701
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/4a041701
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/4a041701

Branch: refs/heads/master
Commit: 4a0417018b2833ee9f308a294b319d8c7570990f
Parents: d1f53cc
Author: efancher <e...@cloudera.com>
Authored: Tue Jul 18 14:06:16 2017 -0700
Committer: Mike Percy <mpe...@apache.org>
Committed: Tue Aug 8 18:34:11 2017 +0000

----------------------------------------------------------------------
 .../org/apache/kudu/client/BaseKuduTest.java    |  2 +-
 .../kudu/client/TestMultipleLeaderFailover.java | 95 ++++++++++++++++++++
 .../org/apache/kudu/util/AssertHelpers.java     | 41 +++++++++
 3 files changed, 137 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/4a041701/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java 
b/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
index 1caa21c..a0a5832 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
@@ -382,7 +382,7 @@ public class BaseKuduTest {
    * @return the RPC port of the given tablet's leader tablet server.
    * @throws Exception
    */
-  private static int findLeaderTabletServerPort(LocatedTablet tablet)
+  protected static int findLeaderTabletServerPort(LocatedTablet tablet)
       throws Exception {
     LocatedTablet.Replica leader = null;
     DeadlineTracker deadlineTracker = new DeadlineTracker();

http://git-wip-us.apache.org/repos/asf/kudu/blob/4a041701/java/kudu-client/src/test/java/org/apache/kudu/client/TestMultipleLeaderFailover.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/client/TestMultipleLeaderFailover.java
 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestMultipleLeaderFailover.java
new file mode 100644
index 0000000..526fdb3
--- /dev/null
+++ 
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestMultipleLeaderFailover.java
@@ -0,0 +1,95 @@
+// 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.kudu.client;
+
+import static org.apache.kudu.util.AssertHelpers.assertEventuallyTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import org.apache.kudu.util.AssertHelpers.BooleanExpression;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestMultipleLeaderFailover extends BaseKuduTest {
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {
+    BaseKuduTest.setUpBeforeClass();
+  }
+
+  private void waitUntilRowCount(final KuduTable table, final int rowCount, 
long timeoutMs)
+      throws Exception {
+    assertEventuallyTrue(String.format("Read count should be %s", rowCount),
+        new BooleanExpression() {
+          @Override
+          public boolean get() throws Exception {
+            AsyncKuduScanner scanner = client.newScannerBuilder(table).build();
+            int read_count = countRowsInScan(scanner);
+            return read_count == rowCount;
+          }
+        }, timeoutMs);
+  }
+
+  /**
+   * This test writes 3 rows. Then in a loop, it kills the leader, then tries 
to write inner_row
+   * rows, and finally restarts the tablet server it killed. Verifying with a 
read as it goes.
+   * Finally it counts to make sure we have total_rows_to_insert of them.
+   */
+  @Test(timeout = 100000)
+  public void testMultipleFailover() throws Exception {
+    KuduTable table;
+    CreateTableOptions builder = getBasicCreateTableOptions();
+    String tableName =
+        TestMultipleLeaderFailover.class.getName() + "-" + 
System.currentTimeMillis();
+    createTable(tableName, basicSchema, builder);
+
+    table = openTable(tableName);
+    KuduSession session = syncClient.newSession();
+    final int ROWS_PER_ITERATION = 3;
+    final int NUM_ITERATIONS = 10;
+    final int TOTAL_ROWS_TO_INSERT = ROWS_PER_ITERATION + NUM_ITERATIONS * 
ROWS_PER_ITERATION;
+
+    for (int i = 0; i < ROWS_PER_ITERATION; i++) {
+      session.apply(createBasicSchemaInsert(table, i));
+    }
+
+    waitUntilRowCount(table, ROWS_PER_ITERATION, DEFAULT_SLEEP);
+
+    int currentRows = ROWS_PER_ITERATION;
+    for (int i = 0; i < NUM_ITERATIONS; i++) {
+      List<LocatedTablet> tablets = table.getTabletsLocations(DEFAULT_SLEEP);
+      assertEquals(1, tablets.size());
+      int leaderPort = findLeaderTabletServerPort(tablets.get(0));
+      miniCluster.killTabletServerOnPort(leaderPort);
+
+      for (int j = 0; j < ROWS_PER_ITERATION; j++) {
+        OperationResponse resp = session.apply(createBasicSchemaInsert(table, 
currentRows));
+        if (resp.hasRowError()) {
+          fail("Encountered a row error " + resp.getRowError());
+        }
+        currentRows++;
+      }
+
+      miniCluster.restartDeadTabletServerOnPort(leaderPort);
+      // Read your writes hasn't been enabled, so we need to use a helper 
function to poll.
+      waitUntilRowCount(table, currentRows, DEFAULT_SLEEP);
+
+    }
+    waitUntilRowCount(table, TOTAL_ROWS_TO_INSERT, DEFAULT_SLEEP);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/kudu/blob/4a041701/java/kudu-client/src/test/java/org/apache/kudu/util/AssertHelpers.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-client/src/test/java/org/apache/kudu/util/AssertHelpers.java 
b/java/kudu-client/src/test/java/org/apache/kudu/util/AssertHelpers.java
new file mode 100644
index 0000000..ff7d67e
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/util/AssertHelpers.java
@@ -0,0 +1,41 @@
+// 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.kudu.util;
+
+import static org.junit.Assert.assertTrue;
+
+public class AssertHelpers {
+  public interface BooleanExpression {
+    boolean get() throws Exception;
+  }
+
+  // A looping check. It's mainly useful for scanners, since writes may take a 
little time to show
+  // up.
+  public static void assertEventuallyTrue(String description, 
BooleanExpression expression,
+                                          long timeoutMillis) throws Exception 
{
+    long deadlineNanos = System.nanoTime() + timeoutMillis * 1000000;
+    boolean success;
+
+    do {
+      success = expression.get();
+      if (success) break;
+      Thread.sleep(50); // Sleep for 50ms
+    } while (System.nanoTime() < deadlineNanos);
+
+    assertTrue(description, success);
+  }
+}

Reply via email to