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