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 org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertTrue;
20 
21 import android.test.suitebuilder.annotation.SmallTest;
22 
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         assertUpdateTime(mTestStartTime);
46         assertUpdateTime(mTestStartTime - 1000L);
47     }
48 
49     @Test
testRunningTimeBackwardDoesntExplodeGet()50     public void testRunningTimeBackwardDoesntExplodeGet() throws Exception {
51         assertUpdateTime(mTestStartTime);
52         final float rate = mEstimator.getRate(mTestStartTime - 1000L);
53         assertFalse(Float.isInfinite(rate));
54         assertFalse(Float.isNaN(rate));
55     }
56 
57     @Test
testInstantaneousEventsDontExplodeUpdate()58     public void testInstantaneousEventsDontExplodeUpdate() throws Exception {
59         assertUpdateTime(mTestStartTime);
60         assertUpdateTime(mTestStartTime);
61     }
62 
63     @Test
testInstantaneousEventsDontExplodeGet()64     public void testInstantaneousEventsDontExplodeGet() throws Exception {
65         assertUpdateTime(mTestStartTime);
66         assertUpdateTime(mTestStartTime);
67         final float rate = mEstimator.getRate(mTestStartTime);
68         assertFalse(Float.isInfinite(rate));
69         assertFalse(Float.isNaN(rate));
70     }
71 
72     @Test
testInstantaneousBurstIsEstimatedUnderTwoPercent()73     public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception {
74         assertUpdateTime(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         assertLessThan("Rate", rate, 20f);
79     }
80 
81     @Test
testCompactBurstIsEstimatedUnderTwoPercent()82     public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception {
83         assertUpdateTime(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         assertLessThan("Rate", rate, 20f);
88     }
89 
90     @Test
testSustained1000HzBurstIsEstimatedOverNinetyPercent()91     public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception {
92         assertUpdateTime(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         assertGreaterThan("Rate", rate, 900f);
97     }
98 
99     @Test
testSustained100HzBurstIsEstimatedOverNinetyPercent()100     public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception {
101         assertUpdateTime(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         assertGreaterThan("Rate", rate, 90f);
107     }
108 
109     @Test
testRecoverQuicklyAfterSustainedBurst()110     public void testRecoverQuicklyAfterSustainedBurst() throws Exception {
111         assertUpdateTime(mTestStartTime);
112         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
113         long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz
114         final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later
115         assertLessThan("Rate", rate, 2f);
116     }
117 
118     @Test
testEstimateShouldNotOvershoot()119     public void testEstimateShouldNotOvershoot() throws Exception {
120         assertUpdateTime(mTestStartTime);
121         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
122         long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz
123         final float rate = mEstimator.getRate(nextEventTime);
124         assertLessThan("Rate", rate, 1000f);
125     }
126 
127     @Test
testGetRateWithoutUpdate()128     public void testGetRateWithoutUpdate() throws Exception {
129         final float rate = mEstimator.getRate(mTestStartTime);
130         assertLessThan("Rate", rate, 0.1f);
131     }
132 
133     @Test
testGetRateWithOneUpdate()134     public void testGetRateWithOneUpdate() throws Exception {
135         assertUpdateTime(mTestStartTime);
136         final float rate = mEstimator.getRate(mTestStartTime+1);
137         assertLessThan("Rate", rate, 1f);
138     }
139 
assertLessThan(String label, float a, float b)140     private void assertLessThan(String label, float a, float b)  {
141         assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a <= b);
142     }
143 
assertGreaterThan(String label, float a, float b)144     private void assertGreaterThan(String label, float a, float b)  {
145         assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a >= b);
146     }
147 
148     /** @returns the next event time. */
postEvents(long start, long dt, int num)149     private long postEvents(long start, long dt, int num) {
150         long time = start;
151         for (int i = 0; i < num; i++) {
152             mEstimator.update(time);
153             time += dt;
154         }
155         return time;
156     }
157 
assertUpdateTime(long time)158     private void assertUpdateTime(long time) {
159         final float rate = mEstimator.update(time);
160         assertFalse(Float.isInfinite(rate));
161         assertFalse(Float.isNaN(rate));
162     }
163 }
164