/* * Copyright 2016, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.managedprovisioning.task; import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; import static com.android.managedprovisioning.task.DownloadPackageTask.ERROR_DOWNLOAD_FAILED; import static com.android.managedprovisioning.task.DownloadPackageTask.ERROR_OTHER; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Matchers.nullable; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.app.DownloadManager; import android.app.DownloadManager.Query; import android.app.DownloadManager.Request; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.MatrixCursor; import android.os.Handler; import android.os.Looper; import android.support.test.filters.FlakyTest; import android.support.test.filters.SmallTest; import com.android.managedprovisioning.common.Utils; import com.android.managedprovisioning.model.PackageDownloadInfo; import com.android.managedprovisioning.model.ProvisioningParams; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest @FlakyTest // TODO: http://b/34117742 public class DownloadPackageTaskTest { @Mock private Context mContext; @Mock private AbstractProvisioningTask.Callback mCallback; @Mock private DownloadManager mDownloadManager; @Mock private Utils mUtils; private static final String TEST_PACKAGE_NAME = "sample.package.name"; private static final String TEST_PACKAGE_LOCATION = "http://www.some.uri.com"; private static final String TEST_LOCAL_FILENAME = "/local/filename"; private static final int TEST_USER_ID = 123; private static final byte[] TEST_SIGNATURE = new byte[] {'a', 'b', 'c', 'd'}; private static final long TEST_DOWNLOAD_ID = 1234; private static final int PACKAGE_VERSION = 43; private static final PackageDownloadInfo TEST_DOWNLOAD_INFO = new PackageDownloadInfo.Builder() .setLocation(TEST_PACKAGE_LOCATION) .setSignatureChecksum(TEST_SIGNATURE) .setMinVersion(PACKAGE_VERSION) .build(); private static final ProvisioningParams PARAMS = new ProvisioningParams.Builder() .setDeviceAdminPackageName(TEST_PACKAGE_NAME) .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE) .setDeviceAdminDownloadInfo(TEST_DOWNLOAD_INFO) .build(); private DownloadPackageTask mTask; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mContext.getSystemService(Context.DOWNLOAD_SERVICE)).thenReturn(mDownloadManager); when(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME, PACKAGE_VERSION, mContext)) .thenReturn(true); mTask = new DownloadPackageTask( mUtils, mContext, PARAMS, mCallback); } @Test public void testAlreadyInstalled() throws Exception { // GIVEN the package is already installed, with the right version when(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME, PACKAGE_VERSION, mContext)) .thenReturn(false); // WHEN running the download package task runTask(); // THEN we get a success callback directly verifyOnTaskFinished(null); verifyNoMoreInteractions(mCallback); } @Test public void testNotConnected() throws Exception { // GIVEN we're not connected to a network doReturn(false).when(mUtils).isConnectedToNetwork(mContext); // WHEN running the download package task runTask(); // THEN we get an error callback verify(mCallback).onError(mTask, ERROR_OTHER); verifyNoMoreInteractions(mCallback); } @Test public void testDownloadFailed() throws Exception { // GIVEN the download succeeds mockSuccessfulDownload(DownloadManager.STATUS_FAILED); // WHEN running the download package task runTask(); // THEN a download receiver was registered BroadcastReceiver receiver = verifyDownloadReceiver(); // WHEN invoking download complete receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); // THEN we get a success callback verify(mCallback).onError(mTask, ERROR_DOWNLOAD_FAILED); verifyNoMoreInteractions(mCallback); } @Test public void testDownloadSucceeded() throws Exception { // GIVEN the download succeeds mockSuccessfulDownload(DownloadManager.STATUS_SUCCESSFUL); // WHEN running the download package task runTask(); // THEN a download receiver was registered BroadcastReceiver receiver = verifyDownloadReceiver(); // WHEN invoking download complete receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); // THEN we get a success callback verifyOnTaskFinished(TEST_LOCAL_FILENAME); verifyNoMoreInteractions(mCallback); } /** Test that it works fine even if DownloadManager sends the broadcast twice */ @Test public void testSendBroadcastTwice() throws Exception { // GIVEN the download succeeds mockSuccessfulDownload(DownloadManager.STATUS_SUCCESSFUL); // WHEN running the download package task runTask(); // THEN a download receiver was registered BroadcastReceiver receiver = verifyDownloadReceiver(); // WHEN invoking download complete twice receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); receiver.onReceive(mContext, new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); // THEN we still get only one success callback verifyOnTaskFinished(TEST_LOCAL_FILENAME); verifyNoMoreInteractions(mCallback); } private void mockSuccessfulDownload(int downloadStatus) { doReturn(true).when(mUtils).isConnectedToNetwork(any(Context.class)); when(mDownloadManager.enqueue(any(Request.class))).thenReturn(TEST_DOWNLOAD_ID); MatrixCursor cursor = new MatrixCursor(new String[]{ DownloadManager.COLUMN_STATUS, DownloadManager.COLUMN_LOCAL_FILENAME}); cursor.addRow(new Object[]{downloadStatus, TEST_LOCAL_FILENAME}); when(mDownloadManager.query(any(Query.class))).thenReturn(cursor); } private BroadcastReceiver verifyDownloadReceiver() { verify(mDownloadManager).setAccessFilename(true); ArgumentCaptor receiverCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); ArgumentCaptor filterCaptor = ArgumentCaptor.forClass( IntentFilter.class); verify(mContext).registerReceiver( receiverCaptor.capture(), filterCaptor.capture(), nullable(String.class), any(Handler.class)); assertEquals(filterCaptor.getValue().getAction(0), DownloadManager.ACTION_DOWNLOAD_COMPLETE); return receiverCaptor.getValue(); } private void verifyOnTaskFinished(String location) { verify(mCallback).onSuccess(mTask); assertEquals(location, mTask.getDownloadedPackageLocation()); } private void runTask() { if (Looper.myLooper() == null) { Looper.prepare(); } mTask.run(TEST_USER_ID); } }