Home | History | Annotate | Download | only in provider
      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
     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
     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 
     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 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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