1 /*
2  * Copyright 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 
17 package com.android.managedprovisioning.provisioning;
18 
19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
20 
21 import static org.junit.Assert.assertTrue;
22 import static org.mockito.Matchers.any;
23 import static org.mockito.Matchers.anyLong;
24 import static org.mockito.Mockito.times;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.verifyNoMoreInteractions;
27 import static org.mockito.Mockito.verifyZeroInteractions;
28 import static org.mockito.Mockito.when;
29 
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.os.Handler;
33 import android.os.Looper;
34 import android.os.Message;
35 import android.support.test.filters.SmallTest;
36 import android.support.test.runner.AndroidJUnit4;
37 
38 import com.android.managedprovisioning.R;
39 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker;
40 import com.android.managedprovisioning.analytics.TimeLogger;
41 import com.android.managedprovisioning.model.ProvisioningParams;
42 
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.junit.runner.RunWith;
46 import org.mockito.ArgumentCaptor;
47 import org.mockito.Mock;
48 import org.mockito.MockitoAnnotations;
49 import org.mockito.invocation.InvocationOnMock;
50 
51 /**
52  * Unit tests for {@link ProvisioningManager}.
53  */
54 @RunWith(AndroidJUnit4.class)
55 @SmallTest
56 public class ProvisioningManagerTest {
57     private final int TEST_PROGRESS_ID = 123;
58     private final int TEST_ERROR_ID = 456;
59     private final boolean TEST_FACTORY_RESET_REQUIRED = true;
60     private final ComponentName TEST_ADMIN = new ComponentName("com.test.admin", ".AdminReceiver");
61     private final ProvisioningParams TEST_PARAMS = new ProvisioningParams.Builder()
62             .setProvisioningAction(ACTION_PROVISION_MANAGED_PROFILE)
63             .setDeviceAdminComponentName(TEST_ADMIN)
64             .build();
65 
66     @Mock private Context mContext;
67     @Mock private ProvisioningControllerFactory mFactory;
68     @Mock private ProvisioningAnalyticsTracker mAnalyticsTracker;
69     @Mock private TimeLogger mTimeLogger;
70     @Mock private Handler mUiHandler;
71     @Mock private ProvisioningManagerCallback mCallback;
72     @Mock private AbstractProvisioningController mController;
73 
74     private ProvisioningManager mManager;
75 
76     @Before
setUp()77     public void setUp() {
78         MockitoAnnotations.initMocks(this);
79 
80         // Immediately execute any message that is sent onto the handler
81         when(mUiHandler.sendMessageAtTime(any(Message.class), anyLong())).thenAnswer(
82                 (InvocationOnMock invocation) -> {
83                     Message msg = (Message) invocation.getArguments()[0];
84                     msg.getCallback().run();
85                     return null;
86                 });
87         mManager = new ProvisioningManager(mContext, mUiHandler, mFactory, mAnalyticsTracker,
88                 mTimeLogger);
89         when(mFactory.createProvisioningController(mContext, TEST_PARAMS, mManager))
90                 .thenReturn(mController);
91     }
92 
93     @Test
testMaybeStartProvisioning()94     public void testMaybeStartProvisioning() {
95         // GIVEN that provisioning is not currently running
96         // WHEN calling maybeStartProvisioning
97         mManager.maybeStartProvisioning(TEST_PARAMS);
98 
99         // THEN the factory should be called
100         verify(mFactory).createProvisioningController(mContext, TEST_PARAMS, mManager);
101 
102         // THEN the controller should be started on a Looper that is not the main thread
103         ArgumentCaptor<Looper> looperCaptor = ArgumentCaptor.forClass(Looper.class);
104         verify(mController).start(looperCaptor.capture());
105         assertTrue(looperCaptor.getValue() != Looper.getMainLooper());
106 
107         // WHEN trying to start provisioning again
108         mManager.maybeStartProvisioning(TEST_PARAMS);
109 
110         // THEN nothing should happen
111         verifyNoMoreInteractions(mFactory);
112         verifyNoMoreInteractions(mController);
113     }
114 
115     @Test
testCancelProvisioning()116     public void testCancelProvisioning() {
117         // GIVEN provisioning has been started
118         mManager.maybeStartProvisioning(TEST_PARAMS);
119 
120         // WHEN cancelling provisioning
121         mManager.cancelProvisioning();
122 
123         // THEN the controller should be cancelled
124         verify(mController).cancel();
125     }
126 
127     @Test
testRegisterListener_noProgress()128     public void testRegisterListener_noProgress() {
129         // GIVEN no progress has previously been achieved
130         // WHEN a listener is registered
131         mManager.registerListener(mCallback);
132 
133         // THEN no callback should be given
134         verifyZeroInteractions(mCallback);
135 
136         // WHEN a progress callback was made
137         mManager.progressUpdate(TEST_PROGRESS_ID);
138 
139         // THEN the listener should receive a callback
140         verify(mCallback).progressUpdate(TEST_PROGRESS_ID);
141         verifyNoMoreInteractions(mCallback);
142     }
143 
144     @Test
testListener_progress()145     public void testListener_progress() {
146         // GIVEN a listener is registered
147         mManager.registerListener(mCallback);
148         // WHEN some progress has occurred previously
149         mManager.progressUpdate(TEST_PROGRESS_ID);
150         // THEN the listener should receive a callback
151         verify(mCallback).progressUpdate(TEST_PROGRESS_ID);
152 
153         // WHEN the listener is unregistered and registered again
154         mManager.unregisterListener(mCallback);
155         mManager.registerListener(mCallback);
156         // THEN the listener should receive a callback again
157         verify(mCallback, times(2)).progressUpdate(TEST_PROGRESS_ID);
158         verifyNoMoreInteractions(mCallback);
159     }
160 
161     @Test
testListener_error()162     public void testListener_error() {
163         // GIVEN a listener is registered
164         mManager.registerListener(mCallback);
165         // WHEN some progress has occurred previously
166         mManager.error(R.string.cant_set_up_device, TEST_ERROR_ID, TEST_FACTORY_RESET_REQUIRED);
167         // THEN the listener should receive a callback
168         verify(mCallback).error(R.string.cant_set_up_device, TEST_ERROR_ID, TEST_FACTORY_RESET_REQUIRED);
169 
170         // WHEN the listener is unregistered and registered again
171         mManager.unregisterListener(mCallback);
172         mManager.registerListener(mCallback);
173         // THEN the listener should receive a callback again
174         verify(mCallback, times(2)).error(R.string.cant_set_up_device, TEST_ERROR_ID, TEST_FACTORY_RESET_REQUIRED);
175         verifyNoMoreInteractions(mCallback);
176     }
177 
178     @Test
testProvisioningTasksCompleted()179     public void testProvisioningTasksCompleted() {
180         // GIVEN provisioning has been started
181         mManager.maybeStartProvisioning(TEST_PARAMS);
182         // WHEN all tasks are completed.
183         mManager.provisioningTasksCompleted();
184         // THEN the controller should be prefinalized
185         verify(mController).preFinalize();
186     }
187 
188     @Test
testListener_cleanupCompleted()189     public void testListener_cleanupCompleted() {
190         // GIVEN provisioning has been started
191         mManager.maybeStartProvisioning(TEST_PARAMS);
192 
193         // GIVEN a listener is registered
194         mManager.registerListener(mCallback);
195         // WHEN some progress has occurred previously
196         mManager.cleanUpCompleted();
197         // THEN no callback is sent
198         verifyZeroInteractions(mCallback);
199     }
200 
201     @Test
testListener_preFinalizationCompleted()202     public void testListener_preFinalizationCompleted() {
203         // GIVEN provisioning has been started
204         mManager.maybeStartProvisioning(TEST_PARAMS);
205         // GIVEN a listener is registered
206         mManager.registerListener(mCallback);
207         // WHEN some progress has occurred previously
208         mManager.preFinalizationCompleted();
209         // THEN the listener should receive a callback
210         verify(mCallback).preFinalizationCompleted();
211 
212         // WHEN the listener is unregistered and registered again
213         mManager.unregisterListener(mCallback);
214         mManager.registerListener(mCallback);
215         // THEN the listener should receive a callback again
216         verify(mCallback, times(2)).preFinalizationCompleted();
217         verifyNoMoreInteractions(mCallback);
218     }
219 
220     @Test
testUnregisterListener()221     public void testUnregisterListener() {
222         // GIVEN a register had previously been registered and then unregistered
223         mManager.registerListener(mCallback);
224         mManager.unregisterListener(mCallback);
225 
226         // WHEN a progress callback was made
227         mManager.progressUpdate(TEST_PROGRESS_ID);
228 
229         // THEN the listener should not receive a callback
230         verifyZeroInteractions(mCallback);
231     }
232 }
233