ControllerProviderOpsTests.java revision 3096b4ae18f55c9ebf04d83c534da4d5e3370932
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;
18
19import com.android.email.provider.ContentCache;
20import com.android.email.provider.EmailProvider;
21import com.android.email.provider.ProviderTestUtils;
22import com.android.emailcommon.provider.EmailContent;
23import com.android.emailcommon.provider.EmailContent.Account;
24import com.android.emailcommon.provider.EmailContent.Body;
25import com.android.emailcommon.provider.EmailContent.Message;
26import com.android.emailcommon.provider.HostAuth;
27import com.android.emailcommon.provider.Mailbox;
28
29import android.content.Context;
30import android.net.Uri;
31import android.test.ProviderTestCase2;
32
33import java.util.Locale;
34import java.util.concurrent.ExecutionException;
35
36/**
37 * Tests of the Controller class that depend on the underlying provider.
38 *
39 * NOTE:  It would probably make sense to rewrite this using a MockProvider, instead of the
40 * ProviderTestCase (which is a real provider running on a temp database).  This would be more of
41 * a true "unit test".
42 *
43 * You can run this entire test case with:
44 *   runtest -c com.android.email.ControllerProviderOpsTests email
45 */
46public class ControllerProviderOpsTests extends ProviderTestCase2<EmailProvider> {
47
48    private Context mProviderContext;
49    private Context mContext;
50    private TestController mTestController;
51
52
53    public ControllerProviderOpsTests() {
54        super(EmailProvider.class, EmailContent.AUTHORITY);
55    }
56
57    @Override
58    public void setUp() throws Exception {
59        super.setUp();
60        mProviderContext = getMockContext();
61        mContext = getContext();
62        mTestController = new TestController(mProviderContext, mContext);
63        // Invalidate all caches, since we reset the database for each test
64        ContentCache.invalidateAllCachesForTest();
65    }
66
67    @Override
68    public void tearDown() throws Exception {
69        super.tearDown();
70        mTestController.cleanupForTest();
71    }
72
73    /**
74     * Lightweight subclass of the Controller class allows injection of mock context
75     */
76    public static class TestController extends Controller {
77
78        protected TestController(Context providerContext, Context systemContext) {
79            super(systemContext);
80            setProviderContext(providerContext);
81        }
82    }
83
84    /**
85     * These are strings that should not change per locale.
86     */
87    public void testGetMailboxServerName() {
88        assertEquals("", mTestController.getMailboxServerName(-1));
89
90        assertEquals("Inbox", mTestController.getMailboxServerName(Mailbox.TYPE_INBOX));
91        assertEquals("Outbox", mTestController.getMailboxServerName(Mailbox.TYPE_OUTBOX));
92        assertEquals("Trash", mTestController.getMailboxServerName(Mailbox.TYPE_TRASH));
93        assertEquals("Sent", mTestController.getMailboxServerName(Mailbox.TYPE_SENT));
94        assertEquals("Junk", mTestController.getMailboxServerName(Mailbox.TYPE_JUNK));
95
96        // Now try again with translation
97        Locale savedLocale = Locale.getDefault();
98        Locale.setDefault(Locale.FRANCE);
99        assertEquals("Inbox", mTestController.getMailboxServerName(Mailbox.TYPE_INBOX));
100        assertEquals("Outbox", mTestController.getMailboxServerName(Mailbox.TYPE_OUTBOX));
101        assertEquals("Trash", mTestController.getMailboxServerName(Mailbox.TYPE_TRASH));
102        assertEquals("Sent", mTestController.getMailboxServerName(Mailbox.TYPE_SENT));
103        assertEquals("Junk", mTestController.getMailboxServerName(Mailbox.TYPE_JUNK));
104        Locale.setDefault(savedLocale);
105    }
106
107    /**
108     * Test of Controller.createMailbox().
109     * Sunny day test only - creates a mailbox that does not exist.
110     * Does not test duplication, bad accountID, or any other bad input.
111     */
112    public void testCreateMailbox() {
113        Account account = ProviderTestUtils.setupAccount("mailboxid", true, mProviderContext);
114        long accountId = account.mId;
115
116        long oldBoxId = Mailbox.findMailboxOfType(mProviderContext, accountId, Mailbox.TYPE_DRAFTS);
117        assertEquals(Mailbox.NO_MAILBOX, oldBoxId);
118
119        mTestController.createMailbox(accountId, Mailbox.TYPE_DRAFTS);
120        long boxId = Mailbox.findMailboxOfType(mProviderContext, accountId, Mailbox.TYPE_DRAFTS);
121
122        // check that the drafts mailbox exists
123        assertTrue("mailbox exists", boxId != Mailbox.NO_MAILBOX);
124    }
125
126    /**
127     * Test of Controller.findOrCreateMailboxOfType().
128     * Checks:
129     * - finds correctly the ID of existing mailbox
130     * - creates non-existing mailbox
131     * - creates only once a new mailbox
132     * - when accountId or mailboxType are -1, returns NO_MAILBOX
133     */
134    public void testFindOrCreateMailboxOfType() {
135        Account account = ProviderTestUtils.setupAccount("mailboxid", true, mProviderContext);
136        long accountId = account.mId;
137        Mailbox box = ProviderTestUtils.setupMailbox("box", accountId, false, mProviderContext);
138        final int boxType = Mailbox.TYPE_TRASH;
139        box.mType = boxType;
140        box.save(mProviderContext);
141        long boxId = box.mId;
142
143        long testBoxId = mTestController.findOrCreateMailboxOfType(accountId, boxType);
144
145        // check it found the right mailbox id
146        assertEquals(boxId, testBoxId);
147
148        long boxId2 = mTestController.findOrCreateMailboxOfType(accountId, Mailbox.TYPE_DRAFTS);
149        assertTrue("mailbox created", boxId2 != Mailbox.NO_MAILBOX);
150        assertTrue("with different id", testBoxId != boxId2);
151
152        // check it doesn't create twice when existing
153        long boxId3 = mTestController.findOrCreateMailboxOfType(accountId, Mailbox.TYPE_DRAFTS);
154        assertEquals("don't create if exists", boxId3, boxId2);
155
156        // check invalid aruments
157        assertEquals(Mailbox.NO_MAILBOX,
158                mTestController.findOrCreateMailboxOfType(-1, Mailbox.TYPE_DRAFTS));
159        assertEquals(Mailbox.NO_MAILBOX, mTestController.findOrCreateMailboxOfType(accountId, -1));
160    }
161
162    /**
163     * Test the "move message" function.
164     */
165    public void testMoveMessage() throws InterruptedException, ExecutionException {
166        Account account1 = ProviderTestUtils.setupAccount("message-move", true, mProviderContext);
167        long account1Id = account1.mId;
168        Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mProviderContext);
169        long box1Id = box1.mId;
170        Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mProviderContext);
171        long box2Id = box2.mId;
172        Mailbox boxDest = ProviderTestUtils.setupMailbox("d", account1Id, true, mProviderContext);
173        long boxDestId = boxDest.mId;
174
175        Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false,
176                true, mProviderContext);
177        Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box2Id, false,
178                true, mProviderContext);
179        long message1Id = message1.mId;
180        long message2Id = message2.mId;
181
182        // Because moveMessage runs asynchronously, call get() to force it to complete
183        mTestController.moveMessages(new long[] { message1Id, message2Id }, boxDestId).get();
184
185        // now read back a fresh copy and confirm it's in the trash
186        assertEquals(boxDestId, EmailContent.Message.restoreMessageWithId(mProviderContext,
187                message1Id).mMailboxKey);
188        assertEquals(boxDestId, EmailContent.Message.restoreMessageWithId(mProviderContext,
189                message2Id).mMailboxKey);
190    }
191
192    /**
193     * Test the "delete message" function.  Sunny day:
194     *    - message/mailbox/account all exist
195     *    - trash mailbox exists
196     */
197    public void testDeleteMessage() {
198        Account account1 = ProviderTestUtils.setupAccount("message-delete", true, mProviderContext);
199        long account1Id = account1.mId;
200        Mailbox box = ProviderTestUtils.setupMailbox("box1", account1Id, true, mProviderContext);
201        long boxId = box.mId;
202
203        Mailbox trashBox = ProviderTestUtils.setupMailbox("box2", account1Id, false,
204                mProviderContext);
205        trashBox.mType = Mailbox.TYPE_TRASH;
206        trashBox.save(mProviderContext);
207        long trashBoxId = trashBox.mId;
208
209        Mailbox draftBox = ProviderTestUtils.setupMailbox("box3", account1Id, false,
210                mProviderContext);
211        draftBox.mType = Mailbox.TYPE_DRAFTS;
212        draftBox.save(mProviderContext);
213        long draftBoxId = draftBox.mId;
214
215        {
216            // Case 1: Message in a regular mailbox, account known.
217            Message message = ProviderTestUtils.setupMessage("message1", account1Id, boxId, false,
218                    true, mProviderContext);
219            long messageId = message.mId;
220
221            mTestController.deleteMessageSync(messageId);
222
223            // now read back a fresh copy and confirm it's in the trash
224            Message restored = EmailContent.Message.restoreMessageWithId(mProviderContext,
225                    messageId);
226            assertEquals(trashBoxId, restored.mMailboxKey);
227        }
228
229        {
230            // Case 2: Already in trash
231            Message message = ProviderTestUtils.setupMessage("message3", account1Id, trashBoxId,
232                    false, true, mProviderContext);
233            long messageId = message.mId;
234
235            mTestController.deleteMessageSync(messageId);
236
237            // Message should be deleted.
238            assertNull(EmailContent.Message.restoreMessageWithId(mProviderContext, messageId));
239        }
240
241        {
242            // Case 3: Draft
243            Message message = ProviderTestUtils.setupMessage("message3", account1Id, draftBoxId,
244                    false, true, mProviderContext);
245            long messageId = message.mId;
246
247            mTestController.deleteMessageSync(messageId);
248
249            // Message should be deleted.
250            assertNull(EmailContent.Message.restoreMessageWithId(mProviderContext, messageId));
251        }
252    }
253
254    /**
255     * Test deleting message when there is no trash mailbox
256     */
257    public void testDeleteMessageNoTrash() {
258        Account account1 =
259                ProviderTestUtils.setupAccount("message-delete-notrash", true, mProviderContext);
260        long account1Id = account1.mId;
261        Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mProviderContext);
262        long box1Id = box1.mId;
263
264        Message message1 =
265                ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true,
266                        mProviderContext);
267        long message1Id = message1.mId;
268
269        mTestController.deleteMessageSync(message1Id);
270
271        // now read back a fresh copy and confirm it's in the trash
272        Message message1get =
273                EmailContent.Message.restoreMessageWithId(mProviderContext, message1Id);
274
275        // check the new mailbox and see if it looks right
276        assertFalse(-1 == message1get.mMailboxKey);
277        assertFalse(box1Id == message1get.mMailboxKey);
278        Mailbox mailbox2get = Mailbox.restoreMailboxWithId(mProviderContext,
279                message1get.mMailboxKey);
280        assertEquals(Mailbox.TYPE_TRASH, mailbox2get.mType);
281    }
282
283    /**
284     * Test read/unread flag
285     */
286    public void testReadUnread() throws InterruptedException, ExecutionException {
287        Account account1 = ProviderTestUtils.setupAccount("read-unread", false, mProviderContext);
288        account1.mHostAuthRecv
289                = ProviderTestUtils.setupHostAuth("read-unread", 0, false, mProviderContext);
290        account1.save(mProviderContext);
291        long account1Id = account1.mId;
292        long box1Id = 2;
293
294        Message message1 =
295                ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true,
296                        mProviderContext);
297        long message1Id = message1.mId;
298
299        // test setting to "read"
300        mTestController.setMessageRead(message1Id, true).get();
301        Message message1get = Message.restoreMessageWithId(mProviderContext, message1Id);
302        assertTrue(message1get.mFlagRead);
303
304        // test setting to "unread"
305        mTestController.setMessageRead(message1Id, false).get();
306        message1get = Message.restoreMessageWithId(mProviderContext, message1Id);
307        assertFalse(message1get.mFlagRead);
308
309        // test setting to "read"
310        mTestController.setMessageRead(message1Id, true).get();
311        message1get = Message.restoreMessageWithId(mProviderContext, message1Id);
312        assertTrue(message1get.mFlagRead);
313    }
314
315    /**
316     * Test favorites flag
317     */
318    public void testFavorites() throws InterruptedException, ExecutionException {
319        Account account1 = ProviderTestUtils.setupAccount("favorites", false, mProviderContext);
320        account1.mHostAuthRecv
321                = ProviderTestUtils.setupHostAuth("favorites", 0, false, mProviderContext);
322        account1.save(mProviderContext);
323        long account1Id = account1.mId;
324        long box1Id = 2;
325
326        Message message1 =
327                ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true,
328                        mProviderContext);
329        long message1Id = message1.mId;
330
331        // test setting to "favorite"
332        mTestController.setMessageFavorite(message1Id, true).get();
333        Message message1get = Message.restoreMessageWithId(mProviderContext, message1Id);
334        assertTrue(message1get.mFlagFavorite);
335
336        // test setting to "not favorite"
337        mTestController.setMessageFavorite(message1Id, false).get();
338        message1get = Message.restoreMessageWithId(mProviderContext, message1Id);
339        assertFalse(message1get.mFlagFavorite);
340
341        // test setting to "favorite"
342        mTestController.setMessageFavorite(message1Id, true).get();
343        message1get = Message.restoreMessageWithId(mProviderContext, message1Id);
344        assertTrue(message1get.mFlagFavorite);
345    }
346
347    public void testGetAndDeleteAttachmentMailbox() {
348        Mailbox box = mTestController.getAttachmentMailbox();
349        assertNotNull(box);
350        Mailbox anotherBox = mTestController.getAttachmentMailbox();
351        assertNotNull(anotherBox);
352        // We should always get back the same Mailbox row
353        assertEquals(box.mId, anotherBox.mId);
354        // Add two messages to this mailbox
355        ProviderTestUtils.setupMessage("message1", 0, box.mId, false, true,
356                mProviderContext);
357        ProviderTestUtils.setupMessage("message2", 0, box.mId, false, true,
358                mProviderContext);
359        // Make sure we can find them where they are expected
360        assertEquals(2, EmailContent.count(mProviderContext, Message.CONTENT_URI,
361                Message.MAILBOX_KEY + "=?", new String[] {Long.toString(box.mId)}));
362        // Delete them
363        mTestController.deleteAttachmentMessages();
364        // Make sure they're gone
365        assertEquals(0, EmailContent.count(mProviderContext, Message.CONTENT_URI,
366                Message.MAILBOX_KEY + "=?", new String[] {Long.toString(box.mId)}));
367    }
368
369    /**
370     * Test wiping an account's synced data.  Everything should go, but account & empty inbox.
371     * Also ensures that the remaining account and the remaining inbox have cleared their
372     * server sync keys, to force refresh eventually.
373     */
374    public void testWipeSyncedData() {
375        Account account1 = ProviderTestUtils.setupAccount("wipe-synced-1", false, mProviderContext);
376        account1.mSyncKey = "account-1-sync-key";
377        account1.save(mProviderContext);
378        long account1Id = account1.mId;
379        Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, false, mProviderContext);
380        box1.mType = Mailbox.TYPE_INBOX;
381        box1.mSyncKey = "box-1-sync-key";
382        box1.save(mProviderContext);
383        long box1Id = box1.mId;
384        Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mProviderContext);
385        long box2Id = box2.mId;
386        // An EAS account mailbox
387        Mailbox eas = ProviderTestUtils.setupMailbox("eas", account1Id, false, mProviderContext);
388        eas.mType = Mailbox.TYPE_EAS_ACCOUNT_MAILBOX;
389        eas.save(mProviderContext);
390
391        Account account2 = ProviderTestUtils.setupAccount("wipe-synced-2", false, mProviderContext);
392        account2.mSyncKey = "account-2-sync-key";
393        account2.save(mProviderContext);
394        long account2Id = account2.mId;
395        Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account2Id, false, mProviderContext);
396        box3.mSyncKey = "box-3-sync-key";
397        box3.mType = Mailbox.TYPE_INBOX;
398        box3.save(mProviderContext);
399        long box3Id = box3.mId;
400        Mailbox box4 = ProviderTestUtils.setupMailbox("box4", account2Id, true, mProviderContext);
401        long box4Id = box4.mId;
402
403        // Now populate the 4 non-account boxes with messages
404        Message message = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false,
405                true, mProviderContext);
406        long message1Id = message.mId;
407        message = ProviderTestUtils.setupMessage("message2", account1Id, box2Id, false,
408                true, mProviderContext);
409        long message2Id = message.mId;
410        message = ProviderTestUtils.setupMessage("message3", account2Id, box3Id, false,
411                true, mProviderContext);
412        long message3Id = message.mId;
413        message = ProviderTestUtils.setupMessage("message4", account2Id, box4Id, false,
414                true, mProviderContext);
415        long message4Id = message.mId;
416
417        // Now wipe account 1's data
418        mTestController.deleteSyncedDataSync(account1Id);
419
420        // Confirm:  Mailboxes gone (except account box), all messages gone, account survives
421        assertNull(Mailbox.restoreMailboxWithId(mProviderContext, box1Id));
422        assertNull(Mailbox.restoreMailboxWithId(mProviderContext, box2Id));
423        assertNotNull(Mailbox.restoreMailboxWithId(mProviderContext, eas.mId));
424        assertNull(Message.restoreMessageWithId(mProviderContext, message1Id));
425        assertNull(Message.restoreMessageWithId(mProviderContext, message2Id));
426        account1 = Account.restoreAccountWithId(mProviderContext, account1Id);
427        assertNotNull(account1);
428        assertNull(account1.mSyncKey);
429
430        // Confirm:  Other account survived
431        assertNotNull(Mailbox.restoreMailboxWithId(mProviderContext, box3Id));
432        assertNotNull(Mailbox.restoreMailboxWithId(mProviderContext, box4Id));
433        assertNotNull(Message.restoreMessageWithId(mProviderContext, message3Id));
434        assertNotNull(Message.restoreMessageWithId(mProviderContext, message4Id));
435        assertNotNull(Account.restoreAccountWithId(mProviderContext, account2Id));
436    }
437
438    public void testLoadMessageFromUri() throws Exception {
439        // Create a simple message
440        Message msg = new Message();
441        String text = "This is some text";
442        msg.mText = text;
443        String sender = "sender@host.com";
444        msg.mFrom = sender;
445        // Save this away
446        msg.save(mProviderContext);
447
448        Uri fileUri = ProviderTestUtils.createTempEmlFile(mProviderContext, msg,
449                mContext.getFilesDir());
450
451        // Load the message via Controller and a Uri
452        Message loadedMsg = mTestController.loadMessageFromUri(fileUri);
453
454        // Check server id, mailbox key, account key, and from
455        assertNotNull(loadedMsg);
456        assertTrue(loadedMsg.mServerId.startsWith(Controller.ATTACHMENT_MESSAGE_UID_PREFIX));
457        Mailbox box = mTestController.getAttachmentMailbox();
458        assertNotNull(box);
459        assertEquals(box.mId, loadedMsg.mMailboxKey);
460        assertEquals(0, loadedMsg.mAccountKey);
461        assertEquals(loadedMsg.mFrom, sender);
462        // Check body text
463        String loadedMsgText = Body.restoreBodyTextWithMessageId(mProviderContext, loadedMsg.mId);
464        assertEquals(text, loadedMsgText);
465    }
466
467    /**
468     * Create a simple HostAuth with protocol
469     */
470    private HostAuth setupSimpleHostAuth(String protocol) {
471        HostAuth hostAuth = new HostAuth();
472        hostAuth.mProtocol = protocol;
473        return hostAuth;
474    }
475
476    public void testIsMessagingController() {
477        Account account1 = ProviderTestUtils.setupAccount("account1", false,
478                mProviderContext);
479        account1.mHostAuthRecv = setupSimpleHostAuth("eas");
480        account1.save(mProviderContext);
481        assertFalse(mTestController.isMessagingController(account1));
482        Account account2 = ProviderTestUtils.setupAccount("account2", false,
483                mProviderContext);
484        account2.mHostAuthRecv = setupSimpleHostAuth("imap");
485        account2.save(mProviderContext);
486        assertTrue(mTestController.isMessagingController(account2));
487        Account account3 = ProviderTestUtils.setupAccount("account3", false,
488                mProviderContext);
489        account3.mHostAuthRecv = setupSimpleHostAuth("pop3");
490        account3.save(mProviderContext);
491        assertTrue(mTestController.isMessagingController(account3));
492        Account account4 = ProviderTestUtils.setupAccount("account4", false,
493                mProviderContext);
494        account4.mHostAuthRecv = setupSimpleHostAuth("smtp");
495        account4.save(mProviderContext);
496        assertFalse(mTestController.isMessagingController(account4));
497        // There should be values for all of these accounts in the legacy map
498        assertNotNull(mTestController.mLegacyControllerMap.get(account1.mId));
499        assertNotNull(mTestController.mLegacyControllerMap.get(account2.mId));
500        assertNotNull(mTestController.mLegacyControllerMap.get(account3.mId));
501        assertNotNull(mTestController.mLegacyControllerMap.get(account4.mId));
502        // The map should have the expected values
503        assertFalse(mTestController.mLegacyControllerMap.get(account1.mId));
504        assertTrue(mTestController.mLegacyControllerMap.get(account2.mId));
505        assertTrue(mTestController.mLegacyControllerMap.get(account3.mId));
506        assertFalse(mTestController.mLegacyControllerMap.get(account4.mId));
507        // This second pass should pull values from the cache
508        assertFalse(mTestController.isMessagingController(account1));
509        assertTrue(mTestController.isMessagingController(account2));
510        assertTrue(mTestController.isMessagingController(account3));
511        assertFalse(mTestController.isMessagingController(account4));
512    }
513
514    /**
515     * TODO: releasing associated data (e.g. attachments, embedded images)
516     */
517}
518