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
17package com.android.managedprovisioning.provisioning;
18
19import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
20
21import static org.junit.Assert.assertTrue;
22import static org.mockito.Matchers.any;
23import static org.mockito.Matchers.anyLong;
24import static org.mockito.Mockito.times;
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.content.ComponentName;
31import android.content.Context;
32import android.os.Handler;
33import android.os.Looper;
34import android.os.Message;
35import android.support.test.filters.SmallTest;
36import android.support.test.runner.AndroidJUnit4;
37
38import com.android.managedprovisioning.R;
39import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker;
40import com.android.managedprovisioning.analytics.TimeLogger;
41import com.android.managedprovisioning.model.ProvisioningParams;
42
43import org.junit.Before;
44import org.junit.Test;
45import org.junit.runner.RunWith;
46import org.mockito.ArgumentCaptor;
47import org.mockito.Mock;
48import org.mockito.MockitoAnnotations;
49import org.mockito.invocation.InvocationOnMock;
50
51/**
52 * Unit tests for {@link ProvisioningManager}.
53 */
54@RunWith(AndroidJUnit4.class)
55@SmallTest
56public 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
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
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
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
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
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
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
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
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
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
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