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