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.task; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20 21 import static com.android.managedprovisioning.task.DownloadPackageTask.ERROR_DOWNLOAD_FAILED; 22 import static com.android.managedprovisioning.task.DownloadPackageTask.ERROR_OTHER; 23 24 import static org.junit.Assert.assertEquals; 25 import static org.mockito.Matchers.any; 26 import static org.mockito.Matchers.anyString; 27 import static org.mockito.Mockito.doReturn; 28 import static org.mockito.Matchers.nullable; 29 import static org.mockito.Mockito.verify; 30 import static org.mockito.Mockito.verifyNoMoreInteractions; 31 import static org.mockito.Mockito.when; 32 33 import android.app.DownloadManager; 34 import android.app.DownloadManager.Query; 35 import android.app.DownloadManager.Request; 36 import android.content.BroadcastReceiver; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.IntentFilter; 40 import android.database.MatrixCursor; 41 import android.os.Handler; 42 import android.os.Looper; 43 import android.support.test.filters.FlakyTest; 44 import android.support.test.filters.SmallTest; 45 46 import com.android.managedprovisioning.common.Utils; 47 import com.android.managedprovisioning.model.PackageDownloadInfo; 48 import com.android.managedprovisioning.model.ProvisioningParams; 49 50 import org.junit.Before; 51 import org.junit.Test; 52 import org.mockito.ArgumentCaptor; 53 import org.mockito.Mock; 54 import org.mockito.MockitoAnnotations; 55 56 @SmallTest 57 @FlakyTest // TODO: http://b/34117742 58 public class DownloadPackageTaskTest { 59 @Mock private Context mContext; 60 @Mock private AbstractProvisioningTask.Callback mCallback; 61 @Mock private DownloadManager mDownloadManager; 62 @Mock private Utils mUtils; 63 64 private static final String TEST_PACKAGE_NAME = "sample.package.name"; 65 private static final String TEST_PACKAGE_LOCATION = "http://www.some.uri.com"; 66 private static final String TEST_LOCAL_FILENAME = "/local/filename"; 67 private static final int TEST_USER_ID = 123; 68 private static final byte[] TEST_SIGNATURE = new byte[] {'a', 'b', 'c', 'd'}; 69 70 private static final long TEST_DOWNLOAD_ID = 1234; 71 private static final int PACKAGE_VERSION = 43; 72 private static final PackageDownloadInfo TEST_DOWNLOAD_INFO = new PackageDownloadInfo.Builder() 73 .setLocation(TEST_PACKAGE_LOCATION) 74 .setSignatureChecksum(TEST_SIGNATURE) 75 .setMinVersion(PACKAGE_VERSION) 76 .build(); 77 private static final ProvisioningParams PARAMS = new ProvisioningParams.Builder() 78 .setDeviceAdminPackageName(TEST_PACKAGE_NAME) 79 .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE) 80 .setDeviceAdminDownloadInfo(TEST_DOWNLOAD_INFO) 81 .build(); 82 83 private DownloadPackageTask mTask; 84 85 @Before 86 public void setUp() throws Exception { 87 MockitoAnnotations.initMocks(this); 88 89 when(mContext.getSystemService(Context.DOWNLOAD_SERVICE)).thenReturn(mDownloadManager); 90 when(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME, PACKAGE_VERSION, mContext)) 91 .thenReturn(true); 92 93 mTask = new DownloadPackageTask( 94 mUtils, 95 mContext, 96 PARAMS, 97 mCallback); 98 } 99 100 @Test 101 public void testAlreadyInstalled() throws Exception { 102 // GIVEN the package is already installed, with the right version 103 when(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME, PACKAGE_VERSION, mContext)) 104 .thenReturn(false); 105 106 // WHEN running the download package task 107 runTask(); 108 109 // THEN we get a success callback directly 110 verifyOnTaskFinished(null); 111 verifyNoMoreInteractions(mCallback); 112 } 113 114 @Test 115 public void testNotConnected() throws Exception { 116 // GIVEN we're not connected to a network 117 doReturn(false).when(mUtils).isConnectedToNetwork(mContext); 118 119 // WHEN running the download package task 120 runTask(); 121 122 // THEN we get an error callback 123 verify(mCallback).onError(mTask, ERROR_OTHER); 124 verifyNoMoreInteractions(mCallback); 125 } 126 127 @Test 128 public void testDownloadFailed() throws Exception { 129 // GIVEN the download succeeds 130 mockSuccessfulDownload(DownloadManager.STATUS_FAILED); 131 132 // WHEN running the download package task 133 runTask(); 134 135 // THEN a download receiver was registered 136 BroadcastReceiver receiver = verifyDownloadReceiver(); 137 138 // WHEN invoking download complete 139 receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 140 141 // THEN we get a success callback 142 verify(mCallback).onError(mTask, ERROR_DOWNLOAD_FAILED); 143 verifyNoMoreInteractions(mCallback); 144 } 145 146 @Test 147 public void testDownloadSucceeded() throws Exception { 148 // GIVEN the download succeeds 149 mockSuccessfulDownload(DownloadManager.STATUS_SUCCESSFUL); 150 151 // WHEN running the download package task 152 runTask(); 153 154 // THEN a download receiver was registered 155 BroadcastReceiver receiver = verifyDownloadReceiver(); 156 157 // WHEN invoking download complete 158 receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 159 160 // THEN we get a success callback 161 verifyOnTaskFinished(TEST_LOCAL_FILENAME); 162 verifyNoMoreInteractions(mCallback); 163 } 164 165 /** Test that it works fine even if DownloadManager sends the broadcast twice */ 166 @Test 167 public void testSendBroadcastTwice() throws Exception { 168 // GIVEN the download succeeds 169 mockSuccessfulDownload(DownloadManager.STATUS_SUCCESSFUL); 170 171 // WHEN running the download package task 172 runTask(); 173 174 // THEN a download receiver was registered 175 BroadcastReceiver receiver = verifyDownloadReceiver(); 176 177 // WHEN invoking download complete twice 178 receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 179 receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 180 181 // THEN we still get only one success callback 182 verifyOnTaskFinished(TEST_LOCAL_FILENAME); 183 verifyNoMoreInteractions(mCallback); 184 } 185 186 private void mockSuccessfulDownload(int downloadStatus) { 187 doReturn(true).when(mUtils).isConnectedToNetwork(any(Context.class)); 188 when(mDownloadManager.enqueue(any(Request.class))).thenReturn(TEST_DOWNLOAD_ID); 189 MatrixCursor cursor = new MatrixCursor(new String[]{ 190 DownloadManager.COLUMN_STATUS, 191 DownloadManager.COLUMN_LOCAL_FILENAME}); 192 cursor.addRow(new Object[]{downloadStatus, TEST_LOCAL_FILENAME}); 193 when(mDownloadManager.query(any(Query.class))).thenReturn(cursor); 194 } 195 196 private BroadcastReceiver verifyDownloadReceiver() { 197 verify(mDownloadManager).setAccessFilename(true); 198 ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass( 199 BroadcastReceiver.class); 200 ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass( 201 IntentFilter.class); 202 verify(mContext).registerReceiver( 203 receiverCaptor.capture(), 204 filterCaptor.capture(), 205 nullable(String.class), 206 any(Handler.class)); 207 assertEquals(filterCaptor.getValue().getAction(0), 208 DownloadManager.ACTION_DOWNLOAD_COMPLETE); 209 return receiverCaptor.getValue(); 210 } 211 212 private void verifyOnTaskFinished(String location) { 213 verify(mCallback).onSuccess(mTask); 214 assertEquals(location, mTask.getDownloadedPackageLocation()); 215 } 216 217 private void runTask() { 218 if (Looper.myLooper() == null) { 219 Looper.prepare(); 220 } 221 mTask.run(TEST_USER_ID); 222 } 223 } 224