Major refactoring of DownloadThread.run().
[android/platform/packages/providers/DownloadProvider.git] / tests / src / com / android / providers / downloads / DownloadManagerFunctionalTest.java
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
17 package com.android.providers.downloads;
18
19 import android.content.ContentValues;
20 import android.database.Cursor;
21 import android.net.ConnectivityManager;
22 import android.net.Uri;
23 import android.os.Environment;
24 import android.provider.Downloads;
25 import android.test.suitebuilder.annotation.LargeTest;
26 import tests.http.MockWebServer;
27 import tests.http.RecordedRequest;
28
29 import java.io.InputStream;
30 import java.net.MalformedURLException;
31 import java.util.List;
32
33 /**
34  * This test exercises the entire download manager working together -- it requests downloads through
35  * the {@link DownloadProvider}, just like a normal client would, and runs the
36  * {@link DownloadService} with start intents.  It sets up a {@link MockWebServer} running on the
37  * device to serve downloads.
38  */
39 @LargeTest
40 public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFunctionalTest {
41     public void testBasicRequest() throws Exception {
42         enqueueResponse(HTTP_OK, FILE_CONTENT);
43
44         String path = "/download_manager_test_path";
45         Uri downloadUri = requestDownload(path);
46         assertEquals(Downloads.STATUS_PENDING, getDownloadStatus(downloadUri));
47         assertTrue(mTestContext.mHasServiceBeenStarted);
48
49         RecordedRequest request = runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
50         assertEquals("GET", request.getMethod());
51         assertEquals(path, request.getPath());
52         assertEquals(FILE_CONTENT, getDownloadContents(downloadUri));
53         assertStartsWith(Environment.getExternalStorageDirectory().getPath(),
54                          getDownloadFilename(downloadUri));
55     }
56
57     public void testDownloadToCache() throws Exception {
58         enqueueResponse(HTTP_OK, FILE_CONTENT);
59         Uri downloadUri = requestDownload("/path");
60         updateDownload(downloadUri, Downloads.COLUMN_DESTINATION,
61                        Integer.toString(Downloads.DESTINATION_CACHE_PARTITION));
62         runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
63         assertEquals(FILE_CONTENT, getDownloadContents(downloadUri));
64         assertStartsWith(Environment.getDownloadCacheDirectory().getPath(),
65                          getDownloadFilename(downloadUri));
66     }
67
68     public void testFileNotFound() throws Exception {
69         enqueueEmptyResponse(HTTP_NOT_FOUND);
70         Uri downloadUri = requestDownload("/nonexistent_path");
71         assertEquals(Downloads.STATUS_PENDING, getDownloadStatus(downloadUri));
72         runUntilStatus(downloadUri, HTTP_NOT_FOUND);
73     }
74
75     public void testRetryAfter() throws Exception {
76         final int delay = 120;
77         enqueueEmptyResponse(HTTP_SERVICE_UNAVAILABLE).addHeader("Retry-after", delay);
78         Uri downloadUri = requestDownload("/path");
79         runUntilStatus(downloadUri, Downloads.STATUS_RUNNING_PAUSED);
80
81         // download manager adds random 0-30s offset
82         mSystemFacade.incrementTimeMillis((delay + 31) * 1000);
83
84         enqueueResponse(HTTP_OK, FILE_CONTENT);
85         runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
86     }
87
88     public void testBasicConnectivityChanges() throws Exception {
89         enqueueResponse(HTTP_OK, FILE_CONTENT);
90         Uri downloadUri = requestDownload("/path");
91
92         // without connectivity, download immediately pauses
93         mSystemFacade.mActiveNetworkType = null;
94         startService(null);
95         waitForDownloadToStop(getStatusReader(downloadUri), Downloads.STATUS_RUNNING_PAUSED);
96
97         // connecting should start the download
98         mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
99         runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
100     }
101
102     public void testRoaming() throws Exception {
103         mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
104         mSystemFacade.mIsRoaming = true;
105
106         // for a normal download, roaming is fine
107         enqueueResponse(HTTP_OK, FILE_CONTENT);
108         Uri downloadUri = requestDownload("/path");
109         startService(null);
110         runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
111
112         // when roaming is disallowed, the download should pause...
113         downloadUri = requestDownload("/path");
114         updateDownload(downloadUri, Downloads.COLUMN_DESTINATION,
115                        Integer.toString(Downloads.DESTINATION_CACHE_PARTITION_NOROAMING));
116         startService(null);
117         waitForDownloadToStop(getStatusReader(downloadUri), Downloads.STATUS_RUNNING_PAUSED);
118
119         // ...and pick up when we're off roaming
120         enqueueResponse(HTTP_OK, FILE_CONTENT);
121         mSystemFacade.mIsRoaming = false;
122         runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
123     }
124
125     /**
126      * Read a downloaded file from disk.
127      */
128     private String getDownloadContents(Uri downloadUri) throws Exception {
129         InputStream inputStream = mResolver.openInputStream(downloadUri);
130         try {
131             return readStream(inputStream);
132         } finally {
133             inputStream.close();
134         }
135     }
136
137     private RecordedRequest runUntilStatus(Uri downloadUri, int status) throws Exception {
138         return super.runUntilStatus(getStatusReader(downloadUri), status);
139     }
140
141     private StatusReader getStatusReader(final Uri downloadUri) {
142         return new StatusReader() {
143             public int getStatus() {
144                 return getDownloadStatus(downloadUri);
145             }
146
147             public boolean isComplete(int status) {
148                 return !Downloads.isStatusInformational(status);
149             }
150         };
151     }
152
153     protected int getDownloadStatus(Uri downloadUri) {
154         return Integer.valueOf(getDownloadField(downloadUri, Downloads.COLUMN_STATUS));
155     }
156
157     private String getDownloadFilename(Uri downloadUri) {
158         return getDownloadField(downloadUri, Downloads._DATA);
159     }
160
161     private String getDownloadField(Uri downloadUri, String column) {
162         final String[] columns = new String[] {column};
163         Cursor cursor = mResolver.query(downloadUri, columns, null, null, null);
164         try {
165             assertEquals(1, cursor.getCount());
166             cursor.moveToFirst();
167             return cursor.getString(0);
168         } finally {
169             cursor.close();
170         }
171     }
172
173     /**
174      * Request a download from the Download Manager.
175      */
176     private Uri requestDownload(String path) throws MalformedURLException {
177         ContentValues values = new ContentValues();
178         values.put(Downloads.COLUMN_URI, getServerUri(path));
179         values.put(Downloads.COLUMN_DESTINATION, Downloads.DESTINATION_EXTERNAL);
180         return mResolver.insert(Downloads.CONTENT_URI, values);
181     }
182
183     /**
184      * Update one field of a download in the provider.
185      */
186     private void updateDownload(Uri downloadUri, String column, String value) {
187         ContentValues values = new ContentValues();
188         values.put(column, value);
189         int numChanged = mResolver.update(downloadUri, values, null, null);
190         assertEquals(1, numChanged);
191     }
192 }