001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.metrics.impl;
019
020import static org.junit.Assert.assertEquals;
021
022import java.util.Arrays;
023import java.util.Random;
024import org.apache.hadoop.hbase.HBaseClassTestRule;
025import org.apache.hadoop.hbase.testclassification.MiscTests;
026import org.apache.hadoop.hbase.testclassification.SmallTests;
027import org.junit.Assert;
028import org.junit.ClassRule;
029import org.junit.Test;
030import org.junit.experimental.categories.Category;
031
032/**
033 * Testcases for FastLongHistogram.
034 */
035@Category({MiscTests.class, SmallTests.class})
036public class TestFastLongHistogram {
037
038  @ClassRule
039  public static final HBaseClassTestRule CLASS_RULE =
040      HBaseClassTestRule.forClass(TestFastLongHistogram.class);
041
042  private static void doTestUniform(FastLongHistogram hist) {
043    long[] VALUES = { 0, 10, 20, 30, 40, 50 };
044    double[] qs = new double[VALUES.length];
045    for (int i = 0; i < qs.length; i++) {
046      qs[i] = (double) VALUES[i] / VALUES[VALUES.length - 1];
047    }
048
049    for (int i = 0; i < 10; i++) {
050      for (long v : VALUES) {
051        hist.add(v, 1);
052      }
053      long[] vals = hist.getQuantiles(qs);
054      System.out.println(Arrays.toString(vals));
055      for (int j = 0; j < qs.length; j++) {
056        Assert.assertTrue(j + "-th element org: " + VALUES[j] + ", act: " + vals[j],
057          Math.abs(vals[j] - VALUES[j]) <= 10);
058      }
059      hist.snapshotAndReset();
060    }
061  }
062
063  @Test
064  public void testUniform() {
065    FastLongHistogram hist = new FastLongHistogram(100, 0, 50);
066    doTestUniform(hist);
067  }
068
069  @Test
070  public void testAdaptionOfChange() {
071    // assumes the uniform distribution
072    FastLongHistogram hist = new FastLongHistogram(100, 0, 100);
073
074    Random rand = new Random();
075
076    for (int n = 0; n < 10; n++) {
077      for (int i = 0; i < 900; i++) {
078        hist.add(rand.nextInt(100), 1);
079      }
080
081      // add 10% outliers, this breaks the assumption, hope bin10xMax works
082      for (int i = 0; i < 100; i++) {
083        hist.add(1000 + rand.nextInt(100), 1);
084      }
085
086      long[] vals = hist.getQuantiles(new double[] { 0.25, 0.75, 0.95 });
087      System.out.println(Arrays.toString(vals));
088      if (n == 0) {
089        Assert.assertTrue("Out of possible value", vals[0] >= 0 && vals[0] <= 50);
090        Assert.assertTrue("Out of possible value", vals[1] >= 50 && vals[1] <= 100);
091        Assert.assertTrue("Out of possible value", vals[2] >= 900 && vals[2] <= 1100);
092      }
093
094      hist.snapshotAndReset();
095    }
096  }
097
098
099  @Test
100  public void testGetNumAtOrBelow() {
101    long[] VALUES = { 1, 10, 20, 30, 40, 50 };
102
103    FastLongHistogram h = new FastLongHistogram();
104    for (long v : VALUES) {
105      for (int i = 0; i < 100; i++) {
106        h.add(v, 1);
107      }
108    }
109
110    h.add(Integer.MAX_VALUE, 1);
111
112    h.snapshotAndReset();
113
114    for (long v : VALUES) {
115      for (int i = 0; i < 100; i++) {
116        h.add(v, 1);
117      }
118    }
119    // Add something way out there to make sure it doesn't throw off the counts.
120    h.add(Integer.MAX_VALUE, 1);
121
122    assertEquals(100, h.getNumAtOrBelow(1));
123    assertEquals(200, h.getNumAtOrBelow(11));
124    assertEquals(601, h.getNumAtOrBelow(Long.MAX_VALUE));
125  }
126
127
128  @Test
129  public void testSameValues() {
130    FastLongHistogram hist = new FastLongHistogram(100);
131
132    hist.add(50, 100);
133
134    hist.snapshotAndReset();
135    doTestUniform(hist);
136  }
137}