| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.email.service; |
| |
| import com.android.email.AccountTestCase; |
| import com.android.email.EmailConnectivityManager; |
| import com.android.email.ExchangeUtils.NullEmailService; |
| import com.android.email.provider.ProviderTestUtils; |
| import com.android.email.service.AttachmentDownloadService.DownloadRequest; |
| import com.android.email.service.AttachmentDownloadService.DownloadSet; |
| import com.android.emailcommon.provider.EmailContent.Account; |
| import com.android.emailcommon.provider.EmailContent.Attachment; |
| import com.android.emailcommon.provider.EmailContent.Mailbox; |
| import com.android.emailcommon.provider.EmailContent.Message; |
| import com.android.emailcommon.service.EmailServiceStatus; |
| |
| import android.content.Context; |
| import android.content.Intent; |
| |
| import java.io.File; |
| import java.util.Iterator; |
| |
| /** |
| * Tests of the AttachmentDownloadService |
| * |
| * You can run this entire test case with: |
| * runtest -c com.android.email.service.AttachmentDownloadServiceTests email |
| */ |
| public class AttachmentDownloadServiceTests extends AccountTestCase { |
| private AttachmentDownloadService mService; |
| private Context mMockContext; |
| private Account mAccount; |
| private Mailbox mMailbox; |
| private long mAccountId; |
| private long mMailboxId; |
| private AttachmentDownloadService.AccountManagerStub mAccountManagerStub; |
| private MockDirectory mMockDirectory; |
| |
| private DownloadSet mDownloadSet; |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| mMockContext = getMockContext(); |
| |
| // Set up an account and mailbox |
| mAccount = ProviderTestUtils.setupAccount("account", false, mMockContext); |
| mAccount.mFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS; |
| mAccount.save(mMockContext); |
| mAccountId = mAccount.mId; |
| |
| mMailbox = ProviderTestUtils.setupMailbox("mailbox", mAccountId, true, mMockContext); |
| mMailboxId = mMailbox.mId; |
| |
| // Set up our download service to simulate a running environment |
| // Use the NullEmailService so that the loadAttachment calls become no-ops |
| mService = new AttachmentDownloadService(); |
| mService.mContext = mMockContext; |
| mService.addServiceIntentForTest(mAccountId, new Intent(mMockContext, |
| NullEmailService.class)); |
| mAccountManagerStub = new AttachmentDownloadService.AccountManagerStub(null); |
| mService.mAccountManagerStub = mAccountManagerStub; |
| mService.mConnectivityManager = new MockConnectivityManager(getContext(), "mock"); |
| mDownloadSet = mService.mDownloadSet; |
| mMockDirectory = |
| new MockDirectory(mService.mContext.getCacheDir().getAbsolutePath()); |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| super.tearDown(); |
| } |
| |
| /** |
| * This test creates attachments and places them in the DownloadSet; we then do various checks |
| * that exercise its functionality. |
| */ |
| public void testDownloadSet() { |
| // TODO: Make sure that this doesn't interfere with the "real" ADS that might be running |
| // on device |
| Message message = ProviderTestUtils.setupMessage("message", mAccountId, mMailboxId, false, |
| true, mMockContext); |
| Attachment att1 = ProviderTestUtils.setupAttachment(message.mId, "filename1", 1000, |
| Attachment.FLAG_DOWNLOAD_USER_REQUEST, true, mMockContext); |
| Attachment att2 = ProviderTestUtils.setupAttachment(message.mId, "filename2", 1000, |
| Attachment.FLAG_DOWNLOAD_FORWARD, true, mMockContext); |
| Attachment att3 = ProviderTestUtils.setupAttachment(message.mId, "filename3", 1000, |
| Attachment.FLAG_DOWNLOAD_FORWARD, true, mMockContext); |
| Attachment att4 = ProviderTestUtils.setupAttachment(message.mId, "filename4", 1000, |
| Attachment.FLAG_DOWNLOAD_USER_REQUEST, true, mMockContext); |
| // Indicate that these attachments have changed; they will be added to the queue |
| mDownloadSet.onChange(mMockContext, att1); |
| mDownloadSet.onChange(mMockContext, att2); |
| mDownloadSet.onChange(mMockContext, att3); |
| mDownloadSet.onChange(mMockContext, att4); |
| Iterator<DownloadRequest> iterator = mDownloadSet.descendingIterator(); |
| // Check the expected ordering; 1 & 4 are higher priority than 2 & 3 |
| // 1 and 3 were created earlier than their priority equals |
| long[] expectedAttachmentIds = new long[] {att1.mId, att4.mId, att2.mId, att3.mId}; |
| for (int i = 0; i < expectedAttachmentIds.length; i++) { |
| assertTrue(iterator.hasNext()); |
| DownloadRequest req = iterator.next(); |
| assertEquals(expectedAttachmentIds[i], req.attachmentId); |
| } |
| |
| // Process the queue; attachment 1 should be marked "in progress", and should be in |
| // the in-progress map |
| mDownloadSet.processQueue(); |
| DownloadRequest req = mDownloadSet.findDownloadRequest(att1.mId); |
| assertNotNull(req); |
| assertTrue(req.inProgress); |
| assertTrue(mDownloadSet.mDownloadsInProgress.containsKey(att1.mId)); |
| // There should also be only one download in progress (testing the per-account limitation) |
| assertEquals(1, mDownloadSet.mDownloadsInProgress.size()); |
| // End the "download" with a connection error; we should still have this in the queue, |
| // but it should no longer be in-progress |
| mDownloadSet.endDownload(att1.mId, EmailServiceStatus.CONNECTION_ERROR); |
| assertFalse(req.inProgress); |
| assertEquals(0, mDownloadSet.mDownloadsInProgress.size()); |
| |
| mDownloadSet.processQueue(); |
| // Things should be as they were earlier; att1 should be an in-progress download |
| req = mDownloadSet.findDownloadRequest(att1.mId); |
| assertNotNull(req); |
| assertTrue(req.inProgress); |
| assertTrue(mDownloadSet.mDownloadsInProgress.containsKey(att1.mId)); |
| // Successfully download the attachment; there should be no downloads in progress, and |
| // att1 should no longer be in the queue |
| mDownloadSet.endDownload(att1.mId, EmailServiceStatus.SUCCESS); |
| assertEquals(0, mDownloadSet.mDownloadsInProgress.size()); |
| assertNull(mDownloadSet.findDownloadRequest(att1.mId)); |
| |
| // Test dequeue and isQueued |
| assertEquals(3, mDownloadSet.size()); |
| mService.dequeue(att2.mId); |
| assertEquals(2, mDownloadSet.size()); |
| assertTrue(mService.isQueued(att4.mId)); |
| assertTrue(mService.isQueued(att3.mId)); |
| |
| mDownloadSet.processQueue(); |
| // att4 should be the download in progress |
| req = mDownloadSet.findDownloadRequest(att4.mId); |
| assertNotNull(req); |
| assertTrue(req.inProgress); |
| assertTrue(mDownloadSet.mDownloadsInProgress.containsKey(att4.mId)); |
| } |
| |
| /** |
| * A mock file directory containing a single (Mock)File. The total space, usable space, and |
| * length of the single file can be set |
| */ |
| private static class MockDirectory extends File { |
| private static final long serialVersionUID = 1L; |
| private long mTotalSpace; |
| private long mUsableSpace; |
| private MockFile[] mFiles; |
| private final MockFile mMockFile = new MockFile(); |
| |
| |
| public MockDirectory(String path) { |
| super(path); |
| mFiles = new MockFile[1]; |
| mFiles[0] = mMockFile; |
| } |
| |
| private void setTotalAndUsableSpace(long total, long usable) { |
| mTotalSpace = total; |
| mUsableSpace = usable; |
| } |
| |
| public long getTotalSpace() { |
| return mTotalSpace; |
| } |
| |
| public long getUsableSpace() { |
| return mUsableSpace; |
| } |
| |
| public void setFileLength(long length) { |
| mMockFile.mLength = length; |
| } |
| |
| public File[] listFiles() { |
| return mFiles; |
| } |
| } |
| |
| /** |
| * A mock file that reports back a pre-set length |
| */ |
| private static class MockFile extends File { |
| private static final long serialVersionUID = 1L; |
| private long mLength = 0; |
| |
| public MockFile() { |
| super("_mock"); |
| } |
| |
| public long length() { |
| return mLength; |
| } |
| } |
| |
| private static class MockConnectivityManager extends EmailConnectivityManager { |
| public MockConnectivityManager(Context context, String name) { |
| super(context, name); |
| } |
| |
| @Override |
| public void waitForConnectivity() { |
| } |
| |
| @Override |
| public boolean isBackgroundDataAllowed() { |
| return true; |
| } |
| } |
| |
| public void testCanPrefetchForAccount() { |
| // First, test our "global" limits (based on free storage) |
| // Mock storage @ 100 total and 26 available |
| // Note that all file lengths in this test are in arbitrary units |
| mMockDirectory.setTotalAndUsableSpace(100L, 26L); |
| // Mock 2 accounts in total |
| mAccountManagerStub.setNumberOfAccounts(2); |
| // With 26% available, we should be ok to prefetch |
| assertTrue(mService.canPrefetchForAccount(mAccount, mMockDirectory)); |
| // Now change to 24 available |
| mMockDirectory.setTotalAndUsableSpace(100L, 24L); |
| // With 24% available, we should NOT be ok to prefetch |
| assertFalse(mService.canPrefetchForAccount(mAccount, mMockDirectory)); |
| |
| // Now, test per-account storage |
| // Mock storage @ 100 total and 50 available |
| mMockDirectory.setTotalAndUsableSpace(100L, 50L); |
| // Mock a file of length 12, but need to uncache previous amount first |
| mService.mAttachmentStorageMap.remove(mAccountId); |
| mMockDirectory.setFileLength(11); |
| // We can prefetch since 11 < 50/4 |
| assertTrue(mService.canPrefetchForAccount(mAccount, mMockDirectory)); |
| // Mock a file of length 13, but need to uncache previous amount first |
| mService.mAttachmentStorageMap.remove(mAccountId); |
| mMockDirectory.setFileLength(13); |
| // We can't prefetch since 13 > 50/4 |
| assertFalse(mService.canPrefetchForAccount(mAccount, mMockDirectory)); |
| } |
| |
| public void testCanPrefetchForAccountNoBackgroundDownload() { |
| Account account = ProviderTestUtils.setupAccount("account2", false, mMockContext); |
| account.mFlags &= ~Account.FLAGS_BACKGROUND_ATTACHMENTS; |
| account.save(mMockContext); |
| |
| // First, test our "global" limits (based on free storage) |
| // Mock storage @ 100 total and 26 available |
| // Note that all file lengths in this test are in arbitrary units |
| mMockDirectory.setTotalAndUsableSpace(100L, 26L); |
| // Mock 2 accounts in total |
| mAccountManagerStub.setNumberOfAccounts(2); |
| |
| // With 26% available, we should be ok to prefetch, |
| // *but* bg download is disabled on the account. |
| assertFalse(mService.canPrefetchForAccount(account, mMockDirectory)); |
| } |
| } |