Migrate to shared MockWebServer.
[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 android.content.ComponentName;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.database.ContentObserver;
24 import android.database.Cursor;
25 import android.net.Uri;
26 import android.provider.Downloads;
27 import android.test.MoreAsserts;
28 import android.test.RenamingDelegatingContext;
29 import android.test.ServiceTestCase;
30 import android.test.mock.MockContentResolver;
31 import android.util.Log;
32
33 import com.google.mockwebserver.MockResponse;
34 import com.google.mockwebserver.MockWebServer;
35 import com.google.mockwebserver.RecordedRequest;
36 import com.google.mockwebserver.SocketPolicy;
37
38 import java.io.BufferedReader;
39 import java.io.File;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.InputStreamReader;
43 import java.net.MalformedURLException;
44 import java.net.UnknownHostException;
45 import java.util.Arrays;
46 import java.util.HashSet;
47 import java.util.Set;
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 Context mRealContext;
98         private Set<String> mAllowedSystemServices;
99         private ContentResolver mResolver;
100
101         boolean mHasServiceBeenStarted = false;
102
103         public TestContext(Context realContext) {
104             super(realContext, FILENAME_PREFIX);
105             mRealContext = realContext;
106             mAllowedSystemServices = new HashSet<String>(Arrays.asList(new String[] {
107                     Context.NOTIFICATION_SERVICE,
108                     Context.POWER_SERVICE,
109             }));
110         }
111
112         public void setResolver(ContentResolver resolver) {
113             mResolver = resolver;
114         }
115
116         /**
117          * Direct DownloadService to our test instance of DownloadProvider.
118          */
119         @Override
120         public ContentResolver getContentResolver() {
121             assert mResolver != null;
122             return mResolver;
123         }
124
125         /**
126          * Stub some system services, allow access to others, and block the rest.
127          */
128         @Override
129         public Object getSystemService(String name) {
130             if (mAllowedSystemServices.contains(name)) {
131                 return mRealContext.getSystemService(name);
132             }
133             return super.getSystemService(name);
134         }
135
136         /**
137          * Record when DownloadProvider starts DownloadService.
138          */
139         @Override
140         public ComponentName startService(Intent service) {
141             if (service.getComponent().getClassName().equals(DownloadService.class.getName())) {
142                 mHasServiceBeenStarted = true;
143                 return service.getComponent();
144             }
145             throw new UnsupportedOperationException("Unexpected service: " + service);
146         }
147     }
148
149     public AbstractDownloadProviderFunctionalTest(FakeSystemFacade systemFacade) {
150         super(DownloadService.class);
151         mSystemFacade = systemFacade;
152     }
153
154     @Override
155     protected void setUp() throws Exception {
156         super.setUp();
157
158         Context realContext = getContext();
159         mTestContext = new TestContext(realContext);
160         setupProviderAndResolver();
161
162         mTestContext.setResolver(mResolver);
163         setContext(mTestContext);
164         setupService();
165         getService().mSystemFacade = mSystemFacade;
166         assertTrue(isDatabaseEmpty()); // ensure we're not messing with real data
167         mServer = new MockWebServer();
168         mServer.play();
169     }
170
171     @Override
172     protected void tearDown() throws Exception {
173         cleanUpDownloads();
174         mServer.shutdown();
175         super.tearDown();
176     }
177
178     private boolean isDatabaseEmpty() {
179         Cursor cursor = mResolver.query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,
180                 null, null, null, null);
181         try {
182             return cursor.getCount() == 0;
183         } finally {
184             cursor.close();
185         }
186     }
187
188     void setupProviderAndResolver() {
189         DownloadProvider provider = new DownloadProvider();
190         provider.mSystemFacade = mSystemFacade;
191         provider.attachInfo(mTestContext, null);
192         mResolver = new MockContentResolverWithNotify();
193         mResolver.addProvider(PROVIDER_AUTHORITY, provider);
194     }
195
196     /**
197      * Remove any downloaded files and delete any lingering downloads.
198      */
199     void cleanUpDownloads() {
200         if (mResolver == null) {
201             return;
202         }
203         String[] columns = new String[] {Downloads.Impl._DATA};
204         Cursor cursor = mResolver.query(Downloads.Impl.CONTENT_URI, columns, null, null, null);
205         try {
206             for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
207                 String filePath = cursor.getString(0);
208                 if (filePath == null) continue;
209                 Log.d(LOG_TAG, "Deleting " + filePath);
210                 new File(filePath).delete();
211             }
212         } finally {
213             cursor.close();
214         }
215         mResolver.delete(Downloads.Impl.CONTENT_URI, null, null);
216     }
217
218     void enqueueResponse(MockResponse resp) {
219         mServer.enqueue(resp);
220     }
221
222     MockResponse buildResponse(int status, String body) {
223         return new MockResponse().setResponseCode(status).setBody(body)
224                 .setHeader("Content-type", "text/plain")
225                 .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
226     }
227
228     MockResponse buildResponse(int status, byte[] body) {
229         return new MockResponse().setResponseCode(status).setBody(body)
230                 .setHeader("Content-type", "text/plain")
231                 .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
232     }
233
234     MockResponse buildEmptyResponse(int status) {
235         return buildResponse(status, "");
236     }
237
238     /**
239      * Fetch the last request received by the MockWebServer.
240      */
241     protected RecordedRequest takeRequest() throws InterruptedException {
242         RecordedRequest request = mServer.takeRequest();
243         assertNotNull("Expected request was not made", request);
244         return request;
245     }
246
247     String getServerUri(String path) throws MalformedURLException, UnknownHostException {
248         return mServer.getUrl(path).toString();
249     }
250
251     public void runService() throws Exception {
252         startService(null);
253         mSystemFacade.runAllThreads();
254     }
255
256     protected String readStream(InputStream inputStream) throws IOException {
257         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
258         try {
259             char[] buffer = new char[1024];
260             int length = reader.read(buffer);
261             assertTrue("Failed to read anything from input stream", length > -1);
262             return String.valueOf(buffer, 0, length);
263         } finally {
264             reader.close();
265         }
266     }
267
268     protected void assertStartsWith(String expectedPrefix, String actual) {
269         String regex = "^" + expectedPrefix + ".*";
270         MoreAsserts.assertMatchesRegex(regex, actual);
271     }
272 }