You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by el...@apache.org on 2014/10/20 03:05:50 UTC

[09/16] git commit: ACCUMULO-3242 Add some tests for Retry

ACCUMULO-3242 Add some tests for Retry


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/1636055a
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/1636055a
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/1636055a

Branch: refs/heads/master
Commit: 1636055ac6d8d5fecae9e292be283b864d3d4341
Parents: 1ce12ae
Author: Josh Elser <el...@apache.org>
Authored: Sat Oct 18 16:18:41 2014 -0400
Committer: Josh Elser <el...@apache.org>
Committed: Sun Oct 19 20:16:04 2014 -0400

----------------------------------------------------------------------
 .../apache/accumulo/fate/zookeeper/Retry.java   |  27 +++-
 .../accumulo/fate/zookeeper/RetryTest.java      | 127 +++++++++++++++++++
 2 files changed, 152 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/1636055a/fate/src/main/java/org/apache/accumulo/fate/zookeeper/Retry.java
----------------------------------------------------------------------
diff --git a/fate/src/main/java/org/apache/accumulo/fate/zookeeper/Retry.java b/fate/src/main/java/org/apache/accumulo/fate/zookeeper/Retry.java
index 63aa902..7bfaba6 100644
--- a/fate/src/main/java/org/apache/accumulo/fate/zookeeper/Retry.java
+++ b/fate/src/main/java/org/apache/accumulo/fate/zookeeper/Retry.java
@@ -24,7 +24,7 @@ import org.apache.log4j.Logger;
 public class Retry {
   private static final Logger log = Logger.getLogger(Retry.class);
 
-  private final long maxRetries, maxWait, waitIncrement;
+  private long maxRetries, maxWait, waitIncrement;
   private long retriesDone, currentWait;
 
   /**
@@ -45,6 +45,26 @@ public class Retry {
     this.currentWait = startWait;
   }
 
+  // Visible for testing
+  void setMaxRetries(long maxRetries) {
+    this.maxRetries = maxRetries;
+  }
+
+  // Visible for testing
+  void setStartWait(long startWait) {
+    this.currentWait = startWait;
+  }
+
+  // Visible for testing
+  void setWaitIncrement(long waitIncrement) {
+    this.waitIncrement = waitIncrement;
+  }
+
+  // Visible for testing
+  void setMaxWait(long maxWait) {
+    this.maxWait = maxWait;
+  }
+
   public boolean canRetry() {
     return retriesDone < maxRetries;
   }
@@ -67,8 +87,11 @@ public class Retry {
 
   public void waitForNextAttempt() throws InterruptedException {
     log.debug("Sleeping for " + currentWait + "ms before retrying operation");
-    Thread.sleep(currentWait);
+    sleep(currentWait);
     currentWait = Math.min(maxWait, currentWait + waitIncrement);
   }
 
+  protected void sleep(long wait) throws InterruptedException {
+    Thread.sleep(wait);
+  }
 }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/1636055a/fate/src/test/java/org/apache/accumulo/fate/zookeeper/RetryTest.java
----------------------------------------------------------------------
diff --git a/fate/src/test/java/org/apache/accumulo/fate/zookeeper/RetryTest.java b/fate/src/test/java/org/apache/accumulo/fate/zookeeper/RetryTest.java
new file mode 100644
index 0000000..e37af01
--- /dev/null
+++ b/fate/src/test/java/org/apache/accumulo/fate/zookeeper/RetryTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.fate.zookeeper;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class RetryTest {
+
+  private Retry retry;
+  long initialWait = 1000l, waitIncrement = 1000l, maxRetries = 5;
+
+  @Before
+  public void setup() {
+    retry = new Retry(maxRetries, initialWait, waitIncrement, maxRetries * 1000l);
+  }
+
+  @Test
+  public void canRetryDoesntAlterState() {
+    for (int i = 0; i < maxRetries + 1; i++) {
+      Assert.assertTrue(retry.canRetry());
+    }
+  }
+
+  @Test
+  public void hasRetriedAfterUse() {
+    Assert.assertFalse(retry.hasRetried());
+    retry.useRetry();
+    Assert.assertTrue(retry.hasRetried());
+  }
+
+  @Test
+  public void retriesAreCompleted() {
+    for (int i = 0; i < maxRetries; i++) {
+      Assert.assertEquals(i, retry.retriesCompleted());
+      // canRetry doesn't alter retry's state
+      retry.canRetry();
+      Assert.assertEquals(i, retry.retriesCompleted());
+      // Using the retry will increase the internal count
+      retry.useRetry();
+      Assert.assertEquals(i + 1, retry.retriesCompleted());
+    }
+  }
+
+  @Test(expected = IllegalStateException.class)
+  public void usingNonExistentRetryFails() {
+    for (int i = 0; i < maxRetries; i++) {
+      Assert.assertTrue(retry.canRetry());
+      retry.useRetry();
+    }
+    Assert.assertFalse(retry.canRetry());
+    // Calling useRetry when canRetry returns false throws an exception
+    retry.useRetry();
+  }
+
+  @Test
+  public void testWaitIncrement() throws InterruptedException {
+    retry = EasyMock.createMockBuilder(Retry.class).addMockedMethod("sleep").createStrictMock();
+    retry.setMaxRetries(maxRetries);
+    retry.setStartWait(initialWait);
+    retry.setWaitIncrement(waitIncrement);
+    retry.setMaxWait(maxRetries * 1000l);
+
+    long currentWait = initialWait;
+    for (int i = 1; i <= maxRetries; i++) {
+      retry.sleep(currentWait);
+      EasyMock.expectLastCall();
+      currentWait += waitIncrement;
+    }
+
+    EasyMock.replay(retry);
+
+    while (retry.canRetry()) {
+      retry.useRetry();
+      retry.waitForNextAttempt();
+    }
+
+    EasyMock.verify(retry);
+  }
+
+  @Test
+  public void testBoundedWaitIncrement() throws InterruptedException {
+    retry = EasyMock.createMockBuilder(Retry.class).addMockedMethod("sleep").createStrictMock();
+    retry.setMaxRetries(maxRetries);
+    retry.setStartWait(initialWait);
+    retry.setWaitIncrement(waitIncrement);
+    // Make the last retry not increment in length
+    retry.setMaxWait((maxRetries - 1) * 1000l);
+
+    long currentWait = initialWait;
+    for (int i = 1; i <= maxRetries; i++) {
+      retry.sleep(currentWait);
+      EasyMock.expectLastCall();
+      if (i < maxRetries - 1) {
+        currentWait += waitIncrement;
+      }
+    }
+
+    EasyMock.replay(retry);
+
+    while (retry.canRetry()) {
+      retry.useRetry();
+      retry.waitForNextAttempt();
+    }
+
+    EasyMock.verify(retry);
+  }
+}