AbstractDownloadProviderFunctionalTest.java revision 8ac10e0e0667a4fe35191deebb5fa9786bf4226c
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 static com.google.testing.littlemock.LittleMock.mock; 20 21import android.app.NotificationManager; 22import android.content.ComponentName; 23import android.content.ContentResolver; 24import android.content.Context; 25import android.content.Intent; 26import android.database.ContentObserver; 27import android.database.Cursor; 28import android.net.Uri; 29import android.provider.Downloads; 30import android.test.MoreAsserts; 31import android.test.RenamingDelegatingContext; 32import android.test.ServiceTestCase; 33import android.test.mock.MockContentResolver; 34import android.util.Log; 35 36import com.google.mockwebserver.MockResponse; 37import com.google.mockwebserver.MockWebServer; 38import com.google.mockwebserver.RecordedRequest; 39import com.google.mockwebserver.SocketPolicy; 40 41import java.io.BufferedReader; 42import java.io.File; 43import java.io.IOException; 44import java.io.InputStream; 45import java.io.InputStreamReader; 46import java.net.MalformedURLException; 47import java.net.UnknownHostException; 48 49public 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} 267