/*
 * Copyright (C) 2015 Google 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.google.cloud.dataflow.sdk.util;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;


import com.google.api.client.util.BackOff;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for {@link IntervalBoundedExponentialBackOff}. */
@RunWith(JUnit4.class)
public class IntervalBoundedExponentialBackOffTest {
  @Rule public ExpectedException exception = ExpectedException.none();

  @Test
  public void testUsingInvalidInitialInterval() throws Exception {
    exception.expect(IllegalArgumentException.class);
    exception.expectMessage("Initial interval must be greater than zero.");
    new IntervalBoundedExponentialBackOff(1000, 0L);
  }

  @Test
  public void testUsingInvalidMaximumInterval() throws Exception {
    exception.expect(IllegalArgumentException.class);
    exception.expectMessage("Maximum interval must be greater than zero.");
    new IntervalBoundedExponentialBackOff(-1, 10L);
  }

  @Test
  public void testThatcertainNumberOfAttemptsReachesMaxInterval() throws Exception {
    BackOff backOff = new IntervalBoundedExponentialBackOff(1000, 500);
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(249L), lessThan(751L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(374L), lessThan(1126L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
  }

  @Test
  public void testThatResettingAllowsReuse() throws Exception {
    BackOff backOff = new IntervalBoundedExponentialBackOff(1000, 500);
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(249L), lessThan(751L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(374L), lessThan(1126L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
    backOff.reset();
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(249L), lessThan(751L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(374L), lessThan(1126L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
  }

  @Test
  public void testAtMaxInterval() throws Exception {
    IntervalBoundedExponentialBackOff backOff = new IntervalBoundedExponentialBackOff(1000, 500);
    assertFalse(backOff.atMaxInterval());
    backOff.nextBackOffMillis();
    assertFalse(backOff.atMaxInterval());
    backOff.nextBackOffMillis();
    assertTrue(backOff.atMaxInterval());
    assertThat(backOff.nextBackOffMillis(), allOf(greaterThan(500L), lessThan(1500L)));
  }
}

@@ -773,24 +773,33 @@
 .greaterThan
+OrEqualTo
 ;%0Aimport sta
@@ -926,53 +926,8 @@
 e;%0A%0A
-%0Aimport com.google.api.client.util.BackOff;%0A%0A
 impo
@@ -1290,16 +1290,17 @@
 one();%0A%0A
+%0A
   @Test%0A
@@ -1905,32 +1905,58 @@
 Exception %7B%0A    
+IntervalBoundedExponential
 BackOff backOff 
@@ -2060,32 +2060,41 @@
 llOf(greaterThan
+OrEqualTo
 (249L), lessThan
@@ -2156,32 +2156,41 @@
 llOf(greaterThan
+OrEqualTo
 (374L), lessThan
@@ -2253,32 +2253,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -2350,32 +2350,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -2447,32 +2447,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -2544,32 +2544,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -2641,32 +2641,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -2766,16 +2766,42 @@
 n %7B%0A    
+IntervalBoundedExponential
 BackOff 
@@ -2913,32 +2913,41 @@
 llOf(greaterThan
+OrEqualTo
 (249L), lessThan
@@ -3009,32 +3009,41 @@
 llOf(greaterThan
+OrEqualTo
 (374L), lessThan
@@ -3106,32 +3106,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -3203,32 +3203,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -3329,16 +3329,25 @@
 aterThan
+OrEqualTo
 (249L), 
@@ -3425,16 +3425,25 @@
 aterThan
+OrEqualTo
 (374L), 
@@ -3514,32 +3514,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -3611,32 +3611,41 @@
 llOf(greaterThan
+OrEqualTo
 (500L), lessThan
@@ -4071,16 +4071,25 @@
 aterThan
+OrEqualTo
 (500L), 

Fix flakiness in IntervalBoundedExponentialBackOff