1/*
2 * Copyright (C) 2017 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
17package com.android.internal.os;
18
19import static android.os.BatteryStats.STATS_CURRENT;
20import static android.os.BatteryStats.STATS_SINCE_CHARGED;
21import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED;
22
23import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray;
24import static com.android.internal.os.BatteryStatsImpl.TimeBase;
25
26import static org.junit.Assert.assertTrue;
27import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.verifyNoMoreInteractions;
29import static org.mockito.Mockito.verifyZeroInteractions;
30import static org.mockito.Mockito.when;
31
32import android.os.Parcel;
33import android.support.test.filters.SmallTest;
34import android.support.test.runner.AndroidJUnit4;
35
36import org.junit.Before;
37import org.junit.Test;
38import org.junit.runner.RunWith;
39import org.mockito.Mock;
40import org.mockito.Mockito;
41import org.mockito.MockitoAnnotations;
42
43import java.util.Arrays;
44
45/**
46 * Test class for {@link BatteryStatsImpl.LongSamplingCounterArray}.
47 *
48 * To run the tests, use
49 *
50 * runtest -c com.android.internal.os.LongSamplingCounterArrayTest frameworks-core
51 *
52 * or the following steps:
53 *
54 * Build: m FrameworksCoreTests
55 * Install: adb install -r \
56 *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
57 * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \
58 *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
59 */
60@SmallTest
61@RunWith(AndroidJUnit4.class)
62public class LongSamplingCounterArrayTest {
63
64    private static final long[] COUNTS = {1111, 2222, 3333, 4444};
65    private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888};
66    private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777};
67    private static final long[] ZEROES = {0, 0, 0, 0};
68
69    @Mock private TimeBase mTimeBase;
70    private LongSamplingCounterArray mCounterArray;
71
72    @Before
73    public void setUp() {
74        MockitoAnnotations.initMocks(this);
75        mCounterArray = new LongSamplingCounterArray(mTimeBase);
76        Mockito.reset(mTimeBase);
77    }
78
79    @Test
80    public void testReadWriteParcel() {
81        final Parcel parcel = Parcel.obtain();
82        initializeCounterArrayWithDefaultValues();
83        LongSamplingCounterArray.writeToParcel(parcel, mCounterArray);
84        parcel.setDataPosition(0);
85
86        // Now clear counterArray and verify values are read from parcel correctly.
87        updateCounts(null, null, null);
88        mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase);
89        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
90        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
91        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
92                "Unexpected unpluggedCounts");
93        parcel.recycle();
94    }
95
96    @Test
97    public void testReadWriteSummaryParcel() {
98        final Parcel parcel = Parcel.obtain();
99        initializeCounterArrayWithDefaultValues();
100        LongSamplingCounterArray.writeSummaryToParcelLocked(parcel, mCounterArray);
101        parcel.setDataPosition(0);
102
103        // Now clear counterArray and verify values are read from parcel correctly.
104        updateCounts(null, null, null);
105        mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase);
106        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
107        assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
108        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
109        parcel.recycle();
110    }
111
112    @Test
113    public void testOnTimeStarted() {
114        initializeCounterArrayWithDefaultValues();
115        mCounterArray.onTimeStarted(0, 0, 0);
116        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
117        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
118        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts,
119                "Unexpected unpluggedCounts");
120    }
121
122    @Test
123    public void testOnTimeStopped() {
124        initializeCounterArrayWithDefaultValues();
125        mCounterArray.onTimeStopped(0, 0, 0);
126        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
127        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
128        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
129                "Unexpected unpluggedCounts");
130    }
131
132    @Test
133    public void testGetCountsLocked() {
134        initializeCounterArrayWithDefaultValues();
135
136        when(mTimeBase.isRunning()).thenReturn(false);
137        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
138                "Unexpected values");
139        assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
140                mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
141        assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
142                mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");
143
144        when(mTimeBase.isRunning()).thenReturn(true);
145        assertArrayEquals(COUNTS, mCounterArray.getCountsLocked(STATS_SINCE_CHARGED),
146                "Unexpected values");
147        assertArrayEquals(subtract(COUNTS, LOADED_COUNTS),
148                mCounterArray.getCountsLocked(STATS_CURRENT), "Unexpected values");
149        assertArrayEquals(subtract(COUNTS, UNPLUGGED_COUNTS),
150                mCounterArray.getCountsLocked(STATS_SINCE_UNPLUGGED), "Unexpected values");
151    }
152
153    private long[] subtract(long[] val, long[] toSubtract) {
154        final long[] result = val.clone();
155        if (toSubtract != null) {
156            for (int i = val.length - 1; i >= 0; --i) {
157                result[i] -= toSubtract[i];
158            }
159        }
160        return result;
161    }
162
163    @Test
164    public void testAddCountLocked() {
165        updateCounts(null, null, null);
166        final long[] deltas = {123, 234, 345, 456};
167        when(mTimeBase.isRunning()).thenReturn(true);
168        mCounterArray.addCountLocked(deltas);
169        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
170        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
171        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
172
173        updateCounts(null, null, null);
174        mCounterArray.addCountLocked(deltas, false);
175        assertArrayEquals(null, mCounterArray.mCounts, "Unexpected counts");
176        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
177        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
178        mCounterArray.addCountLocked(deltas, true);
179        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
180        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
181        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
182
183        initializeCounterArrayWithDefaultValues();
184        final long[] newCounts = new long[deltas.length];
185        for (int i = 0; i < deltas.length; ++i) {
186            newCounts[i] = COUNTS[i] + deltas[i];
187        }
188        mCounterArray.addCountLocked(deltas);
189        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
190        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
191        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
192                "Unexpected unpluggedCounts");
193
194        initializeCounterArrayWithDefaultValues();
195        mCounterArray.addCountLocked(deltas, false);
196        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
197        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
198        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
199                "Unexpected unpluggedCounts");
200        mCounterArray.addCountLocked(deltas, true);
201        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
202        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
203        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
204                "Unexpected unpluggedCounts");
205    }
206
207    @Test
208    public void testReset() {
209        initializeCounterArrayWithDefaultValues();
210        // Test with detachIfReset=false
211        mCounterArray.reset(false /* detachIfReset */);
212        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
213        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
214        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
215        verifyZeroInteractions(mTimeBase);
216
217        initializeCounterArrayWithDefaultValues();
218        // Test with detachIfReset=true
219        mCounterArray.reset(true /* detachIfReset */);
220        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
221        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
222        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
223        verify(mTimeBase).remove(mCounterArray);
224        verifyNoMoreInteractions(mTimeBase);
225    }
226
227    @Test
228    public void testDetach() {
229        mCounterArray.detach();
230        verify(mTimeBase).remove(mCounterArray);
231        verifyNoMoreInteractions(mTimeBase);
232    }
233
234    private void initializeCounterArrayWithDefaultValues() {
235        updateCounts(COUNTS, LOADED_COUNTS, UNPLUGGED_COUNTS);
236    }
237
238    private void assertArrayEquals(long[] expected, long[] actual, String msg) {
239        assertTrue(msg + ", expected: " + Arrays.toString(expected)
240                + ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual));
241    }
242
243    private void updateCounts(long[] counts, long[] loadedCounts, long[] unpluggedCounts) {
244        mCounterArray.mCounts = counts == null ? null : counts.clone();
245        mCounterArray.mLoadedCounts = loadedCounts == null ? null : loadedCounts.clone();
246        mCounterArray.mUnpluggedCounts = unpluggedCounts == null ? null : unpluggedCounts.clone();
247    }
248}
249