/* TestSampledQuantile.java * * Copyright 2009-2015 Comcast Interactive Media, LLC. * * 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 org.fishwife.jrugged; import static org.junit.Assert.*; import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; public class TestSampledQuantile { private SampledQuantile impl; @Before public void setUp() { impl = new SampledQuantile(); } @Test public void quantileWithNoSamplesShouldReturnZero() { assertEquals(0, impl.getPercentile(50)); } @Test public void quantileWithOneSampleShouldReturnThatSample() { impl.addSample(42); assertEquals(42, impl.getPercentile(50)); } @Test public void medianOfThreeSamplesIsMiddleSample() { impl.addSample(42); impl.addSample(41); impl.addSample(43); assertEquals(42, impl.getPercentile(50)); } @Test public void medianOfFiveSamplesWithRepeatsStillWorks() { impl.addSample(41); impl.addSample(43); impl.addSample(42); impl.addSample(41); impl.addSample(43); assertEquals(42, impl.getPercentile(50)); } @Test public void medianOfTwoSamplesIsTheirAverage() { impl.addSample(41); impl.addSample(43); assertEquals(42, impl.getPercentile(50)); } @Test public void canGetMedianAsExpressedInQuantiles() { impl.addSample(42); impl.addSample(41); impl.addSample(43); assertEquals(42, impl.getQuantile(1,2)); } @Test public void canGetMedianDirectly() { impl.addSample(42); impl.addSample(41); impl.addSample(43); assertEquals(42, impl.getMedian()); } @Test public void zerothQuantileShouldThrowException() { impl.addSample(41); try { impl.getQuantile(0,7); fail("should have thrown exception"); } catch (SampledQuantile.QuantileOutOfBoundsException expected) { } } @Test public void qthQuantileShouldThrowException() { impl.addSample(41); try { impl.getQuantile(7,7); fail("should have thrown exception"); } catch (SampledQuantile.QuantileOutOfBoundsException expected) { } } @Test public void canSpecifyMaxSamples() { impl = new SampledQuantile(10); for(int i=0; i<20; i++) impl.addSample(0); assertEquals(10, impl.getNumSamples()); } @Test public void canSpecifyCurrentTimeWhenAddingSample() { impl.addSample(41, System.currentTimeMillis()); } @Test public void ignoresSamplesOutsideOfSpecifiedSecondWindow() { impl = new SampledQuantile(60, TimeUnit.SECONDS); long now = System.currentTimeMillis(); impl.addSample(7, now - 90 * 1000L); impl.addSample(42, now); assertEquals(42, impl.getPercentile(50, now+1)); } @Test public void ignoresSamplesOutsideOfSpecifiedNanosecondWindow() { impl = new SampledQuantile(60 * 1000000000L, TimeUnit.NANOSECONDS); long now = System.currentTimeMillis(); impl.addSample(7, now - 90 * 1000L); impl.addSample(42, now); assertEquals(42, impl.getPercentile(50, now+1)); } @Test public void ignoresSamplesOutsideOfSpecifiedMicrosecondWindow() { impl = new SampledQuantile(60 * 1000000L, TimeUnit.MICROSECONDS); long now = System.currentTimeMillis(); impl.addSample(7, now - 90 * 1000L); impl.addSample(42, now); assertEquals(42, impl.getPercentile(50, now+1)); } @Test public void ignoresSamplesOutsideOfSpecifiedMillisecondWindow() { impl = new SampledQuantile(60 * 1000L, TimeUnit.MILLISECONDS); long now = System.currentTimeMillis(); impl.addSample(7, now - 90 * 1000L); impl.addSample(42, now); assertEquals(42, impl.getPercentile(50, now+1)); } @Test public void ignoresSamplesOutsideOfSpecifiedMinuteWindow() { impl = new SampledQuantile(60L, TimeUnit.SECONDS); long now = System.currentTimeMillis(); impl.addSample(7, now - 90 * 1000L); impl.addSample(42, now); assertEquals(42, impl.getPercentile(50, now+1)); } @Test public void ignoresSamplesOutsideOfSpecifiedHourWindow() { impl = new SampledQuantile(3600L, TimeUnit.SECONDS); long now = System.currentTimeMillis(); impl.addSample(7, now - 5400 * 1000L); impl.addSample(42, now); assertEquals(42, impl.getPercentile(50, now+1)); } @Test public void ignoresSamplesOutsideOfSpecifiedDayWindow() { impl = new SampledQuantile(86400L, TimeUnit.SECONDS); long now = System.currentTimeMillis(); impl.addSample(7, now - 2 * 24 * 3600 * 1000L); impl.addSample(42, now); assertEquals(42, impl.getPercentile(50, now+1)); } @Test public void windowedSamplingWorks() { long t0 = System.currentTimeMillis(); impl = new SampledQuantile(10, 60L, TimeUnit.SECONDS, t0); for(int t=0; t<30 * 1000; t++) { impl.addSample(1L, t0 + t); } long t1 = t0 + 30 * 1000L; assertEquals(1L, impl.getPercentile(50, t1)); for(int t=0; t<60*1000; t++) { impl.addSample(2L, t1 + t); } long t2 = t1 + 60 * 1000L; assertEquals(2L, impl.getPercentile(50, t2)); impl.addSample(3L, t2+1); } @Test public void windowedSamplingHandlesLongTimesBetweenSamples() { long t0 = System.currentTimeMillis(); impl = new SampledQuantile(10, 60L, TimeUnit.SECONDS, t0); impl.addSample(1L, t0 + 1); long t1 = t0 + 90 * 1000L; impl.addSample(2L, t1); assertEquals(2L, impl.getPercentile(50, t1)); } }