1/* 2 * Copyright (C) 2010 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.providers.downloads; 18 19import static android.text.format.DateUtils.SECOND_IN_MILLIS; 20import static java.net.HttpURLConnection.HTTP_OK; 21 22import android.content.ContentValues; 23import android.database.Cursor; 24import android.net.ConnectivityManager; 25import android.net.Uri; 26import android.os.Environment; 27import android.os.SystemClock; 28import android.provider.Downloads; 29import android.test.suitebuilder.annotation.LargeTest; 30 31import com.google.mockwebserver.MockWebServer; 32import com.google.mockwebserver.RecordedRequest; 33 34import java.io.InputStream; 35import java.net.MalformedURLException; 36import java.net.UnknownHostException; 37import java.util.concurrent.TimeoutException; 38 39/** 40 * This test exercises the entire download manager working together -- it requests downloads through 41 * the {@link DownloadProvider}, just like a normal client would, and runs the 42 * {@link DownloadService} with start intents. It sets up a {@link MockWebServer} running on the 43 * device to serve downloads. 44 */ 45@LargeTest 46public class DownloadProviderFunctionalTest extends AbstractDownloadProviderFunctionalTest { 47 private static final String TAG = "DownloadManagerFunctionalTest"; 48 49 public DownloadProviderFunctionalTest() { 50 super(new FakeSystemFacade()); 51 } 52 53 public void testDownloadTextFile() throws Exception { 54 enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT)); 55 56 String path = "/download_manager_test_path"; 57 Uri downloadUri = requestDownload(path); 58 assertEquals(Downloads.Impl.STATUS_PENDING, getDownloadStatus(downloadUri)); 59 assertTrue(mTestContext.mHasServiceBeenStarted); 60 61 runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS); 62 RecordedRequest request = takeRequest(); 63 assertEquals("GET", request.getMethod()); 64 assertEquals(path, request.getPath()); 65 assertEquals(FILE_CONTENT, getDownloadContents(downloadUri)); 66 assertStartsWith(Environment.getExternalStorageDirectory().getPath(), 67 getDownloadFilename(downloadUri)); 68 } 69 70 public void testDownloadToCache() throws Exception { 71 enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT)); 72 73 Uri downloadUri = requestDownload("/path"); 74 updateDownload(downloadUri, Downloads.Impl.COLUMN_DESTINATION, 75 Integer.toString(Downloads.Impl.DESTINATION_CACHE_PARTITION)); 76 runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS); 77 assertEquals(FILE_CONTENT, getDownloadContents(downloadUri)); 78 assertStartsWith(getContext().getCacheDir().getAbsolutePath(), 79 getDownloadFilename(downloadUri)); 80 } 81 82 public void testRoaming() throws Exception { 83 enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT)); 84 enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT)); 85 86 mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE; 87 mSystemFacade.mIsRoaming = true; 88 89 // for a normal download, roaming is fine 90 Uri downloadUri = requestDownload("/path"); 91 runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS); 92 93 // when roaming is disallowed, the download should pause... 94 downloadUri = requestDownload("/path"); 95 updateDownload(downloadUri, Downloads.Impl.COLUMN_DESTINATION, 96 Integer.toString(Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING)); 97 runUntilStatus(downloadUri, Downloads.Impl.STATUS_WAITING_FOR_NETWORK); 98 99 // ...and pick up when we're off roaming 100 mSystemFacade.mIsRoaming = false; 101 runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS); 102 } 103 104 public void testCleartextTrafficPermittedFlagHonored() throws Exception { 105 enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT)); 106 enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT)); 107 108 // Assert that HTTP request succeeds when cleartext traffic is permitted 109 mSystemFacade.mCleartextTrafficPermitted = true; 110 Uri downloadUri = requestDownload("/path"); 111 assertEquals("http", downloadUri.getScheme()); 112 runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS); 113 114 // Assert that HTTP request fails when cleartext traffic is not permitted 115 mSystemFacade.mCleartextTrafficPermitted = false; 116 downloadUri = requestDownload("/path"); 117 assertEquals("http", downloadUri.getScheme()); 118 runUntilStatus(downloadUri, Downloads.Impl.STATUS_BAD_REQUEST); 119 } 120 121 /** 122 * Read a downloaded file from disk. 123 */ 124 private String getDownloadContents(Uri downloadUri) throws Exception { 125 InputStream inputStream = mResolver.openInputStream(downloadUri); 126 try { 127 return readStream(inputStream); 128 } finally { 129 inputStream.close(); 130 } 131 } 132 133 private void runUntilStatus(Uri downloadUri, int expected) throws Exception { 134 startService(null); 135 136 int actual = -1; 137 138 final long timeout = SystemClock.elapsedRealtime() + (15 * SECOND_IN_MILLIS); 139 while (SystemClock.elapsedRealtime() < timeout) { 140 actual = getDownloadStatus(downloadUri); 141 if (expected == actual) { 142 return; 143 } 144 145 SystemClock.sleep(100); 146 } 147 148 throw new TimeoutException("Expected status " + expected + "; only reached " + actual); 149 } 150 151 protected int getDownloadStatus(Uri downloadUri) { 152 return Integer.valueOf(getDownloadField(downloadUri, Downloads.Impl.COLUMN_STATUS)); 153 } 154 155 private String getDownloadFilename(Uri downloadUri) { 156 return getDownloadField(downloadUri, Downloads.Impl._DATA); 157 } 158 159 private String getDownloadField(Uri downloadUri, String column) { 160 final String[] columns = new String[] {column}; 161 Cursor cursor = mResolver.query(downloadUri, columns, null, null, null); 162 try { 163 assertEquals(1, cursor.getCount()); 164 cursor.moveToFirst(); 165 return cursor.getString(0); 166 } finally { 167 cursor.close(); 168 } 169 } 170 171 /** 172 * Request a download from the Download Manager. 173 */ 174 private Uri requestDownload(String path) throws MalformedURLException, UnknownHostException { 175 ContentValues values = new ContentValues(); 176 values.put(Downloads.Impl.COLUMN_URI, getServerUri(path)); 177 values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_EXTERNAL); 178 return mResolver.insert(Downloads.Impl.CONTENT_URI, values); 179 } 180 181 /** 182 * Update one field of a download in the provider. 183 */ 184 private void updateDownload(Uri downloadUri, String column, String value) { 185 ContentValues values = new ContentValues(); 186 values.put(column, value); 187 int numChanged = mResolver.update(downloadUri, values, null, null); 188 assertEquals(1, numChanged); 189 } 190} 191