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 */
16package androidx.work.impl.constraints.trackers;
17
18
19import static org.hamcrest.CoreMatchers.is;
20import static org.hamcrest.CoreMatchers.nullValue;
21import static org.hamcrest.MatcherAssert.assertThat;
22import static org.mockito.ArgumentMatchers.any;
23import static org.mockito.ArgumentMatchers.isNull;
24import static org.mockito.Mockito.mock;
25import static org.mockito.Mockito.times;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.verifyNoMoreInteractions;
28import static org.mockito.Mockito.when;
29
30import android.content.BroadcastReceiver;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
34import android.os.BatteryManager;
35import android.support.test.filters.SmallTest;
36import android.support.test.runner.AndroidJUnit4;
37
38import androidx.work.impl.constraints.ConstraintListener;
39
40import org.junit.Before;
41import org.junit.Test;
42import org.junit.runner.RunWith;
43
44@RunWith(AndroidJUnit4.class)
45public class BatteryNotLowTrackerTest {
46
47    private static final int PLUGGED_IN = BatteryManager.BATTERY_PLUGGED_AC;
48    private static final int NOT_PLUGGED_IN = BatteryNotLowTracker.BATTERY_PLUGGED_NONE;
49    private static final int KNOWN_STATUS = BatteryManager.BATTERY_STATUS_CHARGING;
50    private static final int UNKNOWN_STATUS = BatteryManager.BATTERY_STATUS_UNKNOWN;
51    private static final float AT_LOW_PERCENTAGE = BatteryNotLowTracker.BATTERY_LOW_PERCENTAGE;
52    private static final float ABOVE_LOW_PERCENTAGE =
53            BatteryNotLowTracker.BATTERY_LOW_PERCENTAGE + 0.01f;
54
55    private Context mMockContext;
56    private BatteryNotLowTracker mTracker;
57    private ConstraintListener<Boolean> mListener;
58
59    @Before
60    public void setUp() {
61        mMockContext = mock(Context.class);
62        when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
63
64        mTracker = new BatteryNotLowTracker(mMockContext);
65        mListener = mock(ConstraintListener.class);
66    }
67
68    private void mockContextReturns(Intent expectedIntent) {
69        when(mMockContext.registerReceiver((BroadcastReceiver) isNull(),
70                any(IntentFilter.class))).thenReturn(expectedIntent);
71    }
72
73    private Intent createBatteryChangedIntent(int plugged, int status, float percent) {
74        int scale = 100;
75        int level = (int) (scale * percent);
76
77        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
78        intent.putExtra(BatteryManager.EXTRA_PLUGGED, plugged);
79        intent.putExtra(BatteryManager.EXTRA_STATUS, status);
80        intent.putExtra(BatteryManager.EXTRA_LEVEL, level);
81        intent.putExtra(BatteryManager.EXTRA_SCALE, scale);
82        return intent;
83    }
84
85    private void testGetInitialStateHelper(
86            int plugged, int status, float percentage, boolean expectedBatteryNotLow) {
87        mockContextReturns(createBatteryChangedIntent(plugged, status, percentage));
88        assertThat(mTracker.getInitialState(), is(expectedBatteryNotLow));
89    }
90
91    @Test
92    @SmallTest
93    public void testGetInitialState_nullIntent() {
94        mockContextReturns(null);
95        assertThat(mTracker.getInitialState(), is(nullValue()));
96    }
97
98    @Test
99    @SmallTest
100    public void testGetInitialState_notPlugged_knownStatus_atBatteryLowPercentage() {
101        testGetInitialStateHelper(NOT_PLUGGED_IN, KNOWN_STATUS, AT_LOW_PERCENTAGE, false);
102    }
103
104    @Test
105    @SmallTest
106    public void testGetInitialState_plugged_knownStatus_aboveBatteryLowPercentage() {
107        testGetInitialStateHelper(PLUGGED_IN, KNOWN_STATUS, ABOVE_LOW_PERCENTAGE, true);
108    }
109
110    @Test
111    @SmallTest
112    public void testGetInitialState_plugged_knownStatus_atBatteryLowPercentage() {
113        testGetInitialStateHelper(PLUGGED_IN, KNOWN_STATUS, AT_LOW_PERCENTAGE, true);
114    }
115
116    @Test
117    @SmallTest
118    public void testGetInitialState_plugged_unknownStatus_aboveBatteryLowPercentage() {
119        testGetInitialStateHelper(PLUGGED_IN, UNKNOWN_STATUS, ABOVE_LOW_PERCENTAGE, true);
120    }
121
122    @Test
123    @SmallTest
124    public void testGetInitialState_plugged_unknownStatus_atBatteryLowPercentage() {
125        testGetInitialStateHelper(PLUGGED_IN, UNKNOWN_STATUS, AT_LOW_PERCENTAGE, true);
126    }
127
128    @Test
129    @SmallTest
130    public void testGetInitialState_notPlugged_knownStatus_aboveBatteryLowPercentage() {
131        testGetInitialStateHelper(NOT_PLUGGED_IN, KNOWN_STATUS, ABOVE_LOW_PERCENTAGE, true);
132    }
133
134    @Test
135    @SmallTest
136    public void testGetInitialState_notPlugged_unknownStatus_aboveBatteryLowPercentage() {
137        testGetInitialStateHelper(NOT_PLUGGED_IN, UNKNOWN_STATUS, ABOVE_LOW_PERCENTAGE, true);
138    }
139
140    @Test
141    @SmallTest
142    public void testGetInitialState_notPlugged_unknownStatus_atBatteryLowPercentage() {
143        testGetInitialStateHelper(NOT_PLUGGED_IN, UNKNOWN_STATUS, AT_LOW_PERCENTAGE, true);
144    }
145
146    @Test
147    @SmallTest
148    public void testGetIntentFilter() {
149        IntentFilter intentFilter = mTracker.getIntentFilter();
150        assertThat(intentFilter.hasAction(Intent.ACTION_BATTERY_OKAY), is(true));
151        assertThat(intentFilter.hasAction(Intent.ACTION_BATTERY_LOW), is(true));
152        assertThat(intentFilter.countActions(), is(2));
153    }
154
155    @Test
156    @SmallTest
157    public void testOnBroadcastReceive_invalidIntentAction_doesNotNotifyListeners() {
158        mockContextReturns(
159                createBatteryChangedIntent(PLUGGED_IN, KNOWN_STATUS, ABOVE_LOW_PERCENTAGE));
160        mTracker.addListener(mListener);
161        verify(mListener).onConstraintChanged(true);
162
163        mTracker.onBroadcastReceive(mMockContext, new Intent("INVALID"));
164        verifyNoMoreInteractions(mListener);
165    }
166
167    @Test
168    @SmallTest
169    public void testOnBroadcastReceive_notifiesListeners() {
170        mockContextReturns(
171                createBatteryChangedIntent(NOT_PLUGGED_IN, KNOWN_STATUS, AT_LOW_PERCENTAGE));
172        mTracker.addListener(mListener);
173        verify(mListener).onConstraintChanged(false);
174
175        mTracker.onBroadcastReceive(mMockContext, new Intent(Intent.ACTION_BATTERY_OKAY));
176        verify(mListener).onConstraintChanged(true);
177        mTracker.onBroadcastReceive(mMockContext, new Intent(Intent.ACTION_BATTERY_LOW));
178        verify(mListener, times(2)).onConstraintChanged(false);
179    }
180}
181