1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.providers.downloads;
18
19import android.content.ContentValues;
20import android.database.Cursor;
21import android.net.ConnectivityManager;
22import android.net.Uri;
23import android.os.Environment;
24import android.provider.Downloads;
25import android.test.suitebuilder.annotation.LargeTest;
26import android.util.Log;
27
28import tests.http.MockWebServer;
29import tests.http.RecordedRequest;
30
31import java.io.InputStream;
32import java.net.MalformedURLException;
33
34/**
35 * This test exercises the entire download manager working together -- it requests downloads through
36 * the {@link DownloadProvider}, just like a normal client would, and runs the
37 * {@link DownloadService} with start intents.  It sets up a {@link MockWebServer} running on the
38 * device to serve downloads.
39 */
40@LargeTest
41public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFunctionalTest {
42    private static final String TAG = "DownloadManagerFunctionalTest";
43
44    public DownloadManagerFunctionalTest() {
45        super(new FakeSystemFacade());
46    }
47
48    public void testDownloadTextFile() throws Exception {
49        enqueueResponse(HTTP_OK, FILE_CONTENT);
50
51        String path = "/download_manager_test_path";
52        Uri downloadUri = requestDownload(path);
53        assertEquals(Downloads.Impl.STATUS_PENDING, getDownloadStatus(downloadUri));
54        assertTrue(mTestContext.mHasServiceBeenStarted);
55
56        runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
57        RecordedRequest request = takeRequest();
58        assertEquals("GET", request.getMethod());
59        assertEquals(path, request.getPath());
60        assertEquals(FILE_CONTENT, getDownloadContents(downloadUri));
61        assertStartsWith(Environment.getExternalStorageDirectory().getPath(),
62                         getDownloadFilename(downloadUri));
63    }
64
65    public void testDownloadToCache() throws Exception {
66        enqueueResponse(HTTP_OK, FILE_CONTENT);
67        Uri downloadUri = requestDownload("/path");
68        updateDownload(downloadUri, Downloads.Impl.COLUMN_DESTINATION,
69                       Integer.toString(Downloads.Impl.DESTINATION_CACHE_PARTITION));
70        runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
71        assertEquals(FILE_CONTENT, getDownloadContents(downloadUri));
72        assertStartsWith(getContext().getCacheDir().getAbsolutePath(),
73                         getDownloadFilename(downloadUri));
74    }
75
76    public void testRoaming() throws Exception {
77        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
78        mSystemFacade.mIsRoaming = true;
79
80        // for a normal download, roaming is fine
81        enqueueResponse(HTTP_OK, FILE_CONTENT);
82        Uri downloadUri = requestDownload("/path");
83        runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
84
85        // when roaming is disallowed, the download should pause...
86        downloadUri = requestDownload("/path");
87        updateDownload(downloadUri, Downloads.Impl.COLUMN_DESTINATION,
88                       Integer.toString(Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING));
89        runUntilStatus(downloadUri, Downloads.Impl.STATUS_WAITING_FOR_NETWORK);
90
91        // ...and pick up when we're off roaming
92        enqueueResponse(HTTP_OK, FILE_CONTENT);
93        mSystemFacade.mIsRoaming = false;
94        runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
95    }
96
97    /**
98     * Read a downloaded file from disk.
99     */
100    private String getDownloadContents(Uri downloadUri) throws Exception {
101        InputStream inputStream = mResolver.openInputStream(downloadUri);
102        try {
103            return readStream(inputStream);
104        } finally {
105            inputStream.close();
106        }
107    }
108
109    private void runUntilStatus(Uri downloadUri, int status) throws Exception {
110        runService();
111        boolean done = false;
112        while (!done) {
113            int rslt = getDownloadStatus(downloadUri);
114            if (rslt == Downloads.Impl.STATUS_RUNNING || rslt == Downloads.Impl.STATUS_PENDING) {
115                Log.i(TAG, "status is: " + rslt + ", for: " + downloadUri);
116                DownloadHandler.getInstance().WaitUntilDownloadsTerminate();
117                Thread.sleep(100);
118            } else {
119                done = true;
120            }
121        }
122        assertEquals(status, getDownloadStatus(downloadUri));
123    }
124
125    protected int getDownloadStatus(Uri downloadUri) {
126        return Integer.valueOf(getDownloadField(downloadUri, Downloads.Impl.COLUMN_STATUS));
127    }
128
129    private String getDownloadFilename(Uri downloadUri) {
130        return getDownloadField(downloadUri, Downloads.Impl._DATA);
131    }
132
133    private String getDownloadField(Uri downloadUri, String column) {
134        final String[] columns = new String[] {column};
135        Cursor cursor = mResolver.query(downloadUri, columns, null, null, null);
136        try {
137            assertEquals(1, cursor.getCount());
138            cursor.moveToFirst();
139            return cursor.getString(0);
140        } finally {
141            cursor.close();
142        }
143    }
144
145    /**
146     * Request a download from the Download Manager.
147     */
148    private Uri requestDownload(String path) throws MalformedURLException {
149        ContentValues values = new ContentValues();
150        values.put(Downloads.Impl.COLUMN_URI, getServerUri(path));
151        values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_EXTERNAL);
152        return mResolver.insert(Downloads.Impl.CONTENT_URI, values);
153    }
154
155    /**
156     * Update one field of a download in the provider.
157     */
158    private void updateDownload(Uri downloadUri, String column, String value) {
159        ContentValues values = new ContentValues();
160        values.put(column, value);
161        int numChanged = mResolver.update(downloadUri, values, null, null);
162        assertEquals(1, numChanged);
163    }
164}
165