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