1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi.util; 18 19 import static org.hamcrest.core.IsEqual.equalTo; 20 21 import android.util.SparseIntArray; 22 23 import org.junit.Before; 24 import org.junit.Rule; 25 import org.junit.Test; 26 import org.junit.rules.ErrorCollector; 27 import org.mockito.MockitoAnnotations; 28 29 /** 30 * Unit test harness for MetricsUtils. 31 */ 32 public class MetricsUtilsTest { 33 @Rule 34 public ErrorCollector collector = new ErrorCollector(); 35 36 /** 37 * Pre-test configuration. Initialize and install mocks. 38 */ 39 @Before 40 public void setUp() throws Exception { 41 MockitoAnnotations.initMocks(this); 42 } 43 44 /** 45 * Histogram of following buckets, start[i] = 0 + 1 * 10^i with 9 sub-buckets, i=0,...,5 46 * 1 - 10: 9 sub-buckets each of width 1 47 * 10 - 100: 10 48 * 100 - 10e3: 10^2 49 * 10e3 - 10e4: 10^3 50 * 10e4 - 10e5: 10^4 51 * 10e5 - 10e6: 10^5 52 */ 53 private static final MetricsUtils.LogHistParms HIST1 = new MetricsUtils.LogHistParms(0, 1, 10, 54 9, 6); 55 56 /** 57 * Histogram of following buckets, start[i] = -20 + 2 * 5^i with 40 sub-buckets, i=0,...,2 58 * -18 - -10: 40 sub-bucket each of width 0.2 59 * -10 - 30: 1 60 * 30 - 230: 5 61 */ 62 private static final MetricsUtils.LogHistParms HIST2 = new MetricsUtils.LogHistParms(-20, 2, 5, 63 40, 3); 64 65 // Linear histogram of following buckets: 66 // <10 67 // [10, 30) 68 // [30, 60) 69 // [60, 100) 70 // >100 71 private static final int[] HIST_LINEAR = {10, 30, 60, 100}; 72 73 /** 74 * Validate that a set of values are bucketed correctly into the histogram, and that they are 75 * converted to a primitive proto-buffer array correctly. 76 */ 77 @Test 78 public void testHistBucketing() { 79 SparseIntArray hist1 = new SparseIntArray(); 80 SparseIntArray hist2 = new SparseIntArray(); 81 82 bucketValueAndVerify("HIST1: x=", -5, hist1, HIST1, 0, 1); 83 bucketValueAndVerify("HIST1: x=", 0, hist1, HIST1, 0, 2); 84 bucketValueAndVerify("HIST1: x=", 1, hist1, HIST1, 0, 3); 85 bucketValueAndVerify("HIST1: x=", 9, hist1, HIST1, 8, 1); 86 bucketValueAndVerify("HIST1: x=", 10, hist1, HIST1, 9, 1); 87 bucketValueAndVerify("HIST1: x=", 99, hist1, HIST1, 17, 1); 88 bucketValueAndVerify("HIST1: x=", 100, hist1, HIST1, 18, 1); 89 bucketValueAndVerify("HIST1: x=", 989, hist1, HIST1, 26, 1); 90 bucketValueAndVerify("HIST1: x=", 990, hist1, HIST1, 26, 2); 91 bucketValueAndVerify("HIST1: x=", 999, hist1, HIST1, 26, 3); 92 bucketValueAndVerify("HIST1: x=", 1000, hist1, HIST1, 27, 1); 93 bucketValueAndVerify("HIST1: x=", 9899, hist1, HIST1, 35, 1); 94 bucketValueAndVerify("HIST1: x=", 9900, hist1, HIST1, 35, 2); 95 bucketValueAndVerify("HIST1: x=", 9999, hist1, HIST1, 35, 3); 96 bucketValueAndVerify("HIST1: x=", 10000, hist1, HIST1, 36, 1); 97 bucketValueAndVerify("HIST1: x=", 98999, hist1, HIST1, 44, 1); 98 bucketValueAndVerify("HIST1: x=", 99000, hist1, HIST1, 44, 2); 99 bucketValueAndVerify("HIST1: x=", 99999, hist1, HIST1, 44, 3); 100 bucketValueAndVerify("HIST1: x=", 100000, hist1, HIST1, 45, 1); 101 bucketValueAndVerify("HIST1: x=", 989999, hist1, HIST1, 53, 1); 102 bucketValueAndVerify("HIST1: x=", 990000, hist1, HIST1, 53, 2); 103 bucketValueAndVerify("HIST1: x=", 999999, hist1, HIST1, 53, 3); 104 bucketValueAndVerify("HIST1: x=", 1000000, hist1, HIST1, 53, 4); 105 bucketValueAndVerify("HIST1: x=", 1000001, hist1, HIST1, 53, 5); 106 bucketValueAndVerify("HIST1: x=", 5000000, hist1, HIST1, 53, 6); 107 bucketValueAndVerify("HIST1: x=", 10000000, hist1, HIST1, 53, 7); 108 109 MetricsUtils.GenericBucket[] phb1 = MetricsUtils.logHistogramToGenericBuckets(hist1, HIST1); 110 collector.checkThat("Number of buckets #1", phb1.length, equalTo(hist1.size())); 111 validateProtoHistBucket("Bucket1[0]", phb1[0], 1, 2, 3); 112 validateProtoHistBucket("Bucket1[1]", phb1[1], 9, 10, 1); 113 validateProtoHistBucket("Bucket1[2]", phb1[2], 10, 20, 1); 114 validateProtoHistBucket("Bucket1[3]", phb1[3], 90, 100, 1); 115 validateProtoHistBucket("Bucket1[4]", phb1[4], 100, 200, 1); 116 validateProtoHistBucket("Bucket1[5]", phb1[5], 900, 1000, 3); 117 validateProtoHistBucket("Bucket1[6]", phb1[6], 1000, 2000, 1); 118 validateProtoHistBucket("Bucket1[7]", phb1[7], 9000, 10000, 3); 119 validateProtoHistBucket("Bucket1[8]", phb1[8], 10000, 20000, 1); 120 validateProtoHistBucket("Bucket1[9]", phb1[9], 90000, 100000, 3); 121 validateProtoHistBucket("Bucket1[10]", phb1[10], 100000, 200000, 1); 122 validateProtoHistBucket("Bucket1[11]", phb1[11], 900000, 1000000, 7); 123 124 bucketValueAndVerify("HIST2: x=", -20, hist2, HIST2, 0, 1); 125 bucketValueAndVerify("HIST2: x=", -18, hist2, HIST2, 0, 2); 126 bucketValueAndVerify("HIST2: x=", -17, hist2, HIST2, 5, 1); 127 bucketValueAndVerify("HIST2: x=", -11, hist2, HIST2, 35, 1); 128 bucketValueAndVerify("HIST2: x=", -10, hist2, HIST2, 40, 1); 129 bucketValueAndVerify("HIST2: x=", 29, hist2, HIST2, 79, 1); 130 bucketValueAndVerify("HIST2: x=", 30, hist2, HIST2, 80, 1); 131 bucketValueAndVerify("HIST2: x=", 229, hist2, HIST2, 119, 1); 132 bucketValueAndVerify("HIST2: x=", 230, hist2, HIST2, 119, 2); 133 bucketValueAndVerify("HIST2: x=", 300, hist2, HIST2, 119, 3); 134 bucketValueAndVerify("HIST2: x=", 1000000, hist2, HIST2, 119, 4); 135 136 MetricsUtils.GenericBucket[] phb2 = MetricsUtils.logHistogramToGenericBuckets(hist2, HIST2); 137 collector.checkThat("Number of buckets #2", phb2.length, equalTo(hist2.size())); 138 validateProtoHistBucket("Bucket2[0]", phb2[0], -18, -17, 2); 139 validateProtoHistBucket("Bucket2[1]", phb2[1], -17, -16, 1); 140 validateProtoHistBucket("Bucket2[2]", phb2[2], -11, -10, 1); 141 validateProtoHistBucket("Bucket2[3]", phb2[3], -10, -9, 1); 142 validateProtoHistBucket("Bucket2[4]", phb2[4], 29, 30, 1); 143 validateProtoHistBucket("Bucket2[5]", phb2[5], 30, 35, 1); 144 validateProtoHistBucket("Bucket2[6]", phb2[6], 225, 230, 4); 145 } 146 147 /** 148 * Validate that a set of values are bucketed correctly into the linear histogram, and that 149 * they are converted to a primitive proto-buffer array correctly. 150 */ 151 @Test 152 public void testLinearHistBucketing() { 153 SparseIntArray hist = new SparseIntArray(); 154 155 bucketValueAndVerify("HIST_LINEAR: x=", -5, hist, HIST_LINEAR, 0, 1); 156 bucketValueAndVerify("HIST_LINEAR: x=", 0, hist, HIST_LINEAR, 0, 2); 157 bucketValueAndVerify("HIST_LINEAR: x=", 1, hist, HIST_LINEAR, 0, 3); 158 bucketValueAndVerify("HIST_LINEAR: x=", 9, hist, HIST_LINEAR, 0, 4); 159 bucketValueAndVerify("HIST_LINEAR: x=", 10, hist, HIST_LINEAR, 1, 1); 160 bucketValueAndVerify("HIST_LINEAR: x=", 20, hist, HIST_LINEAR, 1, 2); 161 bucketValueAndVerify("HIST_LINEAR: x=", 30, hist, HIST_LINEAR, 2, 1); 162 bucketValueAndVerify("HIST_LINEAR: x=", 40, hist, HIST_LINEAR, 2, 2); 163 bucketValueAndVerify("HIST_LINEAR: x=", 50, hist, HIST_LINEAR, 2, 3); 164 bucketValueAndVerify("HIST_LINEAR: x=", 60, hist, HIST_LINEAR, 3, 1); 165 bucketValueAndVerify("HIST_LINEAR: x=", 70, hist, HIST_LINEAR, 3, 2); 166 bucketValueAndVerify("HIST_LINEAR: x=", 80, hist, HIST_LINEAR, 3, 3); 167 bucketValueAndVerify("HIST_LINEAR: x=", 90, hist, HIST_LINEAR, 3, 4); 168 bucketValueAndVerify("HIST_LINEAR: x=", 100, hist, HIST_LINEAR, 4, 1); 169 bucketValueAndVerify("HIST_LINEAR: x=", 110, hist, HIST_LINEAR, 4, 2); 170 bucketValueAndVerify("HIST_LINEAR: x=", 98999, hist, HIST_LINEAR, 4, 3); 171 172 MetricsUtils.GenericBucket[] phb = MetricsUtils.linearHistogramToGenericBuckets(hist, 173 HIST_LINEAR); 174 collector.checkThat("Number of buckets", phb.length, equalTo(hist.size())); 175 validateProtoHistBucket("Bucket[0]", phb[0], Integer.MIN_VALUE, 10, 4); 176 validateProtoHistBucket("Bucket[1]", phb[1], 10, 30, 2); 177 validateProtoHistBucket("Bucket[2]", phb[2], 30, 60, 3); 178 validateProtoHistBucket("Bucket[3]", phb[3], 60, 100, 4); 179 validateProtoHistBucket("Bucket[4]", phb[4], 100, Integer.MAX_VALUE, 3); 180 } 181 182 // utilities 183 184 private void bucketValueAndVerify(String prefix, long value, SparseIntArray h, 185 MetricsUtils.LogHistParms hp, int expectedKey, int expectedValue) { 186 MetricsUtils.addValueToLogHistogram(value, h, hp); 187 collector.checkThat(prefix + value, h.get(expectedKey), equalTo(expectedValue)); 188 } 189 190 private void bucketValueAndVerify(String prefix, int value, SparseIntArray h, int[] hp, 191 int expectedKey, int expectedValue) { 192 MetricsUtils.addValueToLinearHistogram(value, h, hp); 193 collector.checkThat(prefix + value, h.get(expectedKey), equalTo(expectedValue)); 194 } 195 196 private void validateProtoHistBucket(String prefix, MetricsUtils.GenericBucket bucket, 197 long start, long end, int count) { 198 collector.checkThat(prefix + ": start", bucket.start, equalTo(start)); 199 collector.checkThat(prefix + ": end", bucket.end, equalTo(end)); 200 collector.checkThat(prefix + ": count", bucket.count, equalTo(count)); 201 } 202 } 203