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