48eb0b4726c65376af679802e38dbff92277ca79
[android/platform/packages/providers/DownloadProvider.git] / tests / src / com / android / providers / downloads / AbstractDownloadProviderFunctionalTest.java
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.providers.downloads;
18
19 import static com.google.testing.littlemock.LittleMock.mock;
20
21 import android.app.NotificationManager;
22 import android.content.ComponentName;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.database.ContentObserver;
27 import android.database.Cursor;
28 import android.net.Uri;
29 import android.provider.Downloads;
30 import android.test.MoreAsserts;
31 import android.test.RenamingDelegatingContext;
32 import android.test.ServiceTestCase;
33 import android.test.mock.MockContentResolver;
34 import android.util.Log;
35
36 import com.google.mockwebserver.MockResponse;
37 import com.google.mockwebserver.MockWebServer;
38 import com.google.mockwebserver.RecordedRequest;
39 import com.google.mockwebserver.SocketPolicy;
40
41 import java.io.BufferedReader;
42 import java.io.File;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.io.InputStreamReader;
46 import java.net.MalformedURLException;
47 import java.net.UnknownHostException;
48
49 public abstract class AbstractDownloadProviderFunctionalTest extends
50         ServiceTestCase<DownloadService> {
51
52     protected static final String LOG_TAG = "DownloadProviderFunctionalTest";
53     private static final String PROVIDER_AUTHORITY = "downloads";
54     protected static final long RETRY_DELAY_MILLIS = 61 * 1000;
55     protected static final String FILE_CONTENT = "hello world hello world hello world hello world";
56     protected static final int HTTP_OK = 200;
57     protected static final int HTTP_PARTIAL_CONTENT = 206;
58     protected static final int HTTP_NOT_FOUND = 404;
59     protected static final int HTTP_SERVICE_UNAVAILABLE = 503;
60
61     protected MockWebServer mServer;
62     protected MockContentResolverWithNotify mResolver;
63     protected TestContext mTestContext;
64     protected FakeSystemFacade mSystemFacade;
65     protected static String STRING_1K;
66     static {
67         StringBuilder buff = new StringBuilder();
68         for (int i = 0; i < 1024; i++) {
69             buff.append("a" + i % 26);
70         }
71         STRING_1K = buff.toString();
72     }
73
74     static class MockContentResolverWithNotify extends MockContentResolver {
75         public boolean mNotifyWasCalled = false;
76
77         public synchronized void resetNotified() {
78             mNotifyWasCalled = false;
79         }
80
81         @Override
82         public synchronized void notifyChange(Uri uri, ContentObserver observer,
83                 boolean syncToNetwork) {
84             mNotifyWasCalled = true;
85             notifyAll();
86         }
87     }
88
89     /**
90      * Context passed to the provider and the service.  Allows most methods to pass through to the
91      * real Context (this is a LargeTest), with a few exceptions, including renaming file operations
92      * to avoid file and DB conflicts (via RenamingDelegatingContext).
93      */
94     static class TestContext extends RenamingDelegatingContext {
95         private static final String FILENAME_PREFIX = "test.";
96
97         private ContentResolver mResolver;
98         private final NotificationManager mNotifManager;
99
100         boolean mHasServiceBeenStarted = false;
101
102         public TestContext(Context realContext) {
103             super(realContext, FILENAME_PREFIX);
104             mNotifManager = mock(NotificationManager.class);
105         }
106
107         public void setResolver(ContentResolver resolver) {
108             mResolver = resolver;
109         }
110
111         /**
112          * Direct DownloadService to our test instance of DownloadProvider.
113          */
114         @Override
115         public ContentResolver getContentResolver() {
116             return mResolver;
117         }
118
119         /**
120          * Stub some system services, allow access to others, and block the rest.
121          */
122         @Override
123         public Object getSystemService(String name) {
124             if (Context.NOTIFICATION_SERVICE.equals(name)) {
125                 return mNotifManager;
126             }
127
128             return super.getSystemService(name);
129         }
130
131         /**
132          * Record when DownloadProvider starts DownloadService.
133          */
134         @Override
135         public ComponentName startService(Intent service) {
136             if (service.getComponent().getClassName().equals(DownloadService.class.getName())) {
137                 mHasServiceBeenStarted = true;
138                 return service.getComponent();
139             }
140             throw new UnsupportedOperationException("Unexpected service: " + service);
141         }
142     }
143
144     public AbstractDownloadProviderFunctionalTest(FakeSystemFacade systemFacade) {
145         super(DownloadService.class);
146         mSystemFacade = systemFacade;
147     }
148
149     @Override
150     protected void setUp() throws Exception {
151         super.setUp();
152
153         // Since we're testing a system app, AppDataDirGuesser doesn't find our
154         // cache dir, so set it explicitly.
155         System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
156
157         final Context realContext = getContext();
158         mTestContext = new TestContext(realContext);
159         setupProviderAndResolver();
160         mTestContext.setResolver(mResolver);
161         setContext(mTestContext);
162         setupService();
163         getService().mSystemFacade = mSystemFacade;
164         mSystemFacade.setUp();
165         assertTrue(isDatabaseEmpty()); // ensure we're not messing with real data
166         mServer = new MockWebServer();
167         mServer.play();
168     }
169
170     @Override
171     protected void tearDown() throws Exception {
172         cleanUpDownloads();
173         mServer.shutdown();
174         super.tearDown();
175     }
176
177     private boolean isDatabaseEmpty() {
178         Cursor cursor = mResolver.query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
179                 null, null, null, null);
180         try {
181             return cursor.getCount() == 0;
182         } finally {
183             cursor.close();
184         }
185     }
186
187     void setupProviderAndResolver() {
188         DownloadProvider provider = new DownloadProvider();
189         provider.mSystemFacade = mSystemFacade;
190         provider.attachInfo(mTestContext, null);
191         mResolver = new MockContentResolverWithNotify();
192         mResolver.addProvider(PROVIDER_AUTHORITY, provider);
193     }
194
195     /**
196      * Remove any downloaded files and delete any lingering downloads.
197      */
198     void cleanUpDownloads() {
199         if (mResolver == null) {
200             return;
201         }
202         String[] columns = new String[] {Downloads.Impl._DATA};
203         Cursor cursor = mResolver.query(Downloads.Impl.CONTENT_URI, columns, null, null, null);
204         try {
205             for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
206                 String filePath = cursor.getString(0);
207                 if (filePath == null) continue;
208                 Log.d(LOG_TAG, "Deleting " + filePath);
209                 new File(filePath).delete();
210             }
211         } finally {
212             cursor.close();
213         }
214         mResolver.delete(Downloads.Impl.CONTENT_URI, null, null);
215     }
216
217     void enqueueResponse(MockResponse resp) {
218         mServer.enqueue(resp);
219     }
220
221     MockResponse buildResponse(int status, String body) {
222         return new MockResponse().setResponseCode(status).setBody(body)
223                 .setHeader("Content-type", "text/plain")
224                 .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
225     }
226
227     MockResponse buildResponse(int status, byte[] body) {
228         return new MockResponse().setResponseCode(status).setBody(body)
229                 .setHeader("Content-type", "text/plain")
230                 .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
231     }
232
233     MockResponse buildEmptyResponse(int status) {
234         return buildResponse(status, "");
235     }
236
237     /**
238      * Fetch the last request received by the MockWebServer.
239      */
240     protected RecordedRequest takeRequest() throws InterruptedException {
241         RecordedRequest request = mServer.takeRequest();
242         assertNotNull("Expected request was not made", request);
243         return request;
244     }
245
246     String getServerUri(String path) throws MalformedURLException, UnknownHostException {
247         return mServer.getUrl(path).toString();
248     }
249
250     protected String readStream(InputStream inputStream) throws IOException {
251         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
252         try {
253             char[] buffer = new char[1024];
254             int length = reader.read(buffer);
255             assertTrue("Failed to read anything from input stream", length > -1);
256             return String.valueOf(buffer, 0, length);
257         } finally {
258             reader.close();
259         }
260     }
261
262     protected void assertStartsWith(String expectedPrefix, String actual) {
263         String regex = "^" + expectedPrefix + ".*";
264         MoreAsserts.assertMatchesRegex(regex, actual);
265     }
266 }