• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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.exchange.provider;
18 
19 import com.android.emailcommon.provider.Account;
20 import com.android.emailcommon.provider.EmailContent.MailboxColumns;
21 import com.android.emailcommon.provider.Mailbox;
22 import com.android.exchange.utility.ExchangeTestCase;
23 
24 import android.content.ContentResolver;
25 import android.content.ContentUris;
26 import android.content.ContentValues;
27 import android.test.suitebuilder.annotation.MediumTest;
28 
29 /**
30  * Tests of MailboxUtilities.
31  *
32  * You can run this entire test case with:
33  *   runtest -c com.android.exchange.provider.MailboxUtilitiesTests exchange
34  */
35 @MediumTest
36 public class MailboxUtilitiesTests extends ExchangeTestCase {
37 
38     // All tests must build their accounts in mAccount so it will be deleted from live data
39     private Account mAccount;
40     private ContentResolver mResolver;
41     private ContentValues mNullParentKey;
42 
43     // Flag sets found in regular email folders that are parents or children
44     private static final int PARENT_FLAGS =
45             Mailbox.FLAG_ACCEPTS_MOVED_MAIL | Mailbox.FLAG_HOLDS_MAIL |
46             Mailbox.FLAG_HAS_CHILDREN | Mailbox.FLAG_CHILDREN_VISIBLE;
47     private static final int CHILD_FLAGS =
48             Mailbox.FLAG_ACCEPTS_MOVED_MAIL | Mailbox.FLAG_HOLDS_MAIL;
49 
50     @Override
setUp()51     public void setUp() throws Exception {
52         super.setUp();
53         mAccount = null;
54         mResolver = mProviderContext.getContentResolver();
55         mNullParentKey = new ContentValues();
56         mNullParentKey.putNull(Mailbox.PARENT_KEY);
57     }
58 
59     @Override
tearDown()60     public void tearDown() throws Exception {
61         super.tearDown();
62         // If we've created and saved an account, delete it
63         if (mAccount != null && mAccount.mId > 0) {
64             mResolver.delete(
65                     ContentUris.withAppendedId(Account.CONTENT_URI, mAccount.mId), null, null);
66         }
67     }
68 
testSetupParentKeyAndFlag()69     public void testSetupParentKeyAndFlag() {
70         // Set up account and various mailboxes with/without parents
71         mAccount = setupTestAccount("acct1", true);
72         Mailbox box1 = EmailContentSetupUtils.setupMailbox("box1", mAccount.mId, true,
73                 mProviderContext, Mailbox.TYPE_DRAFTS);
74         Mailbox box2 = EmailContentSetupUtils.setupMailbox("box2", mAccount.mId, true,
75                 mProviderContext, Mailbox.TYPE_OUTBOX, box1);
76         Mailbox box3 = EmailContentSetupUtils.setupMailbox("box3", mAccount.mId, true,
77                 mProviderContext, Mailbox.TYPE_ATTACHMENT, box1);
78         Mailbox box4 = EmailContentSetupUtils.setupMailbox("box4", mAccount.mId, true,
79                 mProviderContext, Mailbox.TYPE_NOT_SYNCABLE + 64, box3);
80         Mailbox box5 = EmailContentSetupUtils.setupMailbox("box5", mAccount.mId, true,
81                 mProviderContext, Mailbox.TYPE_MAIL, box3);
82 
83         // To make this work, we need to manually set parentKey to null for all mailboxes
84         // This simulates an older database needing update
85         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
86 
87         // Hand-create the account selector for our account
88         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
89 
90         // Fix up the database and restore the mailboxes
91         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
92         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
93         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
94         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
95         box4 = Mailbox.restoreMailboxWithId(mProviderContext, box4.mId);
96         box5 = Mailbox.restoreMailboxWithId(mProviderContext, box5.mId);
97 
98         // Test that flags and parent key are set properly
99         assertEquals(Mailbox.FLAG_HOLDS_MAIL | Mailbox.FLAG_HAS_CHILDREN |
100                 Mailbox.FLAG_CHILDREN_VISIBLE, box1.mFlags);
101         assertEquals(-1, box1.mParentKey);
102 
103         assertEquals(Mailbox.FLAG_HOLDS_MAIL, box2.mFlags);
104         assertEquals(box1.mId, box2.mParentKey);
105 
106         assertEquals(Mailbox.FLAG_HAS_CHILDREN | Mailbox.FLAG_CHILDREN_VISIBLE, box3.mFlags);
107         assertEquals(box1.mId, box3.mParentKey);
108 
109         assertEquals(0, box4.mFlags);
110         assertEquals(box3.mId, box4.mParentKey);
111 
112         assertEquals(Mailbox.FLAG_HOLDS_MAIL | Mailbox.FLAG_ACCEPTS_MOVED_MAIL, box5.mFlags);
113         assertEquals(box3.mId, box5.mParentKey);
114     }
115 
simulateFolderSyncChangeHandling(String accountSelector, Mailbox...mailboxes)116     private void simulateFolderSyncChangeHandling(String accountSelector, Mailbox...mailboxes) {
117         // Run the parent key analyzer and reload the mailboxes
118         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
119         for (Mailbox mailbox: mailboxes) {
120             String serverId = mailbox.mServerId;
121             MailboxUtilities.setFlagsAndChildrensParentKey(mProviderContext, accountSelector,
122                     serverId);
123         }
124     }
125 
126     /**
127      * Test three cases of adding a folder to an existing hierarchy.  Case 1:  Add to parent.
128      */
testParentKeyAddFolder1()129     public void testParentKeyAddFolder1() {
130         // Set up account and various mailboxes with/without parents
131         mAccount = setupTestAccount("acct1", true);
132         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
133 
134         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
135                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
136         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
137                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
138 
139         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
140         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
141 
142         // Run the parent key analyzer to set up the initial hierarchy.
143         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
144         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
145         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
146 
147         // Confirm flags and parent key(s) as expected
148         assertEquals(PARENT_FLAGS, box1.mFlags);
149         assertEquals(-1, box1.mParentKey);
150 
151         assertEquals(CHILD_FLAGS, box2.mFlags);
152         assertEquals(box1.mId, box2.mParentKey);
153 
154         // The specific test:  Create a 3rd mailbox and attach it to box1 (already a parent)
155 
156         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
157                 "box3", mAccount.mId, false, mProviderContext, Mailbox.TYPE_MAIL, box1);
158         box3.mParentKey = Mailbox.PARENT_KEY_UNINITIALIZED;
159         box3.save(mProviderContext);
160         simulateFolderSyncChangeHandling(accountSelector, box1 /*box3's parent*/);
161 
162         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
163         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
164         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
165 
166         // Confirm flags and parent key(s) as expected
167         assertEquals(PARENT_FLAGS, box1.mFlags);
168         assertEquals(-1, box1.mParentKey);
169 
170         assertEquals(CHILD_FLAGS, box2.mFlags);
171         assertEquals(box1.mId, box2.mParentKey);
172 
173         assertEquals(CHILD_FLAGS, box3.mFlags);
174         assertEquals(box1.mId, box3.mParentKey);
175     }
176 
177     /**
178      * Test three cases of adding a folder to an existing hierarchy.  Case 2:  Add to child.
179      */
testParentKeyAddFolder2()180     public void testParentKeyAddFolder2() {
181         // Set up account and various mailboxes with/without parents
182         mAccount = setupTestAccount("acct1", true);
183         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
184 
185         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
186                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
187         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
188                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
189 
190         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
191         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
192 
193         // Run the parent key analyzer to set up the initial hierarchy.
194         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
195 
196         // Skipping tests of initial hierarchy - see testParentKeyAddFolder1()
197 
198         // The specific test:  Create a 3rd mailbox and attach it to box2 (currently a child)
199 
200         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
201                 "box3", mAccount.mId, false, mProviderContext, Mailbox.TYPE_MAIL, box2);
202         box3.mParentKey = Mailbox.PARENT_KEY_UNINITIALIZED;
203         box3.save(mProviderContext);
204         simulateFolderSyncChangeHandling(accountSelector, box2 /*box3's parent*/);
205 
206         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
207         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
208         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
209 
210         // Confirm flags and parent key(s) as expected
211         assertEquals(PARENT_FLAGS, box1.mFlags);
212         assertEquals(-1, box1.mParentKey);
213 
214         assertEquals(PARENT_FLAGS, box2.mFlags);    // should become a parent
215         assertEquals(box1.mId, box2.mParentKey);
216 
217         assertEquals(CHILD_FLAGS, box3.mFlags);     // should be child of box2
218         assertEquals(box2.mId, box3.mParentKey);
219     }
220 
221     /**
222      * Test three cases of adding a folder to an existing hierarchy.  Case 3:  Add to root.
223      */
testParentKeyAddFolder3()224     public void testParentKeyAddFolder3() {
225         // Set up account and various mailboxes with/without parents
226         mAccount = setupTestAccount("acct1", true);
227         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
228 
229         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
230                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
231         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
232                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
233 
234         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
235         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
236 
237         // Run the parent key analyzer to set up the initial hierarchy.
238         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
239 
240         // Skipping tests of initial hierarchy - see testParentKeyAddFolder1()
241 
242         // The specific test:  Create a 3rd mailbox and give it no parent (it's top-level).
243 
244         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
245                 "box3", mAccount.mId, false, mProviderContext, Mailbox.TYPE_MAIL);
246         box3.mParentKey = Mailbox.PARENT_KEY_UNINITIALIZED;
247         box3.save(mProviderContext);
248 
249         simulateFolderSyncChangeHandling(accountSelector);
250         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
251         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
252         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
253 
254         // Confirm flags and parent key(s) as expected
255         assertEquals(PARENT_FLAGS, box1.mFlags);
256         assertEquals(-1, box1.mParentKey);
257 
258         assertEquals(CHILD_FLAGS, box2.mFlags);
259         assertEquals(box1.mId, box2.mParentKey);
260 
261         assertEquals(CHILD_FLAGS, box3.mFlags);
262         assertEquals(-1, box3.mParentKey);
263     }
264 
265     /**
266      * Test three cases of removing a folder from the hierarchy.  Case 1:  Remove from parent.
267      */
testParentKeyRemoveFolder1()268     public void testParentKeyRemoveFolder1() {
269         // Set up account and mailboxes
270         mAccount = setupTestAccount("acct1", true);
271         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
272 
273         // Initial configuration for this test:  box1 has two children.
274         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
275                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
276         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
277                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
278         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
279                 "box3", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
280 
281         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
282         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
283 
284         // Confirm initial configuration as expected
285         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
286         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
287         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
288         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
289 
290         // Confirm flags and parent key(s) as expected
291         assertEquals(PARENT_FLAGS, box1.mFlags);
292         assertEquals(-1, box1.mParentKey);
293 
294         assertEquals(CHILD_FLAGS, box2.mFlags);
295         assertEquals(box1.mId, box2.mParentKey);
296 
297         assertEquals(CHILD_FLAGS, box3.mFlags);
298         assertEquals(box1.mId, box3.mParentKey);
299 
300         // The specific test:  Delete box3 and check remaining configuration
301         mResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box3.mId), null, null);
302         simulateFolderSyncChangeHandling(accountSelector, box1 /*box3's parent*/);
303 
304         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
305         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
306         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
307 
308         // Confirm flags and parent key(s) as expected
309         assertEquals(PARENT_FLAGS, box1.mFlags);        // Should still be a parent
310         assertEquals(-1, box1.mParentKey);
311 
312         assertEquals(CHILD_FLAGS, box2.mFlags);
313         assertEquals(box1.mId, box2.mParentKey);
314 
315         assertNull(box3);
316     }
317 
318     /**
319      * Test three cases of removing a folder from the hierarchy.  Case 2:  Remove from child.
320      */
testParentKeyRemoveFolder2()321     public void testParentKeyRemoveFolder2() {
322         // Set up account and mailboxes
323         mAccount = setupTestAccount("acct1", true);
324         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
325 
326         // Initial configuration for this test:  box1 has box2 and box2 has box3.
327         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
328                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
329         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
330                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
331         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
332                 "box3", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box2);
333 
334         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
335         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
336 
337         // Confirm initial configuration as expected
338         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
339         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
340         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
341         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
342 
343         // Confirm flags and parent key(s) as expected
344         assertEquals(PARENT_FLAGS, box1.mFlags);
345         assertEquals(-1, box1.mParentKey);
346 
347         assertEquals(PARENT_FLAGS, box2.mFlags);    // becomes a parent
348         assertEquals(box1.mId, box2.mParentKey);
349 
350         assertEquals(CHILD_FLAGS, box3.mFlags);
351         assertEquals(box2.mId, box3.mParentKey);
352 
353         // The specific test:  Delete box3 and check remaining configuration
354         mResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box3.mId), null, null);
355         simulateFolderSyncChangeHandling(accountSelector, box2 /*box3's parent*/);
356 
357         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
358         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
359         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
360 
361         // Confirm flags and parent key(s) as expected
362         assertEquals(PARENT_FLAGS, box1.mFlags);        // Should still be a parent
363         assertEquals(-1, box1.mParentKey);
364 
365         assertEquals(CHILD_FLAGS, box2.mFlags);         // Becomes a child
366         assertEquals(box1.mId, box2.mParentKey);
367 
368         assertNull(box3);
369     }
370 
371     /**
372      * Test three cases of removing a folder from the hierarchy.  Case 3:  Remove from root.
373      */
testParentKeyRemoveFolder3()374     public void testParentKeyRemoveFolder3() {
375         // Set up account and mailboxes
376         mAccount = setupTestAccount("acct1", true);
377         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
378 
379         // Initial configuration for this test:  box1 has box2, box3 is also at root.
380         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
381                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
382         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
383                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
384         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
385                 "box3", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
386 
387         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
388         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
389 
390         // Confirm initial configuration as expected
391         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
392         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
393         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
394         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
395 
396         // Confirm flags and parent key(s) as expected
397         assertEquals(PARENT_FLAGS, box1.mFlags);
398         assertEquals(-1, box1.mParentKey);
399 
400         assertEquals(CHILD_FLAGS, box2.mFlags);
401         assertEquals(box1.mId, box2.mParentKey);
402 
403         assertEquals(CHILD_FLAGS, box3.mFlags);
404         assertEquals(-1, box3.mParentKey);
405 
406         // The specific test:  Delete box3 and check remaining configuration
407         mResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box3.mId), null, null);
408         simulateFolderSyncChangeHandling(accountSelector);
409 
410         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
411         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
412         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
413 
414         // Confirm flags and parent key(s) as expected
415         assertEquals(PARENT_FLAGS, box1.mFlags);        // Should still be a parent
416         assertEquals(-1, box1.mParentKey);
417 
418         assertEquals(CHILD_FLAGS, box2.mFlags);         // Should still be a child
419         assertEquals(box1.mId, box2.mParentKey);
420 
421         assertNull(box3);
422     }
423 
424     /**
425      * Test changing a parent from none
426      */
testChangeFromNoParentToParent()427     public void testChangeFromNoParentToParent() {
428         // Set up account and mailboxes
429         mAccount = setupTestAccount("acct1", true);
430         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
431 
432         // Initial configuration for this test:  box1 has box2, box3 is also at root.
433         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
434                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
435         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
436                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
437         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
438                 "box3", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
439 
440         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
441         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
442 
443         // Confirm initial configuration as expected
444         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
445         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
446         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
447         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
448 
449         // Confirm flags and parent key(s) as expected
450         assertEquals(PARENT_FLAGS, box1.mFlags);
451         assertEquals(-1, box1.mParentKey);
452 
453         assertEquals(CHILD_FLAGS, box2.mFlags);
454         assertEquals(box1.mId, box2.mParentKey);
455 
456         assertEquals(CHILD_FLAGS, box3.mFlags);
457         assertEquals(-1, box3.mParentKey);
458 
459         // The specific test:  Give box 3 a new parent (box 2) and check remaining configuration
460         ContentValues values = new ContentValues();
461         values.put(Mailbox.PARENT_SERVER_ID, box2.mServerId);
462         mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box3.mId), values,
463                 null, null);
464         simulateFolderSyncChangeHandling(accountSelector, box2 /*box3's new parent*/);
465 
466         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
467         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
468         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
469 
470         // Confirm flags and parent key(s) as expected
471         assertEquals(PARENT_FLAGS, box1.mFlags);        // Should still be a parent
472         assertEquals(-1, box1.mParentKey);
473 
474         assertEquals(PARENT_FLAGS, box2.mFlags);        // Should now be a parent
475         assertEquals(box1.mId, box2.mParentKey);
476 
477         assertEquals(CHILD_FLAGS, box3.mFlags);         // Should still be a child (of box2)
478         assertEquals(box2.mId, box3.mParentKey);
479     }
480 
481     /**
482      * Test changing to no parent from a parent
483      */
testChangeFromParentToNoParent()484     public void testChangeFromParentToNoParent() {
485         // Set up account and mailboxes
486         mAccount = setupTestAccount("acct1", true);
487         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
488 
489         // Initial configuration for this test:  box1 has box2, box3 is also at root.
490         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
491                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
492         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
493                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
494 
495         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
496         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
497 
498         // Confirm initial configuration as expected
499         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
500         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
501         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
502 
503         // Confirm flags and parent key(s) as expected
504         assertEquals(PARENT_FLAGS, box1.mFlags);
505         assertEquals(-1, box1.mParentKey);
506 
507         assertEquals(CHILD_FLAGS, box2.mFlags);
508         assertEquals(box1.mId, box2.mParentKey);
509 
510         // The specific test:  Remove the parent from box2 and check remaining configuration
511         ContentValues values = new ContentValues();
512         values.putNull(Mailbox.PARENT_SERVER_ID);
513         mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2.mId), values,
514                 null, null);
515         // Note: FolderSync handling of changed folder would cause parent key to be uninitialized
516         // so we do so here
517         mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2.mId), mNullParentKey,
518                 null, null);
519         simulateFolderSyncChangeHandling(accountSelector, box1 /*box2's old parent*/);
520 
521         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
522         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
523 
524         // Confirm flags and parent key(s) as expected
525         assertEquals(CHILD_FLAGS, box1.mFlags);        // Should no longer be a parent
526         assertEquals(-1, box1.mParentKey);
527 
528         assertEquals(CHILD_FLAGS, box2.mFlags);        // Should still be a child (no parent)
529         assertEquals(-1, box2.mParentKey);
530     }
531 
532     /**
533      * Test a mailbox that has no server id (Hotmail Outbox is an example of this)
534      */
testNoServerId()535     public void testNoServerId() {
536         // Set up account and mailboxes
537         mAccount = setupTestAccount("acct1", true);
538         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
539 
540         // Initial configuration for this test:  box1 has no serverId, box2 is a child of box1
541         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
542                 "box1", mAccount.mId, false, mProviderContext, Mailbox.TYPE_MAIL);
543         box1.mServerId = null;
544         box1.save(mProviderContext);
545         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
546                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_OUTBOX, box1);
547 
548         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
549         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
550 
551         // Confirm initial configuration as expected
552         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
553         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
554         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
555 
556         // Box 1 should be a child, even though it is defined as the parent of box2, because it
557         // has no serverId (presumably, this case can't happen, because a child stores the parent's
558         // serverId, but it's nice to know it's handled properly). Box 1 should have no parent.
559         assertEquals(Mailbox.NO_MAILBOX, box1.mParentKey);
560         assertEquals(CHILD_FLAGS, box1.mFlags);
561         // Box 2 should be a child with no parent (see above).  Since it's an outbox, the flags are
562         // only "holds mail".
563         assertEquals(Mailbox.NO_MAILBOX, box2.mParentKey);
564         assertEquals(Mailbox.FLAG_HOLDS_MAIL, box2.mFlags);
565     }
566 
567     /**
568      * Test changing a parent from one mailbox to another
569      */
testChangeParent()570     public void testChangeParent() {
571         // Set up account and mailboxes
572         mAccount = setupTestAccount("acct1", true);
573         String accountSelector = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
574 
575         // Initial configuration for this test:  box1 has box2, box3 is also at root.
576         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
577                 "box1", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
578         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
579                 "box2", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL);
580         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
581                 "box3", mAccount.mId, true, mProviderContext, Mailbox.TYPE_MAIL, box1);
582 
583         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
584         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
585 
586         // Confirm initial configuration as expected
587         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector);
588         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
589         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
590         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
591 
592         // Confirm flags and parent key(s) as expected
593         assertEquals(PARENT_FLAGS, box1.mFlags);
594         assertEquals(-1, box1.mParentKey);
595 
596         assertEquals(CHILD_FLAGS, box2.mFlags);
597         assertEquals(-1, box2.mParentKey);
598 
599         assertEquals(CHILD_FLAGS, box3.mFlags);
600         assertEquals(box1.mId, box3.mParentKey);
601 
602         // The specific test:  Give box 3 a new parent (box 2) and check remaining configuration
603         ContentValues values = new ContentValues();
604         values.put(Mailbox.PARENT_SERVER_ID, box2.mServerId);
605         mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box3.mId), values,
606                 null, null);
607         // Changes to old and new parent
608         simulateFolderSyncChangeHandling(accountSelector, box2 /*box3's new parent*/,
609                 box1 /*box3's old parent*/);
610 
611         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
612         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
613         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
614 
615         // Confirm flags and parent key(s) as expected
616         assertEquals(CHILD_FLAGS, box1.mFlags);        // Should no longer be a parent
617         assertEquals(-1, box1.mParentKey);
618 
619         assertEquals(PARENT_FLAGS, box2.mFlags);        // Should now be a parent
620         assertEquals(-1, box2.mParentKey);
621 
622         assertEquals(CHILD_FLAGS, box3.mFlags);         // Should still be a child (of box2)
623         assertEquals(box2.mId, box3.mParentKey);
624     }
625 
626 
627     /**
628      * Tests the proper separation of two accounts using the methodology from the previous test.
629      * This test will fail if MailboxUtilities fails to distinguish between mailboxes in different
630      * accounts that happen to have the same serverId
631      */
testChangeParentTwoAccounts()632     public void testChangeParentTwoAccounts() {
633         // Set up account and mailboxes
634         mAccount = setupTestAccount("acct1", true);
635         Account acct2 = setupTestAccount("acct2", true);
636 
637         String accountSelector1 = MailboxColumns.ACCOUNT_KEY + " IN (" + mAccount.mId + ")";
638         String accountSelector2 = MailboxColumns.ACCOUNT_KEY + " IN (" + acct2.mId + ")";
639 
640         // Box3 is in Box1
641         Mailbox box1 = EmailContentSetupUtils.setupMailbox(
642                 "box1", mAccount.mId, false, mProviderContext, Mailbox.TYPE_MAIL);
643         box1.mServerId = "1:1";
644         box1.save(mProviderContext);
645         Mailbox box2 = EmailContentSetupUtils.setupMailbox(
646                 "box2", mAccount.mId, false, mProviderContext, Mailbox.TYPE_MAIL);
647         box2.mServerId = "1:2";
648         box2.save(mProviderContext);
649         Mailbox box3 = EmailContentSetupUtils.setupMailbox(
650                 "box3", mAccount.mId, false, mProviderContext, Mailbox.TYPE_MAIL, box1);
651         box3.mServerId = "1:3";
652         box3.save(mProviderContext);
653 
654         // Box5 is in Box4; Box 6 is in Box5
655         // Note that the three serverId's are identical to those in acct1; we want to make sure
656         // that children get associated only with boxes in their own account
657         Mailbox box4 = EmailContentSetupUtils.setupMailbox(
658                 "box4", acct2.mId, false, mProviderContext, Mailbox.TYPE_MAIL, null);
659         box4.mServerId = "1:1";
660         box4.save(mProviderContext);
661         Mailbox box5 = EmailContentSetupUtils.setupMailbox(
662                 "box5", acct2.mId, false, mProviderContext, Mailbox.TYPE_MAIL, box4);
663         box5.mServerId = "1:2";
664         box5.save(mProviderContext);
665         Mailbox box6 = EmailContentSetupUtils.setupMailbox(
666                 "box6", acct2.mId, false, mProviderContext, Mailbox.TYPE_MAIL, box5);
667         box6.mServerId = "1:3";
668         box6.save(mProviderContext);
669 
670         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
671         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
672 
673         // Confirm initial configuration as expected for mAccount
674         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector1);
675         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
676         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
677         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
678 
679         // Confirm flags and parent key(s) as expected
680         assertEquals(PARENT_FLAGS, box1.mFlags);
681         assertEquals(-1, box1.mParentKey);
682 
683         assertEquals(CHILD_FLAGS, box2.mFlags);
684         assertEquals(-1, box2.mParentKey);
685 
686         assertEquals(CHILD_FLAGS, box3.mFlags);
687         assertEquals(box1.mId, box3.mParentKey);
688 
689         // Confirm initial configuration as expected for acct2
690         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector2);
691         box4 = Mailbox.restoreMailboxWithId(mProviderContext, box4.mId);
692         box5 = Mailbox.restoreMailboxWithId(mProviderContext, box5.mId);
693         box6 = Mailbox.restoreMailboxWithId(mProviderContext, box6.mId);
694 
695         // Confirm flags and parent key(s) as expected
696         assertEquals(PARENT_FLAGS, box4.mFlags);
697         assertEquals(-1, box4.mParentKey);
698 
699         assertEquals(PARENT_FLAGS, box5.mFlags);
700         assertEquals(box4.mId, box5.mParentKey);
701 
702         assertEquals(CHILD_FLAGS, box6.mFlags);
703         assertEquals(box5.mId, box6.mParentKey);
704 
705         // The specific test:  Change box1 to have a different serverId
706         ContentValues values = new ContentValues();
707         values.put(MailboxColumns.SERVER_ID, "1:4");
708         mResolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1.mId), values,
709                 null, null);
710         // Manually set parentKey to null for all mailboxes, as if an initial sync or post-upgrade
711         mResolver.update(Mailbox.CONTENT_URI, mNullParentKey, null, null);
712         // Fix up the parent keys
713         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector1);
714 
715         // Make sure that box1 reflects the change properly AND that other boxes remain correct
716         // The reason for all of the seemingly-duplicated tests is to make sure that the fixup of
717         // any account doesn't end up affecting the other account's mailboxes
718         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
719         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
720         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
721 
722         // Confirm flags and parent key(s) as expected
723         assertEquals(CHILD_FLAGS, box1.mFlags);
724         assertEquals(-1, box1.mParentKey);
725 
726         assertEquals(CHILD_FLAGS, box2.mFlags);
727         assertEquals(-1, box2.mParentKey);
728 
729         assertEquals(CHILD_FLAGS, box3.mFlags);
730         assertEquals(-1, box3.mParentKey);
731 
732         // Fix up the 2nd account now, and check that ALL boxes are correct
733         MailboxUtilities.fixupUninitializedParentKeys(mProviderContext, accountSelector2);
734 
735         box1 = Mailbox.restoreMailboxWithId(mProviderContext, box1.mId);
736         box2 = Mailbox.restoreMailboxWithId(mProviderContext, box2.mId);
737         box3 = Mailbox.restoreMailboxWithId(mProviderContext, box3.mId);
738 
739         // Confirm flags and parent key(s) as expected
740         assertEquals(CHILD_FLAGS, box1.mFlags);
741         assertEquals(-1, box1.mParentKey);
742 
743         assertEquals(CHILD_FLAGS, box2.mFlags);
744         assertEquals(-1, box2.mParentKey);
745 
746         assertEquals(CHILD_FLAGS, box3.mFlags);
747         assertEquals(-1, box3.mParentKey);
748 
749         box4 = Mailbox.restoreMailboxWithId(mProviderContext, box4.mId);
750         box5 = Mailbox.restoreMailboxWithId(mProviderContext, box5.mId);
751         box6 = Mailbox.restoreMailboxWithId(mProviderContext, box6.mId);
752 
753         assertEquals(PARENT_FLAGS, box4.mFlags);
754         assertEquals(-1, box4.mParentKey);
755 
756         assertEquals(PARENT_FLAGS, box5.mFlags);
757         assertEquals(box4.mId, box5.mParentKey);
758 
759         assertEquals(CHILD_FLAGS, box6.mFlags);
760         assertEquals(box5.mId, box6.mParentKey);
761     }
762 }
763