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