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