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