/* * Copyright (C) 2012-2015 DataStax 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.datastax.driver.core.policies; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.concurrent.TimeUnit; import static com.datastax.driver.core.Assertions.assertThat; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.mockito.Mockito.when; public class RollingCountTest { @Mock Clock clock; RollingCount rollingCount; @BeforeMethod(groups = "unit") public void setup() { MockitoAnnotations.initMocks(this); assertThat(clock.nanoTime()).isEqualTo(0); rollingCount = new RollingCount(clock); } @Test(groups = "unit") public void should_record_adds_in_first_interval() { // t = 0 rollingCount.increment(); setTime(1, SECONDS); rollingCount.increment(); setTime(2, SECONDS); rollingCount.increment(); // the count does not update in real time... assertThat(rollingCount.get()).isEqualTo(0); // but only at the end of each 5-second interval setTime(5, SECONDS); assertThat(rollingCount.get()).isEqualTo(3); } @Test(groups = "unit") public void should_record_adds_over_two_intervals() { rollingCount.add(2); setTime(5, SECONDS); // 2nd interval rollingCount.add(3); setTime(10, SECONDS); assertThat(rollingCount.get()).isEqualTo(5); } @Test(groups = "unit") public void should_record_adds_separated_by_idle_intervals() { rollingCount.add(2); setTime(10, SECONDS); // 3rd interval rollingCount.add(3); setTime(15, SECONDS); assertThat(rollingCount.get()).isEqualTo(5); } @Test(groups = "unit") public void should_rotate() { // 2 in [0,5[, then 1 every 5 seconds in [5,60[ rollingCount.add(2); for (int i = 1; i < 12; i++) { setTime(i * 5, SECONDS); rollingCount.add(1); } setTime(60, SECONDS); // the previous minute is now [0,60[ assertThat(rollingCount.get()).isEqualTo(13); rollingCount.add(1); setTime(65, SECONDS); // the previous minute is now [5,65[, so the 2 events from [0,5[ should be forgotten assertThat(rollingCount.get()).isEqualTo(12); } @Test(groups = "unit") public void should_rotate_with_idle_intervals() { // 1 every 5 seconds in [0,60[ for (int i = 0; i < 12; i++) { setTime(i * 5, SECONDS); rollingCount.add(1); } // idle in [60, 75[, then 1 in [75,80[ setTime(75, SECONDS); rollingCount.add(1); setTime(80, SECONDS); // the last minute is [20,80[, with 1 every 5 seconds except during 15 seconds assertThat(rollingCount.get()).isEqualTo(9); } @Test(groups = "unit") public void should_rotate_when_idle_for_full_period() { // 1 every 5 seconds in [0,60[ for (int i = 0; i < 12; i++) { setTime(i * 5, SECONDS); rollingCount.add(1); } // idle for the next minute [60,120[, then 1 in [120,125[ setTime(120, SECONDS); rollingCount.add(1); setTime(125, SECONDS); assertThat(rollingCount.get()).isEqualTo(1); } @Test(groups = "unit") public void should_rotate_when_idle_for_more_than_full_period() { // 1 every 5 seconds in [0,60[ for (int i = 0; i < 12; i++) { setTime(i * 5, SECONDS); rollingCount.add(1); } // idle for the next minute and 5 seconds [60,125[, then 1 in [125,130[ setTime(125, SECONDS); rollingCount.add(1); setTime(130, SECONDS); assertThat(rollingCount.get()).isEqualTo(1); } private void setTime(long time, TimeUnit unit) { when(clock.nanoTime()).thenReturn(NANOSECONDS.convert(time, unit)); } }