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 android.support.test.runner.AndroidJUnit4;
19 import android.test.suitebuilder.annotation.SmallTest;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.assertFalse;
26 
27 import com.android.server.UiServiceTestCase;
28 
29 @SmallTest
30 @RunWith(AndroidJUnit4.class)
31 public class RateEstimatorTest extends UiServiceTestCase {
32     private long mTestStartTime;
33     private RateEstimator mEstimator;
34 
35     @Before
setUp()36     public void setUp() {
37         mTestStartTime = 1225731600000L;
38         mEstimator = new RateEstimator();
39     }
40 
41     @Test
testRunningTimeBackwardDoesntExplodeUpdate()42     public void testRunningTimeBackwardDoesntExplodeUpdate() throws Exception {
43         assertUpdateTime(mTestStartTime);
44         assertUpdateTime(mTestStartTime - 1000L);
45     }
46 
47     @Test
testRunningTimeBackwardDoesntExplodeGet()48     public void testRunningTimeBackwardDoesntExplodeGet() throws Exception {
49         assertUpdateTime(mTestStartTime);
50         final float rate = mEstimator.getRate(mTestStartTime - 1000L);
51         assertFalse(Float.isInfinite(rate));
52         assertFalse(Float.isNaN(rate));
53     }
54 
55     @Test
testInstantaneousEventsDontExplodeUpdate()56     public void testInstantaneousEventsDontExplodeUpdate() throws Exception {
57         assertUpdateTime(mTestStartTime);
58         assertUpdateTime(mTestStartTime);
59     }
60 
61     @Test
testInstantaneousEventsDontExplodeGet()62     public void testInstantaneousEventsDontExplodeGet() throws Exception {
63         assertUpdateTime(mTestStartTime);
64         assertUpdateTime(mTestStartTime);
65         final float rate = mEstimator.getRate(mTestStartTime);
66         assertFalse(Float.isInfinite(rate));
67         assertFalse(Float.isNaN(rate));
68     }
69 
70     @Test
testInstantaneousBurstIsEstimatedUnderTwoPercent()71     public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception {
72         assertUpdateTime(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         assertLessThan("Rate", rate, 20f);
77     }
78 
79     @Test
testCompactBurstIsEstimatedUnderTwoPercent()80     public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception {
81         assertUpdateTime(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         assertLessThan("Rate", rate, 20f);
86     }
87 
88     @Test
testSustained1000HzBurstIsEstimatedOverNinetyPercent()89     public void testSustained1000HzBurstIsEstimatedOverNinetyPercent() throws Exception {
90         assertUpdateTime(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         assertGreaterThan("Rate", rate, 900f);
95     }
96 
97     @Test
testSustained100HzBurstIsEstimatedOverNinetyPercent()98     public void testSustained100HzBurstIsEstimatedOverNinetyPercent() throws Exception {
99         assertUpdateTime(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         assertGreaterThan("Rate", rate, 90f);
105     }
106 
107     @Test
testRecoverQuicklyAfterSustainedBurst()108     public void testRecoverQuicklyAfterSustainedBurst() throws Exception {
109         assertUpdateTime(mTestStartTime);
110         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
111         long nextEventTime = postEvents(eventStart, 10, 1000); // one hundred events at 100Hz
112         final float rate = mEstimator.getRate(nextEventTime + 5000L); // two seconds later
113         assertLessThan("Rate", rate, 2f);
114     }
115 
116     @Test
testEstimateShouldNotOvershoot()117     public void testEstimateShouldNotOvershoot() throws Exception {
118         assertUpdateTime(mTestStartTime);
119         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
120         long nextEventTime = postEvents(eventStart, 1, 1000); // one thousand events at 1000Hz
121         final float rate = mEstimator.getRate(nextEventTime);
122         assertLessThan("Rate", rate, 1000f);
123     }
124 
125     @Test
testGetRateWithoutUpdate()126     public void testGetRateWithoutUpdate() throws Exception {
127         final float rate = mEstimator.getRate(mTestStartTime);
128         assertLessThan("Rate", rate, 0.1f);
129     }
130 
131     @Test
testGetRateWithOneUpdate()132     public void testGetRateWithOneUpdate() throws Exception {
133         assertUpdateTime(mTestStartTime);
134         final float rate = mEstimator.getRate(mTestStartTime+1);
135         assertLessThan("Rate", rate, 1f);
136     }
137 
assertLessThan(String label, float a, float b)138     private void assertLessThan(String label, float a, float b)  {
139         assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a <= b);
140     }
141 
assertGreaterThan(String label, float a, float b)142     private void assertGreaterThan(String label, float a, float b)  {
143         assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a >= b);
144     }
145 
146     /** @returns the next event time. */
postEvents(long start, long dt, int num)147     private long postEvents(long start, long dt, int num) {
148         long time = start;
149         for (int i = 0; i < num; i++) {
150             mEstimator.update(time);
151             time += dt;
152         }
153         return time;
154     }
155 
assertUpdateTime(long time)156     private void assertUpdateTime(long time) {
157         final float rate = mEstimator.update(time);
158         assertFalse(Float.isInfinite(rate));
159         assertFalse(Float.isNaN(rate));
160     }
161 }
162