1 /* 2 * Copyright (C) 2016 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 package com.android.server.notification; 17 18 import static com.google.common.truth.Truth.assertThat; 19 20 import static java.util.concurrent.TimeUnit.HOURS; 21 22 import androidx.test.filters.SmallTest; 23 import androidx.test.runner.AndroidJUnit4; 24 25 import com.android.server.UiServiceTestCase; 26 27 import org.junit.Before; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 31 @SmallTest 32 @RunWith(AndroidJUnit4.class) 33 public class RateEstimatorTest extends UiServiceTestCase { 34 private long mTestStartTime; 35 private RateEstimator mEstimator; 36 37 @Before setUp()38 public void setUp() { 39 mTestStartTime = 1225731600000L; 40 mEstimator = new RateEstimator(); 41 } 42 43 @Test testRunningTimeBackwardDoesntExplodeUpdate()44 public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception { 45 updateAndVerifyRate(mTestStartTime); 46 updateAndVerifyRate(mTestStartTime - 1000L); 47 } 48 49 @Test testRunningTimeBackwardDoesntExplodeGet()50 public void testRunningTimeBackwardDoesntExplodeGet() throws Exception { 51 updateAndVerifyRate(mTestStartTime); 52 final float rate = mEstimator.getRate(mTestStartTime - 1000L); 53 assertThat(rate).isFinite(); 54 } 55 56 @Test testInstantaneousEventsDontExplodeUpdate()57 public void testInstantaneousEventsDontExplodeUpdate() throws Exception { 58 updateAndVerifyRate(mTestStartTime); 59 updateAndVerifyRate(mTestStartTime); 60 } 61 62 @Test testInstantaneousEventsDontExplodeGet()63 public void testInstantaneousEventsDontExplodeGet() throws Exception { 64 updateAndVerifyRate(mTestStartTime); 65 updateAndVerifyRate(mTestStartTime); 66 final float rate = mEstimator.getRate(mTestStartTime); 67 assertThat(rate).isFinite(); 68 } 69 70 @Test testInstantaneousBurstIsEstimatedUnderTwoPercent()71 public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception { 72 updateAndVerifyRate(mTestStartTime); 73 long eventStart = mTestStartTime + 1000; // start event a long time after initialization 74 long nextEventTime = postEvents(eventStart, 0, 5); // five events at \inf 75 final float rate = mEstimator.getRate(nextEventTime); 76 assertThat(rate).isLessThan(20f); 77 } 78 79 @Test testCompactBurstIsEstimatedUnderTwoPercent()80 public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception { 81 updateAndVerifyRate(mTestStartTime); 82 long eventStart = mTestStartTime + 1000; // start event a long time after initialization 83 long nextEventTime = postEvents(eventStart, 1, 5); // five events at 1000Hz 84 final float rate = mEstimator.getRate(nextEventTime); 85 assertThat(rate).isLessThan(20f); 86 } 87 88 @Test testSustained1000HzBurstIsEstimatedOverNinetyPercent()89 public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception { 90 updateAndVerifyRate(mTestStartTime); 91 long eventStart = mTestStartTime + 1000; // start event a long time after initialization 92 long nextEventTime = postEvents(eventStart, 1, 100); // one hundred events at 1000Hz 93 final float rate = mEstimator.getRate(nextEventTime); 94 assertThat(rate).isGreaterThan(900f); 95 } 96 97 @Test testSustained100HzBurstIsEstimatedOverNinetyPercent()98 public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception { 99 updateAndVerifyRate(mTestStartTime); 100 long eventStart = mTestStartTime + 1000; // start event a long time after initialization 101 long nextEventTime = postEvents(eventStart, 10, 100); // one hundred events at 100Hz 102 final float rate = mEstimator.getRate(nextEventTime); 103 104 assertThat(rate).isGreaterThan(90f); 105 } 106 107 @Test testRecoverQuicklyAfterSustainedBurst()108 public void testRecoverQuicklyAfterSustainedBurst() throws Exception { 109 updateAndVerifyRate(mTestStartTime); 110 long eventStart = mTestStartTime + 1000; // start event a long time after initialization 111 long nextEventTime = postEvents(eventStart, 10, 1000); // one thousand events at 100Hz 112 final float rate = mEstimator.getRate(nextEventTime + 5000L); // five seconds later 113 assertThat(rate).isLessThan(2f); 114 } 115 116 @Test testEstimateShouldNotOvershoot()117 public void testEstimateShouldNotOvershoot() throws Exception { 118 updateAndVerifyRate(mTestStartTime); 119 long eventStart = mTestStartTime + 1000; // start event a long time after initialization 120 long nextEventTime = postEvents(eventStart, 1, 5000); // five thousand events at 1000Hz 121 final float rate = mEstimator.getRate(nextEventTime); 122 assertThat(rate).isAtMost(1000f); 123 } 124 125 @Test testGetRateWithoutUpdate()126 public void testGetRateWithoutUpdate() throws Exception { 127 final float rate = mEstimator.getRate(mTestStartTime); 128 assertThat(rate).isLessThan(0.1f); 129 } 130 131 @Test testGetRateWithOneUpdate()132 public void testGetRateWithOneUpdate() throws Exception { 133 updateAndVerifyRate(mTestStartTime); 134 final float rate = mEstimator.getRate(mTestStartTime+1); 135 assertThat(rate).isLessThan(1f); 136 } 137 138 @Test testEstimateCatchesUpQuickly()139 public void testEstimateCatchesUpQuickly() { 140 long nextEventTime = postEvents(mTestStartTime, 100, 30); // 30 events at 10Hz 141 142 final float firstBurstRate = mEstimator.getRate(nextEventTime); 143 assertThat(firstBurstRate).isWithin(2f).of(10); 144 145 nextEventTime += HOURS.toMillis(3); // 3 hours later... 146 nextEventTime = postEvents(nextEventTime, 100, 30); // same burst of 30 events at 10Hz 147 148 // Catching up. Rate is not yet 10, since we had a long period of inactivity... 149 float secondBurstRate = mEstimator.getRate(nextEventTime); 150 assertThat(secondBurstRate).isWithin(1f).of(6); 151 152 // ... but after a few more events, we are there. 153 nextEventTime = postEvents(nextEventTime, 100, 10); // 10 more events at 10Hz 154 secondBurstRate = mEstimator.getRate(nextEventTime); 155 assertThat(secondBurstRate).isWithin(1f).of(10); 156 } 157 158 /** @return the next event time. */ postEvents(long start, long dt, int num)159 private long postEvents(long start, long dt, int num) { 160 long time = start; 161 for (int i = 0; i < num; i++) { 162 mEstimator.update(time); 163 time += dt; 164 } 165 return time; 166 } 167 updateAndVerifyRate(long time)168 private void updateAndVerifyRate(long time) { 169 mEstimator.update(time); 170 assertThat(mEstimator.getRate(time)).isFinite(); 171 } 172 }