/* * Copyright (c) 2016 Couchbase, Inc. * * 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. */ package com.couchbase.client.core.time; import org.junit.Test; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class ExponentialDelayTest { @Test public void testPowerOfTwoShouldCalculateExponentially() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Integer.MAX_VALUE, 0, 1, 2); assertEquals(0, exponentialDelay.calculate(0)); assertEquals(1, exponentialDelay.calculate(1)); assertEquals(2, exponentialDelay.calculate(2)); assertEquals(4, exponentialDelay.calculate(3)); assertEquals(8, exponentialDelay.calculate(4)); assertEquals(16, exponentialDelay.calculate(5)); assertEquals(32, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 1.0 SECONDS, powers of 2; lower=0, upper=2147483647}", exponentialDelay.toString()); } @Test public void testPowerOfTwoShouldRespectLowerBound() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Integer.MAX_VALUE, 10, 1, 2); assertEquals(10, exponentialDelay.calculate(0)); assertEquals(10, exponentialDelay.calculate(1)); assertEquals(10, exponentialDelay.calculate(2)); assertEquals(10, exponentialDelay.calculate(3)); assertEquals(10, exponentialDelay.calculate(4)); assertEquals(16, exponentialDelay.calculate(5)); assertEquals(32, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 1.0 SECONDS, powers of 2; lower=10, upper=2147483647}", exponentialDelay.toString()); } @Test public void testPowerOfTwoShouldRespectUpperBound() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, 9, 0, 1, 2); assertEquals(0, exponentialDelay.calculate(0)); assertEquals(1, exponentialDelay.calculate(1)); assertEquals(2, exponentialDelay.calculate(2)); assertEquals(4, exponentialDelay.calculate(3)); assertEquals(8, exponentialDelay.calculate(4)); assertEquals(9, exponentialDelay.calculate(5)); assertEquals(9, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 1.0 SECONDS, powers of 2; lower=0, upper=9}", exponentialDelay.toString()); } @Test public void testPowerOfTwoShouldApplyFactor() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Integer.MAX_VALUE, 0, 10, 2); assertEquals(0, exponentialDelay.calculate(0)); assertEquals(10, exponentialDelay.calculate(1)); assertEquals(20, exponentialDelay.calculate(2)); assertEquals(40, exponentialDelay.calculate(3)); assertEquals(80, exponentialDelay.calculate(4)); assertEquals(160, exponentialDelay.calculate(5)); assertEquals(320, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 10.0 SECONDS, powers of 2; lower=0, upper=2147483647}", exponentialDelay.toString()); } @Test public void testPowerOfTwoShouldNotOverflowInAMillionRetries() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Long.MAX_VALUE, 0, 2d, 2); long previous = Long.MIN_VALUE; //the bitwise operation in ExponentialDelay would overflow the step at i = 32 for(int i = 0; i < 1000000; i++) { long now = exponentialDelay.calculate(i); assertTrue("delay is at " + now + " down from " + previous + ", attempt " + i, now >= previous); previous = now; } } @Test public void testPowerOfTenShouldCalculateExponentially() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Integer.MAX_VALUE, 0, 1, 10); assertEquals(0, exponentialDelay.calculate(0)); assertEquals(1, exponentialDelay.calculate(1)); //1 * 10^0 assertEquals(10, exponentialDelay.calculate(2)); //1 * 10^1 assertEquals(100, exponentialDelay.calculate(3)); //1 * 10^2 assertEquals(1000, exponentialDelay.calculate(4)); assertEquals(10000, exponentialDelay.calculate(5)); assertEquals(100000, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 1.0 SECONDS, powers of 10; lower=0, upper=2147483647}", exponentialDelay.toString()); } @Test public void testPowerOfTenShouldRespectLowerBound() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Integer.MAX_VALUE, 400, 1, 10); assertEquals(400, exponentialDelay.calculate(0)); assertEquals(400, exponentialDelay.calculate(1)); assertEquals(400, exponentialDelay.calculate(2)); assertEquals(400, exponentialDelay.calculate(3)); assertEquals(1000, exponentialDelay.calculate(4)); assertEquals(10000, exponentialDelay.calculate(5)); assertEquals(100000, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 1.0 SECONDS, powers of 10; lower=400, upper=2147483647}", exponentialDelay.toString()); } @Test public void testPowerOfTenShouldRespectUpperBound() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, 500, 0, 1, 10); assertEquals(0, exponentialDelay.calculate(0)); assertEquals(1, exponentialDelay.calculate(1)); assertEquals(10, exponentialDelay.calculate(2)); assertEquals(100, exponentialDelay.calculate(3)); assertEquals(500, exponentialDelay.calculate(4)); assertEquals(500, exponentialDelay.calculate(5)); assertEquals(500, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 1.0 SECONDS, powers of 10; lower=0, upper=500}", exponentialDelay.toString()); } @Test public void testPowerOfTenShouldApplyFactor() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Integer.MAX_VALUE, 0, 2, 10); assertEquals(0, exponentialDelay.calculate(0)); assertEquals(2, exponentialDelay.calculate(1)); assertEquals(20, exponentialDelay.calculate(2)); assertEquals(200, exponentialDelay.calculate(3)); assertEquals(2000, exponentialDelay.calculate(4)); assertEquals(20000, exponentialDelay.calculate(5)); assertEquals(200000, exponentialDelay.calculate(6)); assertEquals("ExponentialDelay{growBy 2.0 SECONDS, powers of 10; lower=0, upper=2147483647}", exponentialDelay.toString()); } @Test public void testPowerOfTenShouldNotOverflowInAMillionRetries() { Delay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Long.MAX_VALUE, 0, 2d, 10); long previous = Long.MIN_VALUE; for(int i = 0; i < 1000000; i++) { long now = exponentialDelay.calculate(i); assertTrue("delay is at " + now + " down from " + previous + ", attempt " + i, now >= previous); previous = now; } } @Test public void testAlternatePowerAndBitshiftPowerProduceSameResult() { ExponentialDelay exponentialDelay = new ExponentialDelay(TimeUnit.SECONDS, Long.MAX_VALUE, 0, 1, 2); for(int i = 1; i < 1000000; i++) { long powValue = exponentialDelay.calculateAlternatePower(i); long bitshiftValue = exponentialDelay.calculatePowerOfTwo(i); assertEquals("difference at step " + i, powValue, bitshiftValue); } } }