001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.statistic; 017 018import static org.junit.Assert.assertArrayEquals; 019import static org.junit.Assert.assertEquals; 020import static org.junit.Assert.assertNotNull; 021import static org.junit.Assert.assertTrue; 022import java.util.ArrayList; 023import java.util.LinkedList; 024import java.util.List; 025import java.util.Random; 026import org.junit.Test; 027import org.modeshape.common.i18n.MockI18n; 028import org.modeshape.common.logging.Logger; 029import org.modeshape.common.math.FloatOperations; 030import org.modeshape.common.math.MathOperations; 031import org.modeshape.common.text.Inflector; 032 033public class HistogramTest { 034 035 private Logger logger = Logger.getLogger(HistogramTest.class); 036 private Inflector inflector = Inflector.getInstance(); 037 038 public static <T extends Number> Histogram<T> createRandomHistogram( T minimum, 039 T maximum, 040 int numberOfValues, 041 MathOperations<T> ops ) { 042 List<T> values = new ArrayList<T>(); 043 Random rng = new Random(); 044 for (int i = 0; i != numberOfValues; ++i) { 045 T newValue = ops.random(minimum, maximum, rng); 046 values.add(newValue); 047 } 048 return new Histogram<T>(ops, values); 049 } 050 051 public static <T extends Number> void writeHistogramToLog( Logger logger, 052 Histogram<T> histogram, 053 int barLength, 054 String description ) { 055 logger.info(MockI18n.passthrough, description != null ? description : "Histogram:"); 056 List<String> barGraph = histogram.getTextGraph(barLength); 057 for (String line : barGraph) { 058 logger.debug(" " + line); 059 } 060 } 061 062 public <T extends Number> void assertBucketValueCount( Histogram<T> histogram, 063 long... values ) { 064 // CHECKSTYLE IGNORE check FOR NEXT 1 LINES 065 List<Histogram<T>.Bucket> buckets = histogram.getBuckets(); 066 // Check the number of buckets ... 067 assertEquals("The number of buckets didn't match expected number", values.length, buckets.size()); 068 // Check the number of values ... 069 for (int i = 0; i != buckets.size(); ++i) { 070 assertEquals("The " + inflector.ordinalize(i + 1) + " bucket didn't have the expected number of values", 071 values[i], 072 buckets.get(i).getNumberOfValues()); 073 } 074 } 075 076 @Test 077 public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSameOddNumberOfBuckets() { 078 Float[] values = {3.0f, 1.0f, 2.0f, 4.0f}; 079 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 080 gram.setBucketCount(3); 081 // HistogramTest.writeHistogramToLog(this.logger, gram, 0, 082 // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSameOddNumberOfBuckets"); 083 assertBucketValueCount(gram, 1, 1, 2); 084 } 085 086 @Test 087 public void shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets() { 088 Float[] values = {3.0f, 1.0f, 2.0f, 4.0f}; 089 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 090 gram.setBucketCount(4); 091 // HistogramTest.writeHistogramToLog(this.logger, gram, 0, 092 // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets"); 093 assertBucketValueCount(gram, 1, 1, 1, 1); 094 095 } 096 097 @Test 098 public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBuckets() { 099 Float[] values = {3.0f, 1.0f, 2.0f}; 100 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 101 gram.setBucketCount(2); 102 // HistogramTest.writeHistogramToLog(this.logger, gram, 0, 103 // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSameEvenNumberOfBuckets"); 104 assertBucketValueCount(gram, 1, 2); 105 } 106 107 @Test 108 public void shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSmallerNumberOfBuckets() { 109 Float[] values = {3.0f, 1.0f, 2.0f, 4.0f}; 110 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 111 gram.setBucketCount(2); 112 // HistogramTest.writeHistogramToLog(this.logger, gram, 0, 113 // "shouldCorrectlyPlaceAnEvenNumberOfFloatValuesIntoSmallerNumberOfBuckets"); 114 assertBucketValueCount(gram, 2, 2); 115 } 116 117 @Test 118 public void shouldReturnListOfBuckets() { 119 Float[] values = {3.0f, 1.0f, 2.0f, 4.0f}; 120 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 121 assertTrue(gram.getBuckets() instanceof LinkedList<?>); 122 } 123 124 @Test 125 public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumAndMaximumRanges() { 126 Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f}; 127 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 128 gram.setBucketCount(5); 129 // HistogramTest.writeHistogramToLog(this.logger, gram, 0, 130 // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumAndMaximumRanges"); 131 assertBucketValueCount(gram, 2, 2, 2, 2, 2); 132 } 133 134 @Test 135 public void shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumRanges() { 136 Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 9.999f}; 137 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 138 gram.setBucketCount(5); 139 // HistogramTest.writeHistogramToLog(this.logger, gram, 0, 140 // "shouldCorrectlyPlaceAnOddNumberOfFloatValuesIntoSmallerNumberOfBucketsWithMinimumRanges"); 141 assertBucketValueCount(gram, 2, 2, 2, 2, 2); 142 } 143 144 @Test 145 public void shouldCorrectlyConstructHistogramWithStandardDeviation() { 146 Float[] values = {3.0f, 1.0f, 2.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 9.999f, 3.1f, 3.2f, 3.3f, 3.21f, 3.22f, 3.33f}; 147 // RunningStatistics<Float> stats = new RunningStatistics<Float>(new FloatOperations()); 148 // for (Float value : values) stats.add(value); 149 // System.out.println(stats); 150 Histogram<Float> gram = new Histogram<Float>(new FloatOperations(), values); 151 gram.setBucketCount(6); 152 gram.setStrategy(3.315f, 2.52367f, 1); 153 154 HistogramTest.writeHistogramToLog(this.logger, gram, 0, "shouldCorrectlyConstructHistogramWithStandardDeviation"); 155 assertBucketValueCount(gram, 1, 1, 7, 1, 1, 5); 156 } 157 158 @Test 159 public void shouldCorrectlyPlace1000RandomFloatValues() { 160 Histogram<Float> gram = createRandomHistogram(10.0f, 100.0f, 1000, new FloatOperations()); 161 // gram.setDesiredRange(0.0f,100.0f); 162 HistogramTest.writeHistogramToLog(this.logger, 163 gram, 164 0, 165 "Histogram of 1000 random float values in " + gram.getBucketCount() + " buckets: "); 166 } 167 168 @Test 169 public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualFloats() { 170 List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(), 10.0f, 20.0f, 5.0f, 25.0f, 12, 3); 171 assertNotNull(boundaries); 172 assertEquals(13, boundaries.size()); 173 Float[] expectedBoundaries = {5.0f, 10.0f, 11f, 12f, 13f, 14f, 15f, 16f, 17f, 18f, 19f, 20f, 25f}; 174 assertArrayEquals(expectedBoundaries, boundaries.toArray(new Float[boundaries.size()])); 175 } 176 177 @Test 178 public void shouldCorrectlyConstructBoundariesWithWindowSmallerThanActualNarrowlyVaryingFloats() { 179 List<Float> boundaries = Histogram.getBucketBoundaries(new FloatOperations(), 180 10.00020f, 181 10.00030f, 182 10.00011f, 183 10.00050f, 184 12, 185 3); 186 assertNotNull(boundaries); 187 assertEquals(13, boundaries.size()); 188 assertEquals(10.00011f, boundaries.get(0), 0.00001f); 189 assertEquals(10.00020f, boundaries.get(1), 0.00001f); 190 assertEquals(10.00021f, boundaries.get(2), 0.00001f); 191 assertEquals(10.00022f, boundaries.get(3), 0.00001f); 192 assertEquals(10.00023f, boundaries.get(4), 0.00001f); 193 assertEquals(10.00024f, boundaries.get(5), 0.00001f); 194 assertEquals(10.00025f, boundaries.get(6), 0.00001f); 195 assertEquals(10.00026f, boundaries.get(7), 0.00001f); 196 assertEquals(10.00027f, boundaries.get(8), 0.00001f); 197 assertEquals(10.00028f, boundaries.get(9), 0.00001f); 198 assertEquals(10.00029f, boundaries.get(10), 0.00001f); 199 assertEquals(10.00030f, boundaries.get(11), 0.00001f); 200 assertEquals(10.00050f, boundaries.get(12), 0.00001f); 201 } 202 203}