1df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard/*
2df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * Copyright (C) 2010 The Android Open Source Project
3df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard *
4df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * Licensed under the Apache License, Version 2.0 (the "License");
5df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * you may not use this file except in compliance with the License.
6df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * You may obtain a copy of the License at
7df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard *
8df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard *      http://www.apache.org/licenses/LICENSE-2.0
9df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard *
10df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * Unless required by applicable law or agreed to in writing, software
11df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * distributed under the License is distributed on an "AS IS" BASIS,
12df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * See the License for the specific language governing permissions and
14df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard * limitations under the License.
15df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard */
16df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
17df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howardpackage com.android.providers.downloads;
18df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
1958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static android.app.DownloadManager.STATUS_FAILED;
2058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static android.app.DownloadManager.STATUS_PAUSED;
217ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkeyimport static android.net.TrafficStats.GB_IN_BYTES;
2258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static android.text.format.DateUtils.SECOND_IN_MILLIS;
2358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
2458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static java.net.HttpURLConnection.HTTP_NOT_FOUND;
2558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static java.net.HttpURLConnection.HTTP_OK;
2658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static java.net.HttpURLConnection.HTTP_PARTIAL;
2758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static java.net.HttpURLConnection.HTTP_PRECON_FAILED;
2858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport static java.net.HttpURLConnection.HTTP_UNAVAILABLE;
2970c0e1eff5ff7cd5051738f76cecd6cb87353a43Jeff Sharkeyimport static org.mockito.Matchers.anyInt;
3070c0e1eff5ff7cd5051738f76cecd6cb87353a43Jeff Sharkeyimport static org.mockito.Matchers.anyString;
3170c0e1eff5ff7cd5051738f76cecd6cb87353a43Jeff Sharkeyimport static org.mockito.Matchers.isA;
3270c0e1eff5ff7cd5051738f76cecd6cb87353a43Jeff Sharkeyimport static org.mockito.Mockito.atLeastOnce;
3370c0e1eff5ff7cd5051738f76cecd6cb87353a43Jeff Sharkeyimport static org.mockito.Mockito.never;
3470c0e1eff5ff7cd5051738f76cecd6cb87353a43Jeff Sharkeyimport static org.mockito.Mockito.times;
3570c0e1eff5ff7cd5051738f76cecd6cb87353a43Jeff Sharkeyimport static org.mockito.Mockito.verify;
3636612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey
3714961f94d762e733a733e3268fca1074d8da5f8cSteve Howardimport android.app.DownloadManager;
3836612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkeyimport android.app.Notification;
3936612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkeyimport android.app.NotificationManager;
4036612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkeyimport android.content.Context;
410a77c62a82503b38c484e0079648f0231dd85d53Steve Howardimport android.content.Intent;
42df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howardimport android.database.Cursor;
43071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howardimport android.net.ConnectivityManager;
44df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howardimport android.net.Uri;
45df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howardimport android.os.Environment;
4658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport android.os.SystemClock;
470a77c62a82503b38c484e0079648f0231dd85d53Steve Howardimport android.provider.Downloads;
48071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howardimport android.test.suitebuilder.annotation.LargeTest;
497ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkeyimport android.test.suitebuilder.annotation.Suppress;
507ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkeyimport android.text.format.DateUtils;
51a1cbbb41a7423c6f87b2f461075aad4c665f19ddVasu Nori
52ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkeyimport com.google.mockwebserver.MockResponse;
53ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkeyimport com.google.mockwebserver.RecordedRequest;
547ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkeyimport com.google.mockwebserver.SocketPolicy;
55df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
56dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkeyimport libcore.io.IoUtils;
57dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey
586d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howardimport java.io.File;
59df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howardimport java.io.FileInputStream;
603d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howardimport java.io.FileNotFoundException;
613d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howardimport java.io.IOException;
62df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howardimport java.io.InputStream;
63b5629da794cb3c1ca1970d206343743b165b9644Steve Howardimport java.util.List;
6458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkeyimport java.util.concurrent.TimeoutException;
65df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
66071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard@LargeTest
67e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howardpublic class PublicApiFunctionalTest extends AbstractPublicApiTest {
68b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    private static final String REDIRECTED_PATH = "/other_path";
69b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    private static final String ETAG = "my_etag";
70df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
71e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    protected File mTestDirectory;
7236612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey    private NotificationManager mNotifManager;
73df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
74e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    public PublicApiFunctionalTest() {
75e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        super(new FakeSystemFacade());
76df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
77df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
78df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    @Override
79df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    protected void setUp() throws Exception {
80df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        super.setUp();
816d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard
8236612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        mNotifManager = (NotificationManager) getContext()
8336612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey                .getSystemService(Context.NOTIFICATION_SERVICE);
8436612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey
856d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator
866d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard                                  + "download_manager_functional_test");
876d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        if (mTestDirectory.exists()) {
88dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            IoUtils.deleteContents(mTestDirectory);
895d217003acf21aea852975af0dff3b398cea6768Vasu Nori        } else {
905d217003acf21aea852975af0dff3b398cea6768Vasu Nori            mTestDirectory.mkdir();
916d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        }
926d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard    }
936d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard
946d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard    @Override
956d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard    protected void tearDown() throws Exception {
965d217003acf21aea852975af0dff3b398cea6768Vasu Nori        if (mTestDirectory != null && mTestDirectory.exists()) {
97dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey            IoUtils.deleteContents(mTestDirectory);
986d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard            mTestDirectory.delete();
996d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        }
1006d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        super.tearDown();
101df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
102df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
103df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    public void testBasicRequest() throws Exception {
104ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
105df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
106df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        Download download = enqueueRequest(getRequest());
107df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals(DownloadManager.STATUS_PENDING,
108df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                     download.getLongField(DownloadManager.COLUMN_STATUS));
109df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals(getServerUri(REQUEST_PATH),
110df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                     download.getStringField(DownloadManager.COLUMN_URI));
111df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals(download.mId, download.getLongField(DownloadManager.COLUMN_ID));
1126d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        assertEquals(mSystemFacade.currentTimeMillis(),
1136d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard                     download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
114df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
1156d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        mSystemFacade.incrementTimeMillis(10);
116e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
117e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        RecordedRequest request = takeRequest();
118df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals("GET", request.getMethod());
119df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals(REQUEST_PATH, request.getPath());
120df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
121df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        Uri localUri = Uri.parse(download.getStringField(DownloadManager.COLUMN_LOCAL_URI));
1223d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        assertEquals("content", localUri.getScheme());
1233d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        checkUriContent(localUri);
124df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals("text/plain", download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
125df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
126df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        int size = FILE_CONTENT.length();
127df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals(size, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
128df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals(size, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
1296d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        assertEquals(mSystemFacade.currentTimeMillis(),
1306d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard                     download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
131df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
132dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        checkCompleteDownload(download);
133df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
134df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
1357ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey    @Suppress
1367ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey    public void testExtremelyLarge() throws Exception {
1377ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey        // NOTE: suppressed since this takes several minutes to run
1387ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey        final long length = 3 * GB_IN_BYTES;
1397ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey        final InputStream body = new FakeInputStream(length);
1407ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey
141323f5ae0cafdc72f61defefaa5ba938f1b4d0ddaJeff Sharkey        enqueueResponse(new MockResponse().setResponseCode(HTTP_OK).setBody(body, length)
1427ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey                .setHeader("Content-type", "text/plain")
1437ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey                .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END));
1447ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey
1457ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey        final Download download = enqueueRequest(getRequest()
1467ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey                .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "extreme.bin"));
1477ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL, 10 * DateUtils.MINUTE_IN_MILLIS);
1487ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey
1497ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey        assertEquals(length, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
1507ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey        assertEquals(length, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
1517ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey    }
1527ce206b2108714035eeed29c1dc268a3f1ccf359Jeff Sharkey
1533d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard    private void checkUriContent(Uri uri) throws FileNotFoundException, IOException {
1543d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        InputStream inputStream = mResolver.openInputStream(uri);
1553d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        try {
1563d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard            assertEquals(FILE_CONTENT, readStream(inputStream));
1573d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        } finally {
1583d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard            inputStream.close();
1593d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        }
1603d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard    }
1613d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard
162df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    public void testTitleAndDescription() throws Exception {
163df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        Download download = enqueueRequest(getRequest()
164df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                                           .setTitle("my title")
165df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                                           .setDescription("my description"));
166df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals("my title", download.getStringField(DownloadManager.COLUMN_TITLE));
167df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals("my description",
168df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                     download.getStringField(DownloadManager.COLUMN_DESCRIPTION));
169df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
170df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
171df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    public void testDownloadError() throws Exception {
172ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
173b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        runSimpleFailureTest(HTTP_NOT_FOUND);
174df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
175df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
176df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    public void testUnhandledHttpStatus() throws Exception {
177ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(1234)); // some invalid HTTP status
178b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        runSimpleFailureTest(DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
179df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
180df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
181df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    public void testInterruptedDownload() throws Exception {
182df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        int initialLength = 5;
183b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        enqueueInterruptedDownloadResponses(initialLength);
184df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
185b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        Download download = enqueueRequest(getRequest());
186df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
187df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        assertEquals(initialLength,
188df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                     download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
189b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        assertEquals(FILE_CONTENT.length(),
190b5629da794cb3c1ca1970d206343743b165b9644Steve Howard                     download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
191e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        takeRequest(); // get the first request out of the queue
192df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
193df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
194e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
195dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        checkCompleteDownload(download);
196b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
197e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        List<String> headers = takeRequest().getHeaders();
198b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        assertTrue("No Range header: " + headers,
199b5629da794cb3c1ca1970d206343743b165b9644Steve Howard                   headers.contains("Range: bytes=" + initialLength + "-"));
200b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        assertTrue("No ETag header: " + headers, headers.contains("If-Match: " + ETAG));
201b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
202b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
203f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard    public void testInterruptedExternalDownload() throws Exception {
204f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard        enqueueInterruptedDownloadResponses(5);
205dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        Download download = enqueueRequest(getRequest().setDestinationUri(getExternalUri()));
206f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
207f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
208f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
209dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        checkCompleteDownload(download);
210f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard    }
211f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard
212b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    private void enqueueInterruptedDownloadResponses(int initialLength) {
213b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        // the first response has normal headers but unexpectedly closes after initialLength bytes
214ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildPartialResponse(0, initialLength));
215df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        // the second response returns partial content for the rest of the data
216ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildPartialResponse(initialLength, FILE_CONTENT.length()));
217b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
218b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
219ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey    private MockResponse buildPartialResponse(int start, int end) {
220dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        int totalLength = FILE_CONTENT.length();
221dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        boolean isFirstResponse = (start == 0);
22258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        int status = isFirstResponse ? HTTP_OK : HTTP_PARTIAL;
223ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        MockResponse response = buildResponse(status, FILE_CONTENT.substring(start, end))
224dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey                .setHeader("Content-length", isFirstResponse ? totalLength : (end - start))
225ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey                .setHeader("Etag", ETAG);
226dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        if (!isFirstResponse) {
227ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey            response.setHeader(
228ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey                    "Content-range", "bytes " + start + "-" + totalLength + "/" + totalLength);
229dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        }
230dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        return response;
231df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
232df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
2335d217003acf21aea852975af0dff3b398cea6768Vasu Nori    // enqueue a huge response to keep the receiveing thread in DownloadThread.java busy for a while
2345d217003acf21aea852975af0dff3b398cea6768Vasu Nori    // give enough time to do something (cancel/remove etc) on that downloadrequest
2355d217003acf21aea852975af0dff3b398cea6768Vasu Nori    // while it is in progress
236ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey    private MockResponse buildContinuingResponse() {
2375d217003acf21aea852975af0dff3b398cea6768Vasu Nori        int numPackets = 100;
238ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        int contentLength = STRING_1K.length() * numPackets;
239ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        return buildResponse(HTTP_OK, STRING_1K)
240ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey               .setHeader("Content-length", contentLength)
241ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey               .setHeader("Etag", ETAG)
242ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey               .setBytesPerSecond(1024);
2435d217003acf21aea852975af0dff3b398cea6768Vasu Nori    }
2445d217003acf21aea852975af0dff3b398cea6768Vasu Nori
245df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    public void testFiltering() throws Exception {
246ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
247ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
248ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
249df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        Download download1 = enqueueRequest(getRequest());
250df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
2516d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard
2526d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        mSystemFacade.incrementTimeMillis(1); // ensure downloads are correctly ordered by time
253df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        Download download2 = enqueueRequest(getRequest());
254df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        download2.runUntilStatus(DownloadManager.STATUS_FAILED);
2556d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard
2566d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        mSystemFacade.incrementTimeMillis(1);
257df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        Download download3 = enqueueRequest(getRequest());
258df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
259df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        Cursor cursor = mManager.query(new DownloadManager.Query());
2606d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        checkAndCloseCursor(cursor, download3, download2, download1);
261df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
262df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        cursor = mManager.query(new DownloadManager.Query().setFilterById(download2.mId));
263df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        checkAndCloseCursor(cursor, download2);
264df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
265df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        cursor = mManager.query(new DownloadManager.Query()
266df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                                .setFilterByStatus(DownloadManager.STATUS_PENDING));
267df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        checkAndCloseCursor(cursor, download3);
268df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
269df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        cursor = mManager.query(new DownloadManager.Query()
270df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                                .setFilterByStatus(DownloadManager.STATUS_FAILED
271df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                                              | DownloadManager.STATUS_SUCCESSFUL));
2726d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        checkAndCloseCursor(cursor, download2, download1);
273df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
274df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        cursor = mManager.query(new DownloadManager.Query()
275df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                                .setFilterByStatus(DownloadManager.STATUS_RUNNING));
276df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        checkAndCloseCursor(cursor);
27771e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
27871e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        mSystemFacade.incrementTimeMillis(1);
27971e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        Download invisibleDownload = enqueueRequest(getRequest().setVisibleInDownloadsUi(false));
28071e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        cursor = mManager.query(new DownloadManager.Query());
28171e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        checkAndCloseCursor(cursor, invisibleDownload, download3, download2, download1);
28271e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        cursor = mManager.query(new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true));
28371e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        checkAndCloseCursor(cursor, download3, download2, download1);
28471e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard    }
28571e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
28671e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard    public void testOrdering() throws Exception {
287ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, "small contents"));
288ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, "large contents large contents"));
289ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
290ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
29171e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        Download download1 = enqueueRequest(getRequest());
29271e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
29371e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
29471e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        mSystemFacade.incrementTimeMillis(1);
29571e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        Download download2 = enqueueRequest(getRequest());
29671e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        download2.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
29771e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
29871e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        mSystemFacade.incrementTimeMillis(1);
29971e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        Download download3 = enqueueRequest(getRequest());
30071e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        download3.runUntilStatus(DownloadManager.STATUS_FAILED);
30171e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
30271e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        // default ordering -- by timestamp descending
30371e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        Cursor cursor = mManager.query(new DownloadManager.Query());
30471e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        checkAndCloseCursor(cursor, download3, download2, download1);
30571e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
30671e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        cursor = mManager.query(new DownloadManager.Query()
30771e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard                .orderBy(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP,
30871e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard                        DownloadManager.Query.ORDER_ASCENDING));
30971e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        checkAndCloseCursor(cursor, download1, download2, download3);
31071e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
31171e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        cursor = mManager.query(new DownloadManager.Query()
31271e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard                .orderBy(DownloadManager.COLUMN_TOTAL_SIZE_BYTES,
31371e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard                        DownloadManager.Query.ORDER_DESCENDING));
31471e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        checkAndCloseCursor(cursor, download2, download1, download3);
31571e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
31671e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        cursor = mManager.query(new DownloadManager.Query()
31771e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard                .orderBy(DownloadManager.COLUMN_TOTAL_SIZE_BYTES,
31871e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard                        DownloadManager.Query.ORDER_ASCENDING));
31971e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        checkAndCloseCursor(cursor, download3, download1, download2);
320df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
321df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
322df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    private void checkAndCloseCursor(Cursor cursor, Download... downloads) {
323df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        try {
324df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            int idIndex = cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
325df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            assertEquals(downloads.length, cursor.getCount());
326df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            cursor.moveToFirst();
327df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            for (Download download : downloads) {
328df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                assertEquals(download.mId, cursor.getLong(idIndex));
329df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard                cursor.moveToNext();
330df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            }
331df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        } finally {
332df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            cursor.close();
333df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        }
334df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
335df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
336df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    public void testInvalidUri() throws Exception {
337df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        try {
338df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            enqueueRequest(getRequest("/no_host"));
339df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        } catch (IllegalArgumentException exc) { // expected
340df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard            return;
341df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        }
342df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
343df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard        fail("No exception thrown for invalid URI");
344df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
345df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard
3466d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard    public void testDestination() throws Exception {
347ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
348f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard        Uri destination = getExternalUri();
3496d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        Download download = enqueueRequest(getRequest().setDestinationUri(destination));
3506d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
3516d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard
3526d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        Uri localUri = Uri.parse(download.getStringField(DownloadManager.COLUMN_LOCAL_URI));
3536d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        assertEquals(destination, localUri);
3546d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard
355b9a0ad7182209d4aca708e13e876e9b1b43ffafcSteve Howard        InputStream stream = new FileInputStream(destination.getPath());
3566d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        try {
3576d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard            assertEquals(FILE_CONTENT, readStream(stream));
3586d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        } finally {
3596d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard            stream.close();
3606d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard        }
3616d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard    }
3626d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard
363f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard    private Uri getExternalUri() {
3645d217003acf21aea852975af0dff3b398cea6768Vasu Nori        return Uri.fromFile(mTestDirectory).buildUpon().appendPath("testfile.txt").build();
365f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard    }
366f6b4c24b4a876daa3f4e91d6da418983222b9dfdSteve Howard
3675224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard    public void testRequestHeaders() throws Exception {
368ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
369ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard        Download download = enqueueRequest(getRequest().addRequestHeader("Header1", "value1")
370ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard                                           .addRequestHeader("Header2", "value2"));
371e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
3725224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard
373e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        List<String> headers = takeRequest().getHeaders();
374e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        assertTrue(headers.contains("Header1: value1"));
375e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        assertTrue(headers.contains("Header2: value2"));
3765224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard    }
3775224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard
3785224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard    public void testDelete() throws Exception {
379ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard        Download download = enqueueRequest(getRequest().addRequestHeader("header", "value"));
3805224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard        mManager.remove(download.mId);
3815224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard        Cursor cursor = mManager.query(new DownloadManager.Query());
3825224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard        try {
3835224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard            assertEquals(0, cursor.getCount());
3845224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard        } finally {
3855224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard            cursor.close();
3865224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard        }
3875224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard    }
3885224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard
389071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard    public void testSizeLimitOverMobile() throws Exception {
390ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
391ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
392071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard
393ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        mSystemFacade.mMaxBytesOverMobile = (long) FILE_CONTENT.length() - 1;
394071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
395071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        Download download = enqueueRequest(getRequest());
396071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
397071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard
398071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
399071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        // first response was read, but aborted after the DL manager processed the Content-Length
400071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        // header, so we need to enqueue a second one
401071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
402071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard    }
4030a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
404b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public void testRedirect301() throws Exception {
405b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        RecordedRequest lastRequest = runRedirectionTest(301);
406f85aa9ef563f2fbb3c0db6c980121122a14d953fSteve Howard        // for 301, upon retry/resume, we reuse the redirected URI
407b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        assertEquals(REDIRECTED_PATH, lastRequest.getPath());
408b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
409b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
410f85aa9ef563f2fbb3c0db6c980121122a14d953fSteve Howard    public void testRedirect302() throws Exception {
411b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        RecordedRequest lastRequest = runRedirectionTest(302);
412f85aa9ef563f2fbb3c0db6c980121122a14d953fSteve Howard        // for 302, upon retry/resume, we use the original URI
413b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        assertEquals(REQUEST_PATH, lastRequest.getPath());
414b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
415b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
41658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    public void testRunawayRedirect() throws Exception {
41758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        for (int i = 0; i < 16; i++) {
41858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            enqueueResponse(buildEmptyResponse(HTTP_MOVED_TEMP)
41958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey                    .setHeader("Location", mServer.getUrl("/" + i).toString()));
42058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        }
42158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
42258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        final Download download = enqueueRequest(getRequest());
42358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
42458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        // Ensure that we arrive at failed download, instead of spinning forever
42558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        download.runUntilStatus(DownloadManager.STATUS_FAILED);
42658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        assertEquals(DownloadManager.ERROR_TOO_MANY_REDIRECTS, download.getReason());
42758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    }
42858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
42958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    public void testRunawayUnavailable() throws Exception {
43058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        final int RETRY_DELAY = 120;
43158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        for (int i = 0; i < 16; i++) {
43258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            enqueueResponse(
43358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey                    buildEmptyResponse(HTTP_UNAVAILABLE).setHeader("Retry-after", RETRY_DELAY));
43458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        }
43558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
43658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        final Download download = enqueueRequest(getRequest());
43758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        for (int i = 0; i < Constants.MAX_RETRIES - 1; i++) {
43858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            download.runUntilStatus(DownloadManager.STATUS_PAUSED);
43958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            mSystemFacade.incrementTimeMillis((RETRY_DELAY + 60) * SECOND_IN_MILLIS);
44058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        }
44158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
44258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        // Ensure that we arrive at failed download, instead of spinning forever
44358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        download.runUntilStatus(DownloadManager.STATUS_FAILED);
44458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    }
44558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
446b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public void testNoEtag() throws Exception {
447ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildPartialResponse(0, 5).removeHeader("Etag"));
448adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard        runSimpleFailureTest(DownloadManager.ERROR_CANNOT_RESUME);
449b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
450b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
45158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    public void testEtagChanged() throws Exception {
45258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        final String A = "kittenz";
45358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        final String B = "puppiez";
45458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
45558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        // 1. Try downloading A, but partial result
45658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, A.substring(0, 2))
45758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey                .setHeader("Content-length", A.length())
45858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey                .setHeader("Etag", A));
45958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
46058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        // 2. Try resuming A, but fail ETag check
46158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_PRECON_FAILED));
46258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
46358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        final Download download = enqueueRequest(getRequest());
46458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        RecordedRequest req;
46558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
46658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        // 1. Try downloading A, but partial result
46758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        download.runUntilStatus(STATUS_PAUSED);
46858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        assertEquals(DownloadManager.PAUSED_WAITING_TO_RETRY, download.getReason());
46958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        req = takeRequest();
47058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        assertNull(getHeaderValue(req, "Range"));
47158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        assertNull(getHeaderValue(req, "If-Match"));
47258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
47358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        // 2. Try resuming A, but fail ETag check
47458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
47558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        download.runUntilStatus(STATUS_FAILED);
476dffbb9c4567e9d29d19964a83129e38dceab7055Jeff Sharkey        assertEquals(DownloadManager.ERROR_CANNOT_RESUME, download.getReason());
47758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        req = takeRequest();
47858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        assertEquals("bytes=2-", getHeaderValue(req, "Range"));
47958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        assertEquals(A, getHeaderValue(req, "If-Match"));
48058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    }
48158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
482b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public void testSanitizeMediaType() throws Exception {
483ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK)
484ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey                .setHeader("Content-Type", "text/html; charset=ISO-8859-4"));
485b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        Download download = enqueueRequest(getRequest());
486b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
487b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        assertEquals("text/html", download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
488b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
489b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
490b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public void testNoContentLength() throws Exception {
491ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK).removeHeader("Content-length"));
49212f5dc46aaa8e28cabfbe25d55f0af68f24ab306Jeff Sharkey        runSimpleFailureTest(DownloadManager.ERROR_CANNOT_RESUME);
493b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
494b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
495b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public void testInsufficientSpace() throws Exception {
496b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        // this would be better done by stubbing the system API to check available space, but in the
497b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        // meantime, just use an absurdly large header value
498ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK)
499ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey                .setHeader("Content-Length", 1024L * 1024 * 1024 * 1024 * 1024));
500b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        runSimpleFailureTest(DownloadManager.ERROR_INSUFFICIENT_SPACE);
501b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
502b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
503b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public void testCancel() throws Exception {
5045d217003acf21aea852975af0dff3b398cea6768Vasu Nori        // return 'real time' from FakeSystemFacade so that DownloadThread will report progress
5055d217003acf21aea852975af0dff3b398cea6768Vasu Nori        mSystemFacade.setReturnActualTime(true);
506ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildContinuingResponse());
507b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        Download download = enqueueRequest(getRequest());
5085d217003acf21aea852975af0dff3b398cea6768Vasu Nori        // give the download time to get started and progress to 1% completion
5095d217003acf21aea852975af0dff3b398cea6768Vasu Nori        // before cancelling it.
5105d217003acf21aea852975af0dff3b398cea6768Vasu Nori        boolean rslt = download.runUntilProgress(1);
5115d217003acf21aea852975af0dff3b398cea6768Vasu Nori        assertTrue(rslt);
512b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        mManager.remove(download.mId);
5138ac10e0e0667a4fe35191deebb5fa9786bf4226cJeff Sharkey
51458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        // Verify that row is removed from database
51558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        final long timeout = SystemClock.elapsedRealtime() + (15 * SECOND_IN_MILLIS);
51658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        while (download.getStatusIfExists() != -1) {
51758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            if (SystemClock.elapsedRealtime() > timeout) {
51858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey                throw new TimeoutException("Row wasn't removed");
51958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            }
52058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            SystemClock.sleep(100);
52158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        }
5220a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    }
5230a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5240a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    public void testDownloadCompleteBroadcast() throws Exception {
525ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
5260a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        Download download = enqueueRequest(getRequest());
5270a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
5280a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5290a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        assertEquals(1, mSystemFacade.mBroadcastsSent.size());
5300a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        Intent broadcast = mSystemFacade.mBroadcastsSent.get(0);
5310a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        assertEquals(DownloadManager.ACTION_DOWNLOAD_COMPLETE, broadcast.getAction());
5320a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        assertEquals(PACKAGE_NAME, broadcast.getPackage());
5330a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        long intentId = broadcast.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
5340a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        assertEquals(download.mId, intentId);
5350a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    }
5360a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5370a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    public void testNotificationClickedBroadcast() throws Exception {
5389da9df3d6e84a3c4b04dd22d277e0e6d8f7f1ccbSteve Howard        Download download = enqueueRequest(getRequest());
5390a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5400a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        DownloadReceiver receiver = new DownloadReceiver();
5410a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        receiver.mSystemFacade = mSystemFacade;
5420a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        Intent intent = new Intent(Constants.ACTION_LIST);
5430a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + download.mId));
544a40a349c0107660bfb4004467550725a3ca3ec97Jeff Sharkey        intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
545a40a349c0107660bfb4004467550725a3ca3ec97Jeff Sharkey                new long[] { download.mId });
5460a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        receiver.onReceive(mContext, intent);
5470a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5480a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        assertEquals(1, mSystemFacade.mBroadcastsSent.size());
5490a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        Intent broadcast = mSystemFacade.mBroadcastsSent.get(0);
5500a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        assertEquals(DownloadManager.ACTION_NOTIFICATION_CLICKED, broadcast.getAction());
5510a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        assertEquals(PACKAGE_NAME, broadcast.getPackage());
5520a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    }
5530a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
554e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    public void testBasicConnectivityChanges() throws Exception {
555ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
556ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
557961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey        // without connectivity, download immediately pauses
558961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey        mSystemFacade.mActiveNetworkType = null;
559e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        Download download = enqueueRequest(getRequest());
560e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
561e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
562e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        // connecting should start the download
563e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
564e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
565e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    }
566e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
5670a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    public void testAllowedNetworkTypes() throws Exception {
568ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
569ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
570ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
5710a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
5720a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5730a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        // by default, use any connection
5740a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        Download download = enqueueRequest(getRequest());
5750a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
5760a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5770a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        // restrict a download to wifi...
5780a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        download = enqueueRequest(getRequest()
5790a77c62a82503b38c484e0079648f0231dd85d53Steve Howard                                  .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI));
580e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
5810a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        // ...then enable wifi
5820a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
5830a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
5840a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    }
5850a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5860a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    public void testRoaming() throws Exception {
587ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
588ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
589ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
5900a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        mSystemFacade.mIsRoaming = true;
5910a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5920a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        // by default, allow roaming
5930a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        Download download = enqueueRequest(getRequest());
5940a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
5950a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
5960a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        // disallow roaming for a download...
5970a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        download = enqueueRequest(getRequest().setAllowedOverRoaming(false));
598e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
5990a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        // ...then turn off roaming
6000a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        mSystemFacade.mIsRoaming = false;
6010a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
602b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
603b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
604691fc58e9a61d99ab5018c5ddc8349ed413e4470Steve Howard    public void testContentObserver() throws Exception {
605ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
606691fc58e9a61d99ab5018c5ddc8349ed413e4470Steve Howard        mResolver.resetNotified();
6078ac10e0e0667a4fe35191deebb5fa9786bf4226cJeff Sharkey        final Download download = enqueueRequest(getRequest());
6088ac10e0e0667a4fe35191deebb5fa9786bf4226cJeff Sharkey        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
609691fc58e9a61d99ab5018c5ddc8349ed413e4470Steve Howard        assertTrue(mResolver.mNotifyWasCalled);
610691fc58e9a61d99ab5018c5ddc8349ed413e4470Steve Howard    }
611691fc58e9a61d99ab5018c5ddc8349ed413e4470Steve Howard
61236612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey    public void testNotificationNever() throws Exception {
613ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
614ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
61536612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        final Download download = enqueueRequest(
61636612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey                getRequest().setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN));
61793155e1da7e89d4925e244f5afa94afb8ada7381Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
61836612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey
6198ac10e0e0667a4fe35191deebb5fa9786bf4226cJeff Sharkey        verify(mNotifManager, times(1)).cancelAll();
620a40a349c0107660bfb4004467550725a3ca3ec97Jeff Sharkey        verify(mNotifManager, never()).notify(anyString(), anyInt(), isA(Notification.class));
62136612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey    }
62236612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey
62336612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey    public void testNotificationVisible() throws Exception {
62436612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
625e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
62636612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        // only shows in-progress notifications
62736612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        final Download download = enqueueRequest(getRequest());
62893155e1da7e89d4925e244f5afa94afb8ada7381Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
62936612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey
63036612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        // TODO: verify different notif types with tags
6318ac10e0e0667a4fe35191deebb5fa9786bf4226cJeff Sharkey        verify(mNotifManager, times(1)).cancelAll();
632a40a349c0107660bfb4004467550725a3ca3ec97Jeff Sharkey        verify(mNotifManager, atLeastOnce()).notify(anyString(), anyInt(), isA(Notification.class));
63336612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey    }
634e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
63536612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey    public void testNotificationVisibleComplete() throws Exception {
63636612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
63736612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey
63836612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        final Download download = enqueueRequest(getRequest().setNotificationVisibility(
63936612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED));
64036612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
64136612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey
64236612d27b67ff2e79ffff8eb12d95d2058abde02Jeff Sharkey        // TODO: verify different notif types with tags
6438ac10e0e0667a4fe35191deebb5fa9786bf4226cJeff Sharkey        verify(mNotifManager, times(1)).cancelAll();
644a40a349c0107660bfb4004467550725a3ca3ec97Jeff Sharkey        verify(mNotifManager, atLeastOnce()).notify(anyString(), anyInt(), isA(Notification.class));
645e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    }
646e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
647e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard    public void testRetryAfter() throws Exception {
648e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        final int delay = 120;
649ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(
65058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey                buildEmptyResponse(HTTP_UNAVAILABLE).setHeader("Retry-after", delay));
651ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
652ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
653e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        Download download = enqueueRequest(getRequest());
654e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
655e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard
656e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        // download manager adds random 0-30s offset
657e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        mSystemFacade.incrementTimeMillis((delay + 31) * 1000);
658e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
65993155e1da7e89d4925e244f5afa94afb8ada7381Steve Howard    }
66093155e1da7e89d4925e244f5afa94afb8ada7381Steve Howard
661dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard    public void testManyInterruptions() throws Exception {
662ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        final int length = FILE_CONTENT.length();
663ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        for (int i = 0; i < length; i++) {
664ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey            enqueueResponse(buildPartialResponse(i, i + 1));
665ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        }
666dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard
667dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        Download download = enqueueRequest(getRequest());
668ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        for (int i = 0; i < length - 1; i++) {
669dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard            download.runUntilStatus(DownloadManager.STATUS_PAUSED);
670dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard            mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
671dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        }
672dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard
673dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
674dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        checkCompleteDownload(download);
675dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard    }
676dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard
677adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard    public void testExistingFile() throws Exception {
678ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
679ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
6805d217003acf21aea852975af0dff3b398cea6768Vasu Nori        // download a file which already exists.
6815d217003acf21aea852975af0dff3b398cea6768Vasu Nori        // downloadservice should simply create filename with "-" and a number attached
6825d217003acf21aea852975af0dff3b398cea6768Vasu Nori        // at the end; i.e., download shouldnot fail.
683adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard        Uri destination = getExternalUri();
684b9a0ad7182209d4aca708e13e876e9b1b43ffafcSteve Howard        new File(destination.getPath()).createNewFile();
685adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard
686adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard        Download download = enqueueRequest(getRequest().setDestinationUri(destination));
6875d217003acf21aea852975af0dff3b398cea6768Vasu Nori        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
688adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard    }
689adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard
690a89321ea04ced76d06f60f5909be203cb654a830Steve Howard    public void testEmptyFields() throws Exception {
691a89321ea04ced76d06f60f5909be203cb654a830Steve Howard        Download download = enqueueRequest(getRequest());
692a89321ea04ced76d06f60f5909be203cb654a830Steve Howard        assertEquals("", download.getStringField(DownloadManager.COLUMN_TITLE));
693a89321ea04ced76d06f60f5909be203cb654a830Steve Howard        assertEquals("", download.getStringField(DownloadManager.COLUMN_DESCRIPTION));
694a89321ea04ced76d06f60f5909be203cb654a830Steve Howard        assertNull(download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
695a89321ea04ced76d06f60f5909be203cb654a830Steve Howard        assertEquals(0, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
696a89321ea04ced76d06f60f5909be203cb654a830Steve Howard        assertEquals(-1, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
697a89321ea04ced76d06f60f5909be203cb654a830Steve Howard        // just ensure no exception is thrown
698b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        download.getLongField(DownloadManager.COLUMN_REASON);
699a89321ea04ced76d06f60f5909be203cb654a830Steve Howard    }
700a89321ea04ced76d06f60f5909be203cb654a830Steve Howard
70171e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard    public void testRestart() throws Exception {
702ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
703ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(HTTP_OK));
704ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey
70571e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        Download download = enqueueRequest(getRequest());
70671e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        download.runUntilStatus(DownloadManager.STATUS_FAILED);
70771e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
70871e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        mManager.restartDownload(download.mId);
70971e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        assertEquals(DownloadManager.STATUS_PENDING,
71071e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard                download.getLongField(DownloadManager.COLUMN_STATUS));
71171e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
71271e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard    }
71371e7fda9135a0915af1fd419d07ebf85ad09beb4Steve Howard
714dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard    private void checkCompleteDownload(Download download) throws Exception {
715dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        assertEquals(FILE_CONTENT.length(),
716dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard                     download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
717dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard        assertEquals(FILE_CONTENT, download.getContents());
718dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard    }
719dea0a5f8e5804d3aba40eaa7de763dd88058384eSteve Howard
720b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    private void runSimpleFailureTest(int expectedErrorCode) throws Exception {
721b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        Download download = enqueueRequest(getRequest());
722b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        download.runUntilStatus(DownloadManager.STATUS_FAILED);
723b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        assertEquals(expectedErrorCode,
724b108a273b150e81bf26553b8851d6241bc711f98Steve Howard                     download.getLongField(DownloadManager.COLUMN_REASON));
725b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    }
726b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
727b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    /**
728b5629da794cb3c1ca1970d206343743b165b9644Steve Howard     * Run a redirection test consisting of
729b5629da794cb3c1ca1970d206343743b165b9644Steve Howard     * 1) Request to REQUEST_PATH with 3xx response redirecting to another URI
730b5629da794cb3c1ca1970d206343743b165b9644Steve Howard     * 2) Request to REDIRECTED_PATH with interrupted partial response
731b5629da794cb3c1ca1970d206343743b165b9644Steve Howard     * 3) Resume request to complete download
732b5629da794cb3c1ca1970d206343743b165b9644Steve Howard     * @return the last request sent to the server, resuming after the interruption
733b5629da794cb3c1ca1970d206343743b165b9644Steve Howard     */
73458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    private RecordedRequest runRedirectionTest(int status) throws Exception {
735ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey        enqueueResponse(buildEmptyResponse(status)
736ae6856b0fca5215f45619dd031a7e7beae7bd8ccJeff Sharkey                .setHeader("Location", mServer.getUrl(REDIRECTED_PATH).toString()));
737b5629da794cb3c1ca1970d206343743b165b9644Steve Howard        enqueueInterruptedDownloadResponses(5);
738b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
739a85832b4772626852142b60c4806ff5384a76478Jeff Sharkey        final Download download = enqueueRequest(getRequest());
740a85832b4772626852142b60c4806ff5384a76478Jeff Sharkey        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
741a85832b4772626852142b60c4806ff5384a76478Jeff Sharkey        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
742a85832b4772626852142b60c4806ff5384a76478Jeff Sharkey        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
743a85832b4772626852142b60c4806ff5384a76478Jeff Sharkey
744e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        assertEquals(REQUEST_PATH, takeRequest().getPath());
745e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        assertEquals(REDIRECTED_PATH, takeRequest().getPath());
746b5629da794cb3c1ca1970d206343743b165b9644Steve Howard
747e6a05a1aa4697440e9630d12b741b3bae321fe49Steve Howard        return takeRequest();
748df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard    }
74958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey
75058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    /**
75158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey     * Return value of requested HTTP header, if it exists.
75258eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey     */
75358eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    private static String getHeaderValue(RecordedRequest req, String header) {
75458eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        header = header.toLowerCase() + ":";
75558eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        for (String h : req.getHeaders()) {
75658eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            if (h.toLowerCase().startsWith(header)) {
75758eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey                return h.substring(header.length()).trim();
75858eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey            }
75958eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        }
76058eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey        return null;
76158eee87b70862a7ced85eabc3c225fad24664065Jeff Sharkey    }
762df71633a02ce2f1b6228dad1ba3198185edf6107Steve Howard}
763