Return-Path: X-Original-To: apmail-accumulo-commits-archive@www.apache.org Delivered-To: apmail-accumulo-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1D24B172CD for ; Mon, 20 Oct 2014 01:05:43 +0000 (UTC) Received: (qmail 20725 invoked by uid 500); 20 Oct 2014 01:05:43 -0000 Delivered-To: apmail-accumulo-commits-archive@accumulo.apache.org Received: (qmail 20593 invoked by uid 500); 20 Oct 2014 01:05:42 -0000 Mailing-List: contact commits-help@accumulo.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@accumulo.apache.org Delivered-To: mailing list commits@accumulo.apache.org Received: (qmail 20543 invoked by uid 99); 20 Oct 2014 01:05:42 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 20 Oct 2014 01:05:42 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 926FA9D27DA; Mon, 20 Oct 2014 01:05:42 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: elserj@apache.org To: commits@accumulo.apache.org Date: Mon, 20 Oct 2014 01:05:48 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [07/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/1.6 Commit: 1636055ac6d8d5fecae9e292be283b864d3d4341 Parents: 1ce12ae Author: Josh Elser Authored: Sat Oct 18 16:18:41 2014 -0400 Committer: Josh Elser 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); + } +}