• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.email.service;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 
22 import com.android.email.AccountTestCase;
23 import com.android.email.EmailConnectivityManager;
24 import com.android.email.provider.ProviderTestUtils;
25 import com.android.email.service.AttachmentDownloadService.DownloadRequest;
26 import com.android.email.service.AttachmentDownloadService.DownloadSet;
27 import com.android.email.service.EmailServiceUtils.NullEmailService;
28 import com.android.emailcommon.provider.Account;
29 import com.android.emailcommon.provider.EmailContent.Attachment;
30 import com.android.emailcommon.provider.EmailContent.Message;
31 import com.android.emailcommon.provider.Mailbox;
32 import com.android.emailcommon.service.EmailServiceStatus;
33 
34 import java.io.File;
35 import java.util.Iterator;
36 
37 /**
38  * Tests of the AttachmentDownloadService
39  *
40  * You can run this entire test case with:
41  *   runtest -c com.android.email.service.AttachmentDownloadServiceTests email
42  */
43 public class AttachmentDownloadServiceTests extends AccountTestCase {
44     private AttachmentDownloadService mService;
45     private Context mMockContext;
46     private Account mAccount;
47     private Mailbox mMailbox;
48     private long mAccountId;
49     private long mMailboxId;
50     private AttachmentDownloadService.AccountManagerStub mAccountManagerStub;
51     private MockDirectory mMockDirectory;
52 
53     private DownloadSet mDownloadSet;
54 
55     @Override
setUp()56     public void setUp() throws Exception {
57         super.setUp();
58         mMockContext = getMockContext();
59 
60         // Set up an account and mailbox
61         mAccount = ProviderTestUtils.setupAccount("account", false, mMockContext);
62         mAccount.mFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS;
63         mAccount.save(mMockContext);
64         mAccountId = mAccount.mId;
65 
66         mMailbox = ProviderTestUtils.setupMailbox("mailbox", mAccountId, true, mMockContext);
67         mMailboxId = mMailbox.mId;
68 
69         // Set up our download service to simulate a running environment
70         // Use the NullEmailService so that the loadAttachment calls become no-ops
71         mService = new AttachmentDownloadService();
72         mService.mContext = mMockContext;
73         mService.addServiceIntentForTest(mAccountId, new Intent(mContext,
74                 NullEmailService.class));
75         mAccountManagerStub = new AttachmentDownloadService.AccountManagerStub(null);
76         mService.mAccountManagerStub = mAccountManagerStub;
77         mService.mConnectivityManager = new MockConnectivityManager(mContext, "mock");
78         mDownloadSet = mService.mDownloadSet;
79         mMockDirectory =
80             new MockDirectory(mService.mContext.getCacheDir().getAbsolutePath());
81     }
82 
83     @Override
tearDown()84     public void tearDown() throws Exception {
85         super.tearDown();
86     }
87 
88     /**
89      * This test creates attachments and places them in the DownloadSet; we then do various checks
90      * that exercise its functionality.
91      */
testDownloadSet()92     public void testDownloadSet() {
93         // TODO: Make sure that this doesn't interfere with the "real" ADS that might be running
94         // on device
95         Message message = ProviderTestUtils.setupMessage("message", mAccountId, mMailboxId, false,
96                 true, mMockContext);
97         Attachment att1 = ProviderTestUtils.setupAttachment(message.mId, "filename1", 1000,
98                 Attachment.FLAG_DOWNLOAD_USER_REQUEST, true, mMockContext);
99         Attachment att2 = ProviderTestUtils.setupAttachment(message.mId, "filename2", 1000,
100                 Attachment.FLAG_DOWNLOAD_FORWARD, true, mMockContext);
101         Attachment att3 = ProviderTestUtils.setupAttachment(message.mId, "filename3", 1000,
102                 Attachment.FLAG_DOWNLOAD_FORWARD, true, mMockContext);
103         Attachment att4 = ProviderTestUtils.setupAttachment(message.mId, "filename4", 1000,
104                 Attachment.FLAG_DOWNLOAD_USER_REQUEST, true, mMockContext);
105         // Indicate that these attachments have changed; they will be added to the queue
106         mDownloadSet.onChange(mMockContext, att1);
107         mDownloadSet.onChange(mMockContext, att2);
108         mDownloadSet.onChange(mMockContext, att3);
109         mDownloadSet.onChange(mMockContext, att4);
110         Iterator<DownloadRequest> iterator = mDownloadSet.descendingIterator();
111         // Check the expected ordering; 1 & 4 are higher priority than 2 & 3
112         // 1 and 3 were created earlier than their priority equals
113         long[] expectedAttachmentIds = new long[] {att1.mId, att4.mId, att2.mId, att3.mId};
114         for (int i = 0; i < expectedAttachmentIds.length; i++) {
115             assertTrue(iterator.hasNext());
116             DownloadRequest req = iterator.next();
117             assertEquals(expectedAttachmentIds[i], req.attachmentId);
118         }
119 
120         // Process the queue; attachment 1 should be marked "in progress", and should be in
121         // the in-progress map
122         mDownloadSet.processQueue();
123         DownloadRequest req = mDownloadSet.findDownloadRequest(att1.mId);
124         assertNotNull(req);
125         assertTrue(req.inProgress);
126         assertTrue(mDownloadSet.mDownloadsInProgress.containsKey(att1.mId));
127         // There should also be only one download in progress (testing the per-account limitation)
128         assertEquals(1, mDownloadSet.mDownloadsInProgress.size());
129         // End the "download" with a connection error; we should still have this in the queue,
130         // but it should no longer be in-progress
131         mDownloadSet.endDownload(att1.mId, EmailServiceStatus.CONNECTION_ERROR);
132         assertFalse(req.inProgress);
133         assertEquals(0, mDownloadSet.mDownloadsInProgress.size());
134 
135         mDownloadSet.processQueue();
136         // Things should be as they were earlier; att1 should be an in-progress download
137         req = mDownloadSet.findDownloadRequest(att1.mId);
138         assertNotNull(req);
139         assertTrue(req.inProgress);
140         assertTrue(mDownloadSet.mDownloadsInProgress.containsKey(att1.mId));
141         // Successfully download the attachment; there should be no downloads in progress, and
142         // att1 should no longer be in the queue
143         mDownloadSet.endDownload(att1.mId, EmailServiceStatus.SUCCESS);
144         assertEquals(0, mDownloadSet.mDownloadsInProgress.size());
145         assertNull(mDownloadSet.findDownloadRequest(att1.mId));
146 
147         // Test dequeue and isQueued
148         assertEquals(3, mDownloadSet.size());
149         mService.dequeue(att2.mId);
150         assertEquals(2, mDownloadSet.size());
151         assertTrue(mService.isQueued(att4.mId));
152         assertTrue(mService.isQueued(att3.mId));
153 
154         mDownloadSet.processQueue();
155         // att4 should be the download in progress
156         req = mDownloadSet.findDownloadRequest(att4.mId);
157         assertNotNull(req);
158         assertTrue(req.inProgress);
159         assertTrue(mDownloadSet.mDownloadsInProgress.containsKey(att4.mId));
160     }
161 
162     /**
163      * A mock file directory containing a single (Mock)File.  The total space, usable space, and
164      * length of the single file can be set
165      */
166     private static class MockDirectory extends File {
167         private static final long serialVersionUID = 1L;
168         private long mTotalSpace;
169         private long mUsableSpace;
170         private MockFile[] mFiles;
171         private final MockFile mMockFile = new MockFile();
172 
173 
MockDirectory(String path)174         public MockDirectory(String path) {
175             super(path);
176             mFiles = new MockFile[1];
177             mFiles[0] = mMockFile;
178         }
179 
setTotalAndUsableSpace(long total, long usable)180         private void setTotalAndUsableSpace(long total, long usable) {
181             mTotalSpace = total;
182             mUsableSpace = usable;
183         }
184 
185         @Override
getTotalSpace()186         public long getTotalSpace() {
187             return mTotalSpace;
188         }
189 
190         @Override
getUsableSpace()191         public long getUsableSpace() {
192             return mUsableSpace;
193         }
194 
setFileLength(long length)195         public void setFileLength(long length) {
196             mMockFile.mLength = length;
197         }
198 
199         @Override
listFiles()200         public File[] listFiles() {
201             return mFiles;
202         }
203     }
204 
205     /**
206      * A mock file that reports back a pre-set length
207      */
208     private static class MockFile extends File {
209         private static final long serialVersionUID = 1L;
210         private long mLength = 0;
211 
MockFile()212         public MockFile() {
213             super("_mock");
214         }
215 
216         @Override
length()217         public long length() {
218             return mLength;
219         }
220     }
221 
222     private static class MockConnectivityManager extends EmailConnectivityManager {
MockConnectivityManager(Context context, String name)223         public MockConnectivityManager(Context context, String name) {
224             super(context, name);
225         }
226 
227         @Override
waitForConnectivity()228         public void waitForConnectivity() {
229         }
230 
231         @Override
isAutoSyncAllowed()232         public boolean isAutoSyncAllowed() {
233             return true;
234         }
235     }
236 
testCanPrefetchForAccount()237     public void testCanPrefetchForAccount() {
238         // First, test our "global" limits (based on free storage)
239         // Mock storage @ 100 total and 26 available
240         // Note that all file lengths in this test are in arbitrary units
241         mMockDirectory.setTotalAndUsableSpace(100L, 26L);
242         // Mock 2 accounts in total
243         mAccountManagerStub.setNumberOfAccounts(2);
244         // With 26% available, we should be ok to prefetch
245         assertTrue(mService.canPrefetchForAccount(mAccount, mMockDirectory));
246         // Now change to 24 available
247         mMockDirectory.setTotalAndUsableSpace(100L, 24L);
248         // With 24% available, we should NOT be ok to prefetch
249         assertFalse(mService.canPrefetchForAccount(mAccount, mMockDirectory));
250 
251         // Now, test per-account storage
252         // Mock storage @ 100 total and 50 available
253         mMockDirectory.setTotalAndUsableSpace(100L, 50L);
254         // Mock a file of length 12, but need to uncache previous amount first
255         mService.mAttachmentStorageMap.remove(mAccountId);
256         mMockDirectory.setFileLength(11);
257         // We can prefetch since 11 < 50/4
258         assertTrue(mService.canPrefetchForAccount(mAccount, mMockDirectory));
259         // Mock a file of length 13, but need to uncache previous amount first
260         mService.mAttachmentStorageMap.remove(mAccountId);
261         mMockDirectory.setFileLength(13);
262         // We can't prefetch since 13 > 50/4
263         assertFalse(mService.canPrefetchForAccount(mAccount, mMockDirectory));
264     }
265 
testCanPrefetchForAccountNoBackgroundDownload()266     public void testCanPrefetchForAccountNoBackgroundDownload() {
267         Account account = ProviderTestUtils.setupAccount("account2", false, mMockContext);
268         account.mFlags &= ~Account.FLAGS_BACKGROUND_ATTACHMENTS;
269         account.save(mMockContext);
270 
271         // First, test our "global" limits (based on free storage)
272         // Mock storage @ 100 total and 26 available
273         // Note that all file lengths in this test are in arbitrary units
274         mMockDirectory.setTotalAndUsableSpace(100L, 26L);
275         // Mock 2 accounts in total
276         mAccountManagerStub.setNumberOfAccounts(2);
277 
278         // With 26% available, we should be ok to prefetch,
279         // *but* bg download is disabled on the account.
280         assertFalse(mService.canPrefetchForAccount(account, mMockDirectory));
281     }
282 }
283