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