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 AttachmentProviderTests()56 public AttachmentProviderTests() { 57 super(AttachmentProvider.class, AttachmentUtilities.AUTHORITY); 58 } 59 60 @Override setUp()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 */ testUnimplemented()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 */ testQuery()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 createMessage(Context c, Mailbox b)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 testInboxQuery()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 */ testGetType()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 */ testOpenFile()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 */ testOpenThumbnail()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 createAttachment(Account account, long messageId, String contentUriStr)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 */ testResolveAttachmentIdToContentUri()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 */ testDeleteFiles()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 */ testDeleteMailbox()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 */ testDeleteAccount()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 */ populateAccountMailbox(Account account, long mailboxId, int numAttachments)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 */ createAttachmentFile(Account forAccount, long id)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 */ addAttachmentToDb(Account forAccount, Attachment newAttachment)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 */ getAttachmentFile(Account forAccount, long id)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