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