/*
 * Copyright (C) 2010 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.providers.downloads;

import static android.app.DownloadManager.STATUS_FAILED;
import static android.app.DownloadManager.STATUS_PAUSED;
import static android.net.TrafficStats.GB_IN_BYTES;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;

import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.net.HttpURLConnection.HTTP_PARTIAL;
import static java.net.HttpURLConnection.HTTP_PRECON_FAILED;
import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;

import android.app.BroadcastOptions;
import android.app.DownloadManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Intent;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.Downloads;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
import android.text.format.DateUtils;

import androidx.test.filters.FlakyTest;

import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.RecordedRequest;
import com.google.mockwebserver.SocketPolicy;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

@LargeTest
public class PublicApiFunctionalTest extends AbstractPublicApiTest {
    private static final String REDIRECTED_PATH = "/other_path";
    private static final String ETAG = "my_etag";

    protected File mTestDirectory;
    private NotificationManager mNotifManager;
    private DownloadManager mDownloadManager;

    public PublicApiFunctionalTest() {
        super(new FakeSystemFacade());
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        mNotifManager = getContext().getSystemService(NotificationManager.class);
        mDownloadManager = getContext().getSystemService(DownloadManager.class);

        mTestDirectory = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOWNLOADS)
                + File.separator + "download_manager_functional_test");
        if (mTestDirectory.exists()) {
            FsHelper.deleteContents(mTestDirectory);
        } else {
            mTestDirectory.mkdir();
        }
    }

    @Override
    protected void tearDown() throws Exception {
        if (mTestDirectory != null && mTestDirectory.exists()) {
            FsHelper.deleteContents(mTestDirectory);
            mTestDirectory.delete();
        }
        super.tearDown();
    }

    public void testBasicRequest() throws Exception {
        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));

        Download download = enqueueRequest(getRequest());
        assertEquals(DownloadManager.STATUS_PENDING,
                     download.getLongField(DownloadManager.COLUMN_STATUS));
        assertEquals(getServerUri(REQUEST_PATH),
                     download.getStringField(DownloadManager.COLUMN_URI));
        assertEquals(download.mId, download.getLongField(DownloadManager.COLUMN_ID));
        assertEquals(mSystemFacade.currentTimeMillis(),
                     download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));

        mSystemFacade.incrementTimeMillis(10);
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
        RecordedRequest request = takeRequest();
        assertEquals("GET", request.getMethod());
        assertEquals(REQUEST_PATH, request.getPath());

        Uri localUri = Uri.parse(download.getStringField(DownloadManager.COLUMN_LOCAL_URI));
        assertEquals("content", localUri.getScheme());
        checkUriContent(localUri);
        assertEquals("text/plain", download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));

        int size = FILE_CONTENT.length();
        assertEquals(size, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
        assertEquals(size, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
        assertEquals(mSystemFacade.currentTimeMillis(),
                     download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));

        checkCompleteDownload(download);
    }

    @Suppress
    public void testExtremelyLarge() throws Exception {
        // NOTE: suppressed since this takes several minutes to run
        final long length = 3 * GB_IN_BYTES;
        final InputStream body = new FakeInputStream(length);

        enqueueResponse(new MockResponse().setResponseCode(HTTP_OK).setBody(body, length)
                .setHeader("Content-type", "text/plain")
                .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END));

        final Download download = enqueueRequest(getRequest()
                .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "extreme.bin"));
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL, 10 * DateUtils.MINUTE_IN_MILLIS);

        assertEquals(length, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
        assertEquals(length, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
    }

    private void checkUriContent(Uri uri) throws FileNotFoundException, IOException {
        InputStream inputStream = mResolver.openInputStream(uri);
        try {
            assertEquals(FILE_CONTENT, readStream(inputStream));
        } finally {
            inputStream.close();
        }
    }

    public void testTitleAndDescription() throws Exception {
        Download download = enqueueRequest(getRequest()
                                           .setTitle("my title")
                                           .setDescription("my description"));
        assertEquals("my title", download.getStringField(DownloadManager.COLUMN_TITLE));
        assertEquals("my description",
                     download.getStringField(DownloadManager.COLUMN_DESCRIPTION));
    }

    public void testDownloadError() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
        runSimpleFailureTest(HTTP_NOT_FOUND);
    }

    public void testUnhandledHttpStatus() throws Exception {
        enqueueResponse(buildEmptyResponse(1234)); // some invalid HTTP status
        runSimpleFailureTest(DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
    }

    public void testInterruptedDownload() throws Exception {
        int initialLength = 5;
        enqueueInterruptedDownloadResponses(initialLength);

        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
        assertEquals(initialLength,
                     download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
        assertEquals(FILE_CONTENT.length(),
                     download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
        takeRequest(); // get the first request out of the queue

        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
        checkCompleteDownload(download);

        List<String> headers = takeRequest().getHeaders();
        assertTrue("No Range header: " + headers,
                   headers.contains("Range: bytes=" + initialLength + "-"));
        assertTrue("No ETag header: " + headers, headers.contains("If-Match: " + ETAG));
    }

    public void testInterruptedExternalDownload() throws Exception {
        enqueueInterruptedDownloadResponses(5);
        Download download = enqueueRequest(getRequest().setDestinationUri(getExternalUri()));
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
        checkCompleteDownload(download);
    }

    private void enqueueInterruptedDownloadResponses(int initialLength) {
        // the first response has normal headers but unexpectedly closes after initialLength bytes
        enqueueResponse(buildPartialResponse(0, initialLength));
        // the second response returns partial content for the rest of the data
        enqueueResponse(buildPartialResponse(initialLength, FILE_CONTENT.length()));
    }

    private MockResponse buildPartialResponse(int start, int end) {
        int totalLength = FILE_CONTENT.length();
        boolean isFirstResponse = (start == 0);
        int status = isFirstResponse ? HTTP_OK : HTTP_PARTIAL;
        MockResponse response = buildResponse(status, FILE_CONTENT.substring(start, end))
                .setHeader("Content-length", isFirstResponse ? totalLength : (end - start))
                .setHeader("Etag", ETAG);
        if (!isFirstResponse) {
            response.setHeader(
                    "Content-range", "bytes " + start + "-" + totalLength + "/" + totalLength);
        }
        return response;
    }

    // enqueue a huge response to keep the receiveing thread in DownloadThread.java busy for a while
    // give enough time to do something (cancel/remove etc) on that downloadrequest
    // while it is in progress
    private MockResponse buildContinuingResponse() {
        int numPackets = 100;
        int contentLength = STRING_1K.length() * numPackets;
        return buildResponse(HTTP_OK, STRING_1K)
               .setHeader("Content-length", contentLength)
               .setHeader("Etag", ETAG)
               .throttleBody(1024, 1, TimeUnit.SECONDS);
    }

    public void testFiltering() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));
        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));

        Download download1 = enqueueRequest(getRequestWithDestinationDownloadsDir());
        download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        mSystemFacade.incrementTimeMillis(1); // ensure downloads are correctly ordered by time
        Download download2 = enqueueRequest(getRequestWithDestinationDownloadsDir());
        download2.runUntilStatus(DownloadManager.STATUS_FAILED);

        mSystemFacade.incrementTimeMillis(1);
        Download download3 = enqueueRequest(getRequestWithDestinationDownloadsDir());

        Cursor cursor = mManager.query(new DownloadManager.Query());
        checkAndCloseCursor(cursor, download3, download2, download1);

        cursor = mManager.query(new DownloadManager.Query().setFilterById(download2.mId));
        checkAndCloseCursor(cursor, download2);

        cursor = mManager.query(new DownloadManager.Query()
                                .setFilterByStatus(DownloadManager.STATUS_PENDING));
        checkAndCloseCursor(cursor, download3);

        cursor = mManager.query(new DownloadManager.Query()
                                .setFilterByStatus(DownloadManager.STATUS_FAILED
                                              | DownloadManager.STATUS_SUCCESSFUL));
        checkAndCloseCursor(cursor, download2, download1);

        cursor = mManager.query(new DownloadManager.Query()
                                .setFilterByStatus(DownloadManager.STATUS_RUNNING));
        checkAndCloseCursor(cursor);

        mSystemFacade.incrementTimeMillis(1);
        Download invisibleDownload = enqueueRequest(getRequest().setVisibleInDownloadsUi(false));
        cursor = mManager.query(new DownloadManager.Query());
        checkAndCloseCursor(cursor, invisibleDownload, download3, download2, download1);
        cursor = mManager.query(new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true));
        checkAndCloseCursor(cursor, download3, download2, download1);
    }

    public void testOrdering() throws Exception {
        enqueueResponse(buildResponse(HTTP_OK, "small contents"));
        enqueueResponse(buildResponse(HTTP_OK, "large contents large contents"));
        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));

        Download download1 = enqueueRequest(getRequest());
        download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        mSystemFacade.incrementTimeMillis(1);
        Download download2 = enqueueRequest(getRequest());
        download2.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        mSystemFacade.incrementTimeMillis(1);
        Download download3 = enqueueRequest(getRequest());
        download3.runUntilStatus(DownloadManager.STATUS_FAILED);

        // default ordering -- by timestamp descending
        Cursor cursor = mManager.query(new DownloadManager.Query());
        checkAndCloseCursor(cursor, download3, download2, download1);

        cursor = mManager.query(new DownloadManager.Query()
                .orderBy(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP,
                        DownloadManager.Query.ORDER_ASCENDING));
        checkAndCloseCursor(cursor, download1, download2, download3);

        cursor = mManager.query(new DownloadManager.Query()
                .orderBy(DownloadManager.COLUMN_TOTAL_SIZE_BYTES,
                        DownloadManager.Query.ORDER_DESCENDING));
        checkAndCloseCursor(cursor, download2, download1, download3);

        cursor = mManager.query(new DownloadManager.Query()
                .orderBy(DownloadManager.COLUMN_TOTAL_SIZE_BYTES,
                        DownloadManager.Query.ORDER_ASCENDING));
        checkAndCloseCursor(cursor, download3, download1, download2);
    }

    private void checkAndCloseCursor(Cursor cursor, Download... downloads) {
        try {
            int idIndex = cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
            assertEquals(downloads.length, cursor.getCount());
            cursor.moveToFirst();
            for (Download download : downloads) {
                assertEquals(download.mId, cursor.getLong(idIndex));
                cursor.moveToNext();
            }
        } finally {
            cursor.close();
        }
    }

    public void testInvalidUri() throws Exception {
        try {
            enqueueRequest(getRequest("/no_host"));
        } catch (IllegalArgumentException exc) { // expected
            return;
        }

        fail("No exception thrown for invalid URI");
    }

    public void testDestination() throws Exception {
        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
        Uri destination = getExternalUri();
        Download download = enqueueRequest(getRequest().setDestinationUri(destination));
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        Uri localUri = Uri.parse(download.getStringField(DownloadManager.COLUMN_LOCAL_URI));
        assertEquals(destination, localUri);

        InputStream stream = new FileInputStream(destination.getPath());
        try {
            assertEquals(FILE_CONTENT, readStream(stream));
        } finally {
            stream.close();
        }
    }

    private Uri getExternalUri() {
        return Uri.fromFile(mTestDirectory).buildUpon().appendPath("testfile.txt").build();
    }

    public void testRequestHeaders() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));
        Download download = enqueueRequest(getRequest().addRequestHeader("Header1", "value1")
                                           .addRequestHeader("Header2", "value2"));
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        List<String> headers = takeRequest().getHeaders();
        assertTrue(headers.contains("Header1: value1"));
        assertTrue(headers.contains("Header2: value2"));
    }

    public void testDelete() throws Exception {
        Download download = enqueueRequest(getRequest().addRequestHeader("header", "value"));
        mManager.remove(download.mId);
        Cursor cursor = mManager.query(new DownloadManager.Query());
        try {
            assertEquals(0, cursor.getCount());
        } finally {
            cursor.close();
        }
    }

    public void testSizeLimitOverMobile() throws Exception {
        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));

        mSystemFacade.mMaxBytesOverMobile = (long) FILE_CONTENT.length() - 1;
        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
        mSystemFacade.mIsMetered = true;
        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);

        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
        mSystemFacade.mIsMetered = false;
        // first response was read, but aborted after the DL manager processed the Content-Length
        // header, so we need to enqueue a second one
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
    }

    public void testRedirect301() throws Exception {
        RecordedRequest lastRequest = runRedirectionTest(301);
        // for 301, upon retry/resume, we reuse the redirected URI
        assertEquals(REDIRECTED_PATH, lastRequest.getPath());
    }

    public void testRedirect302() throws Exception {
        RecordedRequest lastRequest = runRedirectionTest(302);
        // for 302, upon retry/resume, we use the original URI
        assertEquals(REQUEST_PATH, lastRequest.getPath());
    }

    public void testRunawayRedirect() throws Exception {
        for (int i = 0; i < 16; i++) {
            enqueueResponse(buildEmptyResponse(HTTP_MOVED_TEMP)
                    .setHeader("Location", mServer.getUrl("/" + i).toString()));
        }

        final Download download = enqueueRequest(getRequest());

        // Ensure that we arrive at failed download, instead of spinning forever
        download.runUntilStatus(DownloadManager.STATUS_FAILED);
        assertEquals(DownloadManager.ERROR_TOO_MANY_REDIRECTS, download.getReason());
    }

    public void testRunawayUnavailable() throws Exception {
        final int RETRY_DELAY = 120;
        for (int i = 0; i < 16; i++) {
            enqueueResponse(
                    buildEmptyResponse(HTTP_UNAVAILABLE).setHeader("Retry-after", RETRY_DELAY));
        }

        final Download download = enqueueRequest(getRequest());
        for (int i = 0; i < Constants.MAX_RETRIES - 1; i++) {
            download.runUntilStatus(DownloadManager.STATUS_PAUSED);
            mSystemFacade.incrementTimeMillis((RETRY_DELAY + 60) * SECOND_IN_MILLIS);
        }

        // Ensure that we arrive at failed download, instead of spinning forever
        download.runUntilStatus(DownloadManager.STATUS_FAILED);
    }

    public void testNoEtag() throws Exception {
        enqueueResponse(buildPartialResponse(0, 5).removeHeader("Etag"));
        runSimpleFailureTest(DownloadManager.ERROR_CANNOT_RESUME);
    }

    public void testEtagChanged() throws Exception {
        final String A = "kittenz";
        final String B = "puppiez";

        // 1. Try downloading A, but partial result
        enqueueResponse(buildResponse(HTTP_OK, A.substring(0, 2))
                .setHeader("Content-length", A.length())
                .setHeader("Etag", A));

        // 2. Try resuming A, but fail ETag check
        enqueueResponse(buildEmptyResponse(HTTP_PRECON_FAILED));

        final Download download = enqueueRequest(getRequest());
        RecordedRequest req;

        // 1. Try downloading A, but partial result
        download.runUntilStatus(STATUS_PAUSED);
        assertEquals(DownloadManager.PAUSED_WAITING_TO_RETRY, download.getReason());
        req = takeRequest();
        assertNull(getHeaderValue(req, "Range"));
        assertNull(getHeaderValue(req, "If-Match"));

        // 2. Try resuming A, but fail ETag check
        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
        download.runUntilStatus(STATUS_FAILED);
        assertEquals(DownloadManager.ERROR_CANNOT_RESUME, download.getReason());
        req = takeRequest();
        assertEquals("bytes=2-", getHeaderValue(req, "Range"));
        assertEquals(A, getHeaderValue(req, "If-Match"));
    }

    public void testSanitizeMediaType() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK)
                .setHeader("Content-Type", "text/html; charset=ISO-8859-4"));
        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
        assertEquals("text/html", download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
    }

    public void testNoContentLength() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK).removeHeader("Content-length"));
        runSimpleFailureTest(DownloadManager.ERROR_CANNOT_RESUME);
    }

    public void testInsufficientSpace() throws Exception {
        // this would be better done by stubbing the system API to check available space, but in the
        // meantime, just use an absurdly large header value
        enqueueResponse(buildEmptyResponse(HTTP_OK)
                .setHeader("Content-Length", 1024L * 1024 * 1024 * 1024 * 1024));
        runSimpleFailureTest(DownloadManager.ERROR_INSUFFICIENT_SPACE);
    }

    public void testCancel() throws Exception {
        // return 'real time' from FakeSystemFacade so that DownloadThread will report progress
        mSystemFacade.setReturnActualTime(true);
        enqueueResponse(buildContinuingResponse());
        Download download = enqueueRequest(getRequest());
        // give the download time to get started and progress to 1% completion
        // before cancelling it.
        boolean rslt = download.runUntilProgress(1);
        assertTrue(rslt);
        mManager.remove(download.mId);

        // Verify that row is removed from database
        final long timeout = SystemClock.elapsedRealtime() + (15 * SECOND_IN_MILLIS);
        while (download.getStatusIfExists() != -1) {
            if (SystemClock.elapsedRealtime() > timeout) {
                throw new TimeoutException("Row wasn't removed");
            }
            SystemClock.sleep(100);
        }
    }

    public void testDownloadCompleteBroadcast() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));
        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        assertEquals(1, mSystemFacade.mBroadcastsSent.size());
        Intent broadcast = mSystemFacade.mBroadcastsSent.get(0);
        assertEquals(DownloadManager.ACTION_DOWNLOAD_COMPLETE, broadcast.getAction());
        assertEquals(PACKAGE_NAME, broadcast.getPackage());
        long intentId = broadcast.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
        assertEquals(download.mId, intentId);
    }

    public void testNotificationClickedBroadcast() throws Exception {
        Download download = enqueueRequest(getRequest());

        DownloadReceiver receiver = new DownloadReceiver();
        Helpers.setSystemFacade(mSystemFacade);
        Intent intent = new Intent(Constants.ACTION_LIST);
        intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + download.mId));
        intent.putExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS,
                new long[] { download.mId });
        receiver.onReceive(mContext, intent);

        assertEquals(1, mSystemFacade.mBroadcastsSent.size());
        Intent broadcast = mSystemFacade.mBroadcastsSent.get(0);
        assertEquals(DownloadManager.ACTION_NOTIFICATION_CLICKED, broadcast.getAction());
        assertEquals(PACKAGE_NAME, broadcast.getPackage());

        Bundle bOptions = mSystemFacade.mLastBroadcastOptions;
        assertNotNull(bOptions);
        BroadcastOptions brOptions = new BroadcastOptions(bOptions);
        assertTrue(brOptions.allowsBackgroundActivityStarts());
    }

    public void testNotificationCancelDownloadClicked() throws Exception {
        Download download = enqueueRequest(getRequest());

        DownloadReceiver receiver = new DownloadReceiver();
        Helpers.setSystemFacade(mSystemFacade);
        Intent intent = new Intent(Constants.ACTION_CANCEL);
        intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + download.mId));

        long[] downloadIds = {download.mId};
        intent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_IDS, downloadIds);
        intent.putExtra(DownloadReceiver.EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG, "tag");
        receiver.onReceive(mContext, intent);

        verify(mNotifManager, times(1)).cancel("tag", 0);
        verify(mDownloadManager, times(1)).remove(downloadIds);
    }

    public void testBasicConnectivityChanges() throws Exception {
        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));

        // without connectivity, download immediately pauses
        mSystemFacade.mActiveNetworkType = null;
        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);

        // connecting should start the download
        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
    }

    public void testAllowedNetworkTypes() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
        mSystemFacade.mIsMetered = true;

        // by default, use any connection
        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        // restrict a download to wifi...
        download = enqueueRequest(getRequest()
                                  .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI));
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
        // ...then enable wifi
        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
        mSystemFacade.mIsMetered = false;
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
    }

    public void testRoaming() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        mSystemFacade.mIsRoaming = true;

        // by default, allow roaming
        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        // disallow roaming for a download...
        download = enqueueRequest(getRequest().setAllowedOverRoaming(false));
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
        // ...then turn off roaming
        mSystemFacade.mIsRoaming = false;
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
    }

    public void testContentObserver() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));
        mResolver.resetNotified();
        final Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
        assertTrue(mResolver.mNotifyWasCalled);
    }

    @Suppress
    public void testNotificationNever() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        final Download download = enqueueRequest(
                getRequest().setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN));
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        // TODO: verify different notif types with tags
        verify(mNotifManager, never()).notify(anyString(), anyInt(), isA(Notification.class));
    }

    @Suppress
    public void testNotificationVisible() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        // only shows in-progress notifications
        final Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        // TODO: verify different notif types with tags
        verify(mNotifManager, atLeastOnce()).notify(anyString(), anyInt(), isA(Notification.class));
    }

    @Suppress
    public void testNotificationVisibleComplete() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        final Download download = enqueueRequest(getRequest().setNotificationVisibility(
                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED));
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        // TODO: verify different notif types with tags
        verify(mNotifManager, atLeastOnce()).notify(anyString(), anyInt(), isA(Notification.class));
    }

    public void testRetryAfter() throws Exception {
        final int delay = 120;
        enqueueResponse(
                buildEmptyResponse(HTTP_UNAVAILABLE).setHeader("Retry-after", delay));
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);

        // download manager adds random 0-30s offset
        mSystemFacade.incrementTimeMillis((delay + 31) * 1000);
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
    }

    @FlakyTest(bugId = 177499952)
    public void testManyInterruptions() throws Exception {
        final int length = FILE_CONTENT.length();
        for (int i = 0; i < length; i++) {
            enqueueResponse(buildPartialResponse(i, i + 1));
        }

        Download download = enqueueRequest(getRequest());
        for (int i = 0; i < length - 1; i++) {
            download.runUntilStatus(DownloadManager.STATUS_PAUSED);
            mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
        }

        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
        checkCompleteDownload(download);
    }

    public void testExistingFile() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        // download a file which already exists.
        // downloadservice should simply create filename with "-" and a number attached
        // at the end; i.e., download shouldnot fail.
        Uri destination = getExternalUri();
        new File(destination.getPath()).createNewFile();

        Download download = enqueueRequest(getRequest().setDestinationUri(destination));
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
    }

    public void testEmptyFields() throws Exception {
        Download download = enqueueRequest(getRequest());
        assertEquals("", download.getStringField(DownloadManager.COLUMN_TITLE));
        assertEquals("", download.getStringField(DownloadManager.COLUMN_DESCRIPTION));
        assertNull(download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
        assertEquals(0, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
        assertEquals(-1, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
        // just ensure no exception is thrown
        download.getLongField(DownloadManager.COLUMN_REASON);
    }

    public void testRestart() throws Exception {
        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
        enqueueResponse(buildEmptyResponse(HTTP_OK));

        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_FAILED);

        mManager.restartDownload(download.mId);
        assertEquals(DownloadManager.STATUS_PENDING,
                download.getLongField(DownloadManager.COLUMN_STATUS));
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
    }

    private void checkCompleteDownload(Download download) throws Exception {
        assertEquals(FILE_CONTENT.length(),
                     download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
        assertEquals(FILE_CONTENT, download.getContents());
    }

    private void runSimpleFailureTest(int expectedErrorCode) throws Exception {
        Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_FAILED);
        assertEquals(expectedErrorCode,
                     download.getLongField(DownloadManager.COLUMN_REASON));
    }

    /**
     * Run a redirection test consisting of
     * 1) Request to REQUEST_PATH with 3xx response redirecting to another URI
     * 2) Request to REDIRECTED_PATH with interrupted partial response
     * 3) Resume request to complete download
     * @return the last request sent to the server, resuming after the interruption
     */
    private RecordedRequest runRedirectionTest(int status) throws Exception {
        enqueueResponse(buildEmptyResponse(status)
                .setHeader("Location", mServer.getUrl(REDIRECTED_PATH).toString()));
        enqueueInterruptedDownloadResponses(5);

        final Download download = enqueueRequest(getRequest());
        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);

        assertEquals(REQUEST_PATH, takeRequest().getPath());
        assertEquals(REDIRECTED_PATH, takeRequest().getPath());

        return takeRequest();
    }

    /**
     * Return value of requested HTTP header, if it exists.
     */
    private static String getHeaderValue(RecordedRequest req, String header) {
        header = header.toLowerCase() + ":";
        for (String h : req.getHeaders()) {
            if (h.toLowerCase().startsWith(header)) {
                return h.substring(header.length()).trim();
            }
        }
        return null;
    }
}
