Home | History | Annotate | Download | only in provider
      1 /*
      2  * Copyright (C) 2009 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.provider;
     18 
     19 import com.android.email.AttachmentInfo;
     20 import com.android.email.R;
     21 import com.android.emailcommon.mail.MessagingException;
     22 import com.android.emailcommon.provider.Account;
     23 import com.android.emailcommon.provider.EmailContent;
     24 import com.android.emailcommon.provider.EmailContent.Attachment;
     25 import com.android.emailcommon.provider.EmailContent.Message;
     26 import com.android.emailcommon.provider.Mailbox;
     27 import com.android.emailcommon.utility.AttachmentUtilities;
     28 
     29 import android.content.ContentResolver;
     30 import android.content.Context;
     31 import android.content.res.AssetFileDescriptor;
     32 import android.database.Cursor;
     33 import android.graphics.Bitmap;
     34 import android.graphics.BitmapFactory;
     35 import android.net.Uri;
     36 import android.test.ProviderTestCase2;
     37 import android.test.mock.MockContentResolver;
     38 
     39 import java.io.File;
     40 import java.io.FileNotFoundException;
     41 import java.io.FileOutputStream;
     42 import java.io.IOException;
     43 
     44 /**
     45  * Tests of the Email Attachments provider.
     46  *
     47  * You can run this entire test case with:
     48  *   runtest -c com.android.email.provider.AttachmentProviderTests email
     49  */
     50 public class AttachmentProviderTests extends ProviderTestCase2<AttachmentProvider> {
     51 
     52     EmailProvider mEmailProvider;
     53     Context mMockContext;
     54     ContentResolver mMockResolver;
     55 
     56     public AttachmentProviderTests() {
     57         super(AttachmentProvider.class, AttachmentUtilities.AUTHORITY);
     58     }
     59 
     60     @Override
     61     public void setUp() throws Exception {
     62         super.setUp();
     63         mMockContext = getMockContext();
     64         mMockResolver = mMockContext.getContentResolver();
     65 
     66         // Spin up an Email provider as well and put it under the same mock test framework
     67         mEmailProvider = new EmailProvider();
     68         mEmailProvider.attachInfo(mMockContext, null);
     69         assertNotNull(mEmailProvider);
     70         ((MockContentResolver) mMockResolver)
     71                 .addProvider(EmailContent.AUTHORITY, mEmailProvider);
     72     }
     73 
     74     /**
     75      * test delete() - should do nothing
     76      * test update() - should do nothing
     77      * test insert() - should do nothing
     78      */
     79     public void testUnimplemented() {
     80         assertEquals(0, mMockResolver.delete(AttachmentUtilities.CONTENT_URI, null, null));
     81         assertEquals(0, mMockResolver.update(AttachmentUtilities.CONTENT_URI, null, null,
     82                 null));
     83         assertEquals(null, mMockResolver.insert(AttachmentUtilities.CONTENT_URI, null));
     84     }
     85 
     86     /**
     87      * test query()
     88      *  - item found
     89      *  - item not found
     90      *  - permuted projection
     91      */
     92     public void testQuery() throws MessagingException {
     93         Account account1 = ProviderTestUtils.setupAccount("attachment-query", false, mMockContext);
     94         account1.mCompatibilityUuid = "test-UUID";
     95         account1.save(mMockContext);
     96         final long message1Id = 1;
     97         long attachment1Id = 1;
     98         long attachment2Id = 2;
     99         long attachment3Id = 3;
    100 
    101         // Note:  There is an implicit assumption in this test sequence that the first
    102         // attachment we add will be id=1 and the 2nd will have id=2.  This could fail on
    103         // a legitimate implementation.  Asserts below will catch this and fail the test
    104         // if necessary.
    105         Uri attachment1Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
    106                 attachment1Id);
    107         Uri attachment2Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
    108                 attachment2Id);
    109         Uri attachment3Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
    110                 attachment3Id);
    111 
    112         // Test with no attachment found - should return null
    113         Cursor c = mMockResolver.query(attachment1Uri, (String[])null, null, (String[])null, null);
    114         assertNull(c);
    115 
    116         // Add a couple of attachment entries.  Note, query() just uses the DB, and does not
    117         // sample the files, so we won't bother creating the files
    118         Attachment newAttachment1 = ProviderTestUtils.setupAttachment(message1Id, "file1", 100,
    119                 false, mMockContext);
    120         newAttachment1.mContentUri =
    121             AttachmentUtilities.getAttachmentUri(account1.mId, attachment1Id).toString();
    122         attachment1Id = addAttachmentToDb(account1, newAttachment1);
    123         assertEquals("Broken test:  Unexpected id assignment", 1, attachment1Id);
    124 
    125         Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message1Id, "file2", 200,
    126                 false, mMockContext);
    127         newAttachment2.mContentUri =
    128             AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id).toString();
    129         attachment2Id = addAttachmentToDb(account1, newAttachment2);
    130         assertEquals("Broken test:  Unexpected id assignment", 2, attachment2Id);
    131 
    132         Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message1Id, "file3", 300,
    133                 false, mMockContext);
    134         newAttachment3.mContentUri =
    135             AttachmentUtilities.getAttachmentUri(account1.mId, attachment3Id).toString();
    136         attachment3Id = addAttachmentToDb(account1, newAttachment3);
    137         assertEquals("Broken test:  Unexpected id assignment", 3, attachment3Id);
    138 
    139         // Return a row with all columns specified
    140         attachment2Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id);
    141         c = mMockResolver.query(
    142                 attachment2Uri,
    143                 new String[] { AttachmentUtilities.Columns._ID,
    144                                AttachmentUtilities.Columns.DATA,
    145                                AttachmentUtilities.Columns.DISPLAY_NAME,
    146                                AttachmentUtilities.Columns.SIZE },
    147                 null, null, null);
    148         assertEquals(1, c.getCount());
    149         assertTrue(c.moveToFirst());
    150         assertEquals(attachment2Id, c.getLong(0));                  // id
    151         assertEquals(attachment2Uri.toString(), c.getString(1));    // content URI
    152         assertEquals("file2", c.getString(2));                      // display name
    153         assertEquals(200, c.getInt(3));                             // size
    154 
    155         // Return a row with permuted columns
    156         attachment3Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment3Id);
    157         c = mMockResolver.query(
    158                 attachment3Uri,
    159                 new String[] { AttachmentUtilities.Columns.SIZE,
    160                                AttachmentUtilities.Columns.DISPLAY_NAME,
    161                                AttachmentUtilities.Columns.DATA,
    162                                AttachmentUtilities.Columns._ID },
    163                 null, null, null);
    164         assertEquals(1, c.getCount());
    165         assertTrue(c.moveToFirst());
    166         assertEquals(attachment3Id, c.getLong(3));                  // id
    167         assertEquals(attachment3Uri.toString(), c.getString(2));    // content URI
    168         assertEquals("file3", c.getString(1));                      // display name
    169         assertEquals(300, c.getInt(0));                             // size
    170     }
    171 
    172     private static Message createMessage(Context c, Mailbox b) {
    173         Message m = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, false, c, false,
    174                 false);
    175         m.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
    176         m.save(c);
    177         return m;
    178     }
    179 
    180     public void testInboxQuery() {
    181         // Create 2 accounts
    182         Account a1 = ProviderTestUtils.setupAccount("inboxquery-1", true, mMockContext);
    183         Account a2 = ProviderTestUtils.setupAccount("inboxquery-2", true, mMockContext);
    184 
    185         // Create mailboxes for each account
    186         Mailbox b1 = ProviderTestUtils.setupMailbox(
    187                 "box1", a1.mId, true, mMockContext, Mailbox.TYPE_INBOX);
    188         Mailbox b2 = ProviderTestUtils.setupMailbox(
    189                 "box2", a1.mId, true, mMockContext, Mailbox.TYPE_MAIL);
    190         Mailbox b3 = ProviderTestUtils.setupMailbox(
    191                 "box3", a2.mId, true, mMockContext, Mailbox.TYPE_INBOX);
    192         Mailbox b4 = ProviderTestUtils.setupMailbox(
    193                 "box4", a2.mId, true, mMockContext, Mailbox.TYPE_MAIL);
    194         Mailbox bt = ProviderTestUtils.setupMailbox(
    195                 "boxT", a2.mId, true, mMockContext, Mailbox.TYPE_TRASH);
    196 
    197         // Create some messages
    198         // b1 (account 1, inbox): 2 messages
    199         Message m11 = createMessage(mMockContext, b1);
    200         Message m12 = createMessage(mMockContext, b1);
    201 
    202         // b2 (account 1, mail): 2 messages
    203         Message m21 = createMessage(mMockContext, b2);
    204         Message m22 = createMessage(mMockContext, b2);
    205 
    206         // b3 (account 2, inbox): 1 message
    207         Message m31 = createMessage(mMockContext, b3);
    208 
    209         // b4 (account 2, mail) has no messages.
    210 
    211         // bt (account 2, trash): 1 message
    212         Message mt1 = createMessage(mMockContext, bt);
    213 
    214         // 4 attachments in the inbox, 2 different messages, 1 downloaded
    215         createAttachment(a1, m11.mId, null);
    216         createAttachment(a1, m11.mId, null);
    217         createAttachment(a1, m12.mId, null);
    218         createAttachment(a1, m12.mId, "file:///path/to/file1");
    219 
    220         // 3 attachments in generic mailbox, 2 different messages, 1 downloaded
    221         createAttachment(a1, m21.mId, null);
    222         createAttachment(a1, m21.mId, null);
    223         createAttachment(a1, m22.mId, null);
    224         createAttachment(a1, m22.mId, "file:///path/to/file2");
    225 
    226         // 1 attachment in inbox
    227         createAttachment(a2, m31.mId, null);
    228 
    229         // 2 attachments in trash, same message
    230         createAttachment(a2, mt1.mId, null);
    231         createAttachment(a2, mt1.mId, null);
    232 
    233         Cursor c = null;
    234         try {
    235             // count all attachments with an empty URI, regardless of mailbox location
    236             c = mMockContext.getContentResolver().query(
    237                     Attachment.CONTENT_URI, AttachmentInfo.PROJECTION,
    238                     EmailContent.Attachment.PRECACHE_SELECTION,
    239                     null, Attachment.RECORD_ID + " DESC");
    240             assertEquals(9, c.getCount());
    241         } finally {
    242             c.close();
    243         }
    244 
    245         try {
    246             // count all attachments with an empty URI, only in an inbox
    247             c = mMockContext.getContentResolver().query(
    248                     Attachment.CONTENT_URI, AttachmentInfo.PROJECTION,
    249                     EmailContent.Attachment.PRECACHE_INBOX_SELECTION,
    250                     null, Attachment.RECORD_ID + " DESC");
    251             assertEquals(4, c.getCount());
    252         } finally {
    253             c.close();
    254         }
    255     }
    256 
    257     /**
    258      * test getType()
    259      *  - regular file
    260      *  - thumbnail
    261      */
    262     public void testGetType() throws MessagingException {
    263         Account account1 = ProviderTestUtils.setupAccount("get-type", false, mMockContext);
    264         account1.mCompatibilityUuid = "test-UUID";
    265         account1.save(mMockContext);
    266         final long message1Id = 1;
    267         long attachment1Id = 1;
    268         long attachment2Id = 2;
    269         long attachment3Id = 3;
    270         long attachment4Id = 4;
    271         long attachment5Id = 5;
    272         long attachment6Id = 6;
    273 
    274         Uri attachment1Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
    275                 attachment1Id);
    276 
    277         // Test with no attachment found - should return null
    278         String type = mMockResolver.getType(attachment1Uri);
    279         assertNull(type);
    280 
    281         // Add a couple of attachment entries.  Note, getType() just uses the DB, and does not
    282         // sample the files, so we won't bother creating the files
    283         Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message1Id, "file2", 100,
    284                 false, mMockContext);
    285         newAttachment2.mMimeType = "image/jpg";
    286         attachment2Id = addAttachmentToDb(account1, newAttachment2);
    287 
    288         Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message1Id, "file3", 100,
    289                 false, mMockContext);
    290         newAttachment3.mMimeType = "text/plain";
    291         attachment3Id = addAttachmentToDb(account1, newAttachment3);
    292 
    293         Attachment newAttachment4 = ProviderTestUtils.setupAttachment(message1Id, "file4.doc", 100,
    294                 false, mMockContext);
    295         newAttachment4.mMimeType = "application/octet-stream";
    296         attachment4Id = addAttachmentToDb(account1, newAttachment4);
    297 
    298         Attachment newAttachment5 = ProviderTestUtils.setupAttachment(message1Id, "file5.xyz", 100,
    299                 false, mMockContext);
    300         newAttachment5.mMimeType = "application/octet-stream";
    301         attachment5Id = addAttachmentToDb(account1, newAttachment5);
    302 
    303         Attachment newAttachment6 = ProviderTestUtils.setupAttachment(message1Id, "file6", 100,
    304                 false, mMockContext);
    305         newAttachment6.mMimeType = "";
    306         attachment6Id = addAttachmentToDb(account1, newAttachment6);
    307 
    308         // Check the returned filetypes
    309         Uri uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id);
    310         type = mMockResolver.getType(uri);
    311         assertEquals("image/jpg", type);
    312         uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment3Id);
    313         type = mMockResolver.getType(uri);
    314         assertEquals("text/plain", type);
    315         uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment4Id);
    316         type = mMockResolver.getType(uri);
    317         assertEquals("application/msword", type);
    318         uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment5Id);
    319         type = mMockResolver.getType(uri);
    320         assertEquals("application/xyz", type);
    321         uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment6Id);
    322         type = mMockResolver.getType(uri);
    323         assertEquals("application/octet-stream", type);
    324 
    325         // Check the returned filetypes for the thumbnails
    326         uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId, attachment2Id, 62,
    327                 62);
    328         type = mMockResolver.getType(uri);
    329         assertEquals("image/png", type);
    330         uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId, attachment3Id, 62,
    331                 62);
    332         type = mMockResolver.getType(uri);
    333         assertEquals("image/png", type);
    334     }
    335 
    336     /**
    337      * test openFile()
    338      *  - regular file
    339      *  - TODO: variations on the content URI
    340      */
    341     public void testOpenFile() throws MessagingException, IOException {
    342         Account account1 = ProviderTestUtils.setupAccount("open-file", false, mMockContext);
    343         account1.mCompatibilityUuid = "test-UUID";
    344         account1.save(mMockContext);
    345         final long message1Id = 1;
    346         long attachment1Id = 1;
    347         long attachment2Id = 2;
    348 
    349         // Note:  There is an implicit assumption in this test sequence that the first
    350         // attachment we add will be id=1 and the 2nd will have id=2.  This could fail on
    351         // a legitimate implementation.  Asserts below will catch this and fail the test
    352         // if necessary.
    353         Uri file1Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment1Id);
    354         Uri file2Uri = AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id);
    355 
    356         // Test with no attachment found
    357         AssetFileDescriptor afd;
    358         try {
    359             afd = mMockResolver.openAssetFileDescriptor(file1Uri, "r");
    360             fail("Should throw an exception on a missing attachment entry");
    361         } catch (FileNotFoundException fnf) {
    362             // expected
    363         }
    364 
    365         // Add an attachment (but no associated file)
    366         Attachment newAttachment = ProviderTestUtils.setupAttachment(message1Id, "file", 100,
    367                 false, mMockContext);
    368         attachment1Id = addAttachmentToDb(account1, newAttachment);
    369         assertEquals("Broken test:  Unexpected id assignment", 1, attachment1Id);
    370 
    371         // Test with an attached database, attachment entry found, but no attachment found
    372         try {
    373             afd = mMockResolver.openAssetFileDescriptor(file1Uri, "r");
    374             fail("Should throw an exception on a missing attachment file");
    375         } catch (FileNotFoundException fnf) {
    376             // expected
    377         }
    378 
    379         // Create an "attachment" by copying an image resource into a file
    380         /* String fileName = */ createAttachmentFile(account1, attachment2Id);
    381         Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message1Id, "file", 100,
    382                 false, mMockContext);
    383         newAttachment2.mContentId = null;
    384         newAttachment2.mContentUri =
    385                 AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id)
    386                 .toString();
    387         newAttachment2.mMimeType = "image/png";
    388         attachment2Id = addAttachmentToDb(account1, newAttachment2);
    389         assertEquals("Broken test:  Unexpected id assignment", 2, attachment2Id);
    390 
    391         // Test with an attached database, attachment entry found - returns a file
    392         afd = mMockResolver.openAssetFileDescriptor(file2Uri, "r");
    393         assertNotNull(afd);
    394         // TODO: Confirm it's the "right" file?
    395         afd.close();
    396     }
    397 
    398     /**
    399      * test openFile()
    400      *  - thumbnail
    401      * @throws IOException
    402      *
    403      * TODO:  The thumbnail mode returns null for its failure cases (and in one case, throws
    404      * an SQLiteException).  The ContentResolver contract requires throwing FileNotFoundException
    405      * in all of the non-success cases, and the provider should be fixed for consistency.
    406      */
    407     public void testOpenThumbnail() throws MessagingException, IOException {
    408         Account account1 = ProviderTestUtils.setupAccount("open-thumbnail", false, mMockContext);
    409         account1.mCompatibilityUuid = "test-UUID";
    410         account1.save(mMockContext);
    411         final long message1Id = 1;
    412         long attachment1Id = 1;
    413         long attachment2Id = 2;
    414 
    415         // Note:  There is an implicit assumption in this test sequence that the first
    416         // attachment we add will be id=1 and the 2nd will have id=2.  This could fail on
    417         // a legitimate implementation.  Asserts below will catch this and fail the test
    418         // if necessary.
    419         Uri thumb1Uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId,
    420                 attachment1Id, 62, 62);
    421         Uri thumb2Uri = AttachmentUtilities.getAttachmentThumbnailUri(account1.mId,
    422                 attachment2Id, 62, 62);
    423 
    424         // Test with an attached database, but no attachment found
    425         AssetFileDescriptor afd = mMockResolver.openAssetFileDescriptor(thumb1Uri, "r");
    426         assertNull(afd);
    427 
    428         // Add an attachment (but no associated file)
    429         Attachment newAttachment = ProviderTestUtils.setupAttachment(message1Id, "file", 100,
    430                 false, mMockContext);
    431         attachment1Id = addAttachmentToDb(account1, newAttachment);
    432         assertEquals("Broken test:  Unexpected id assignment", 1, attachment1Id);
    433 
    434         // Test with an attached database, attachment entry found, but no attachment found
    435         afd = mMockResolver.openAssetFileDescriptor(thumb1Uri, "r");
    436         assertNull(afd);
    437 
    438         // Create an "attachment" by copying an image resource into a file
    439         /* String fileName = */ createAttachmentFile(account1, attachment2Id);
    440         Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message1Id, "file", 100,
    441                 false, mMockContext);
    442         newAttachment2.mContentId = null;
    443         newAttachment2.mContentUri =
    444                 AttachmentUtilities.getAttachmentUri(account1.mId, attachment2Id)
    445                 .toString();
    446         newAttachment2.mMimeType = "image/png";
    447         attachment2Id = addAttachmentToDb(account1, newAttachment2);
    448         assertEquals("Broken test:  Unexpected id assignment", 2, attachment2Id);
    449 
    450         // Test with an attached database, attachment entry found - returns a thumbnail
    451         afd = mMockResolver.openAssetFileDescriptor(thumb2Uri, "r");
    452         assertNotNull(afd);
    453         // TODO: Confirm it's the "right" file?
    454         afd.close();
    455     }
    456 
    457     private Uri createAttachment(Account account, long messageId, String contentUriStr) {
    458         // Add an attachment entry.
    459         Attachment newAttachment = ProviderTestUtils.setupAttachment(messageId, "file", 100,
    460                 false, mMockContext);
    461         newAttachment.mContentUri = contentUriStr;
    462         long attachmentId = addAttachmentToDb(account, newAttachment);
    463         Uri attachmentUri = AttachmentUtilities.getAttachmentUri(account.mId, attachmentId);
    464         return attachmentUri;
    465     }
    466 
    467     /**
    468      * test resolveAttachmentIdToContentUri()
    469      *  - without DB
    470      *  - not in DB
    471      *  - in DB, with not-null contentUri
    472      *  - in DB, with null contentUri
    473      */
    474     public void testResolveAttachmentIdToContentUri() throws MessagingException {
    475         Account account1 = ProviderTestUtils.setupAccount("attachment-query", false, mMockContext);
    476         account1.mCompatibilityUuid = "test-UUID";
    477         account1.save(mMockContext);
    478         final long message1Id = 1;
    479         // We use attachmentId == 1 but any other id would do
    480         final long attachment1Id = 1;
    481         final Uri attachment1Uri = AttachmentUtilities.getAttachmentUri(account1.mId,
    482                 attachment1Id);
    483 
    484         // Test with no attachment found - should return input
    485         // We know that the attachmentId 1 does not exist because there are no attachments
    486         // created at this point
    487         Uri result = AttachmentUtilities.resolveAttachmentIdToContentUri(
    488                 mMockResolver, attachment1Uri);
    489         assertEquals(attachment1Uri, result);
    490 
    491         // Test with existing attachement and contentUri != null
    492         // Note, resolveAttachmentIdToContentUri() just uses
    493         // the DB, and does not sample the files, so we won't bother creating the files
    494         {
    495             Uri attachmentUri = createAttachment(account1, message1Id, "file:///path/to/file");
    496             Uri contentUri = AttachmentUtilities.resolveAttachmentIdToContentUri(
    497                     mMockResolver, attachmentUri);
    498             // When the attachment is found, return the stored content_uri value
    499             assertEquals("file:///path/to/file", contentUri.toString());
    500         }
    501 
    502         // Test with existing attachement and contentUri == null
    503         {
    504             Uri attachmentUri = createAttachment(account1, message1Id, null);
    505             Uri contentUri = AttachmentUtilities.resolveAttachmentIdToContentUri(
    506                     mMockResolver, attachmentUri);
    507             // When contentUri is null should return input
    508             assertEquals(attachmentUri, contentUri);
    509         }
    510     }
    511 
    512     /**
    513      * Test the functionality of deleting all attachment files for a given message.
    514      */
    515     public void testDeleteFiles() throws IOException {
    516         Account account1 = ProviderTestUtils.setupAccount("attachment-query", false, mMockContext);
    517         account1.mCompatibilityUuid = "test-UUID";
    518         account1.save(mMockContext);
    519         final long message1Id = 1;      // 1 attachment, 1 file
    520         final long message2Id = 2;      // 2 attachments, 2 files
    521         final long message3Id = 3;      // 1 attachment, missing file
    522         final long message4Id = 4;      // no attachments
    523 
    524         // Add attachment entries for various test messages
    525         Attachment newAttachment1 = ProviderTestUtils.setupAttachment(message1Id, "file1", 100,
    526                 true, mMockContext);
    527         Attachment newAttachment2 = ProviderTestUtils.setupAttachment(message2Id, "file2", 200,
    528                 true, mMockContext);
    529         Attachment newAttachment3 = ProviderTestUtils.setupAttachment(message2Id, "file3", 100,
    530                 true, mMockContext);
    531         Attachment newAttachment4 = ProviderTestUtils.setupAttachment(message3Id, "file4", 100,
    532                 true, mMockContext);
    533 
    534         // Create test files
    535         createAttachmentFile(account1, newAttachment1.mId);
    536         createAttachmentFile(account1, newAttachment2.mId);
    537         createAttachmentFile(account1, newAttachment3.mId);
    538 
    539         // Confirm 3 attachment files found
    540         File attachmentsDir = AttachmentUtilities.getAttachmentDirectory(mMockContext,
    541                 account1.mId);
    542         assertEquals(3, attachmentsDir.listFiles().length);
    543 
    544         // Command deletion of some files and check for results
    545 
    546         // Message 4 has no attachments so no files should be deleted
    547         AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
    548                 message4Id);
    549         assertEquals(3, attachmentsDir.listFiles().length);
    550 
    551         // Message 3 has no attachment files so no files should be deleted
    552         AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
    553                 message3Id);
    554         assertEquals(3, attachmentsDir.listFiles().length);
    555 
    556         // Message 2 has 2 attachment files so this should delete 2 files
    557         AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
    558                 message2Id);
    559         assertEquals(1, attachmentsDir.listFiles().length);
    560 
    561         // Message 1 has 1 attachment file so this should delete the last file
    562         AttachmentUtilities.deleteAllAttachmentFiles(mMockContext, account1.mId,
    563                 message1Id);
    564         assertEquals(0, attachmentsDir.listFiles().length);
    565     }
    566 
    567     /**
    568      * Test the functionality of deleting an entire mailbox's attachments.
    569      */
    570     public void testDeleteMailbox() throws IOException {
    571         Account account1 = ProviderTestUtils.setupAccount("attach-mbox-del", false, mMockContext);
    572         account1.mCompatibilityUuid = "test-UUID";
    573         account1.save(mMockContext);
    574         long account1Id = account1.mId;
    575         Mailbox mailbox1 = ProviderTestUtils.setupMailbox("mbox1", account1Id, true, mMockContext);
    576         long mailbox1Id = mailbox1.mId;
    577         Mailbox mailbox2 = ProviderTestUtils.setupMailbox("mbox2", account1Id, true, mMockContext);
    578         long mailbox2Id = mailbox2.mId;
    579 
    580         // Fill each mailbox with messages & attachments
    581         populateAccountMailbox(account1, mailbox1Id, 3);
    582         populateAccountMailbox(account1, mailbox2Id, 1);
    583 
    584         // Confirm four attachment files found
    585         File attachmentsDir = AttachmentUtilities.getAttachmentDirectory(mMockContext,
    586                 account1.mId);
    587         assertEquals(4, attachmentsDir.listFiles().length);
    588 
    589         // Command the deletion of mailbox 1 - we should lose 3 attachment files
    590         AttachmentUtilities.deleteAllMailboxAttachmentFiles(mMockContext, account1Id,
    591                 mailbox1Id);
    592         assertEquals(1, attachmentsDir.listFiles().length);
    593 
    594         // Command the deletion of mailbox 2 - we should lose 1 attachment file
    595         AttachmentUtilities.deleteAllMailboxAttachmentFiles(mMockContext, account1Id,
    596                 mailbox2Id);
    597         assertEquals(0, attachmentsDir.listFiles().length);
    598     }
    599 
    600     /**
    601      * Test the functionality of deleting an entire account's attachments.
    602      */
    603     public void testDeleteAccount() throws IOException {
    604         Account account1 = ProviderTestUtils.setupAccount("attach-acct-del1", false, mMockContext);
    605         account1.mCompatibilityUuid = "test-UUID";
    606         account1.save(mMockContext);
    607         long account1Id = account1.mId;
    608         Mailbox mailbox1 = ProviderTestUtils.setupMailbox("mbox1", account1Id, true, mMockContext);
    609         long mailbox1Id = mailbox1.mId;
    610         Mailbox mailbox2 = ProviderTestUtils.setupMailbox("mbox2", account1Id, true, mMockContext);
    611         long mailbox2Id = mailbox2.mId;
    612 
    613         // Repeat for account #2
    614         Account account2 = ProviderTestUtils.setupAccount("attach-acct-del2", false, mMockContext);
    615         account2.mCompatibilityUuid = "test-UUID-2";
    616         account2.save(mMockContext);
    617         long account2Id = account2.mId;
    618         Mailbox mailbox3 = ProviderTestUtils.setupMailbox("mbox3", account2Id, true, mMockContext);
    619         long mailbox3Id = mailbox3.mId;
    620         Mailbox mailbox4 = ProviderTestUtils.setupMailbox("mbox4", account2Id, true, mMockContext);
    621         long mailbox4Id = mailbox4.mId;
    622 
    623         // Fill each mailbox with messages & attachments
    624         populateAccountMailbox(account1, mailbox1Id, 3);
    625         populateAccountMailbox(account1, mailbox2Id, 1);
    626         populateAccountMailbox(account2, mailbox3Id, 5);
    627         populateAccountMailbox(account2, mailbox4Id, 2);
    628 
    629         // Confirm eleven attachment files found
    630         File directory1 = AttachmentUtilities.getAttachmentDirectory(mMockContext,
    631                 account1.mId);
    632         assertEquals(4, directory1.listFiles().length);
    633         File directory2 = AttachmentUtilities.getAttachmentDirectory(mMockContext,
    634                 account2.mId);
    635         assertEquals(7, directory2.listFiles().length);
    636 
    637         // Command the deletion of account 1 - we should lose 4 attachment files
    638         AttachmentUtilities.deleteAllAccountAttachmentFiles(mMockContext, account1Id);
    639         assertEquals(0, directory1.listFiles().length);
    640         assertEquals(7, directory2.listFiles().length);
    641 
    642         // Command the deletion of account 2 - we should lose 7 attachment file
    643         AttachmentUtilities.deleteAllAccountAttachmentFiles(mMockContext, account2Id);
    644         assertEquals(0, directory1.listFiles().length);
    645         assertEquals(0, directory2.listFiles().length);
    646     }
    647 
    648     /**
    649      * Create a set of attachments for a given test account and mailbox.  Creates the following:
    650      *  Two messages per mailbox, one w/attachments, one w/o attachments
    651      *  Any number of attachments (on the first message)
    652      *  @param account the account to populate
    653      *  @param mailboxId the mailbox to populate
    654      *  @param numAttachments how many attachments to create
    655      */
    656     private void populateAccountMailbox(Account account, long mailboxId, int numAttachments)
    657             throws IOException {
    658         long accountId = account.mId;
    659 
    660         // two messages per mailbox, one w/attachments, one w/o attachments
    661         Message message1a = ProviderTestUtils.setupMessage(
    662                 "msg1a", accountId, mailboxId, false, true, mMockContext);
    663         /* Message message1b = */ ProviderTestUtils.setupMessage(
    664                 "msg1b", accountId, mailboxId, false, true, mMockContext);
    665 
    666         // Create attachment records & files
    667         for (int count = 0; count < numAttachments; count++) {
    668             Attachment newAttachment = ProviderTestUtils.setupAttachment(message1a.mId,
    669                     "file" + count, 100 * count, true, mMockContext);
    670             createAttachmentFile(account, newAttachment.mId);
    671         }
    672     }
    673 
    674     /**
    675      * Create an attachment by copying an image resource into a file.  Uses "real" resources
    676      * to get a real image from Email
    677      */
    678     private String createAttachmentFile(Account forAccount, long id) throws IOException {
    679         File outFile = getAttachmentFile(forAccount, id);
    680         Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(),
    681                 R.drawable.ic_attachment_holo_light);
    682         FileOutputStream out = new FileOutputStream(outFile);
    683         bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
    684         out.close();
    685 
    686         return outFile.getAbsolutePath();
    687     }
    688 
    689     /**
    690      * Record an attachment in the attachments database
    691      * @return the id of the attachment just created
    692      */
    693     private long addAttachmentToDb(Account forAccount, Attachment newAttachment) {
    694         newAttachment.save(mMockContext);
    695         return newAttachment.mId;
    696     }
    697 
    698     /**
    699      * Map from account, attachment ID to attachment file
    700      */
    701     private File getAttachmentFile(Account forAccount, long id) {
    702         String idString = Long.toString(id);
    703         File attachmentsDir = mMockContext.getDatabasePath(forAccount.mId + ".db_att");
    704         if (!attachmentsDir.exists()) {
    705             attachmentsDir.mkdirs();
    706         }
    707         return new File(attachmentsDir, idString);
    708     }
    709 }
    710