Home | History | Annotate | Download | only in activity
      1 /*
      2  * Copyright (C) 2010 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.email.activity;
     18 
     19 import android.content.Context;
     20 import android.database.AbstractCursor;
     21 import android.database.Cursor;
     22 import android.os.Handler;
     23 import android.test.ProviderTestCase2;
     24 import android.test.suitebuilder.annotation.SmallTest;
     25 
     26 import com.android.email.MessageListContext;
     27 import com.android.email.provider.EmailProvider;
     28 import com.android.emailcommon.provider.EmailContent;
     29 import com.android.emailcommon.utility.DelayedOperations;
     30 
     31 import junit.framework.Assert;
     32 
     33 @SmallTest
     34 public class MessageOrderManagerTest extends ProviderTestCase2<EmailProvider> {
     35 
     36     private MyCallback mCallback;
     37 
     38     @Override protected void setUp() throws Exception {
     39         super.setUp();
     40         mCallback = new MyCallback();
     41     }
     42 
     43     public MessageOrderManagerTest() {
     44         super(EmailProvider.class, EmailContent.AUTHORITY);
     45     }
     46 
     47     private static void assertCanMove(MessageOrderManager mom, boolean newer, boolean older) {
     48         Assert.assertEquals(older, mom.canMoveToOlder());
     49         Assert.assertEquals(newer, mom.canMoveToNewer());
     50     }
     51 
     52     public void testBasic() {
     53         MessageOrderManagerForTest mom = new MessageOrderManagerForTest(getContext(), 1, mCallback);
     54         mom.assertStartQueryCalledAndReset();
     55 
     56         // moveTo not called, so it returns -1
     57         assertEquals(-1, mom.getCurrentMessageId());
     58 
     59         // Task not finished, so all returns false.
     60         assertCanMove(mom, false, false);
     61         assertFalse(mom.moveToNewer());
     62         assertFalse(mom.moveToOlder());
     63 
     64         // Set current message
     65         mom.moveTo(54);
     66         assertEquals(54, mom.getCurrentMessageId());
     67 
     68         // Task still not finished, so all returns false.
     69         assertCanMove(mom, false, false);
     70         assertFalse(mom.moveToNewer());
     71         assertFalse(mom.moveToOlder());
     72 
     73         // Both callbacks shouldn't have called.
     74         mCallback.assertCallbacksCalled(false, false);
     75 
     76         // Cursor not open yet, so these are both 0.
     77         assertEquals(0, mom.getCurrentPosition());
     78         assertEquals(0, mom.getTotalMessageCount());
     79     }
     80 
     81     /**
     82      * Test with actual message list.
     83      *
     84      * In this test, {@link MessageOrderManager#moveTo} is called AFTER the cursor opens.
     85      */
     86     public void testWithList() {
     87         MessageOrderManagerForTest mom = new MessageOrderManagerForTest(getContext(), 1, mCallback);
     88         mom.assertStartQueryCalledAndReset();
     89 
     90         // Callback not called yet.
     91         mCallback.assertCallbacksCalled(false, false);
     92 
     93         // Inject mock cursor.  (Imitate async query done.)
     94         MyCursor cursor = new MyCursor(11, 22, 33, 44); // Newer to older
     95         mom.onCursorOpenDone(cursor);
     96 
     97         assertEquals(0, mom.getCurrentPosition());
     98         assertEquals(4, mom.getTotalMessageCount());
     99 
    100         // Current message id not set yet, so callback should have called yet.
    101         mCallback.assertCallbacksCalled(false, false);
    102 
    103         // Set current message id -- now onMessagesChanged() should get called.
    104         mom.moveTo(22);
    105         assertEquals(1, mom.getCurrentPosition());
    106         mCallback.assertCallbacksCalled(true, false);
    107         assertEquals(22, mom.getCurrentMessageId());
    108         assertCanMove(mom, true, true);
    109 
    110         // Move to row 1
    111         assertTrue(mom.moveToNewer());
    112         assertEquals(0, mom.getCurrentPosition());
    113         assertEquals(11, mom.getCurrentMessageId());
    114         assertCanMove(mom, false, true);
    115         mCallback.assertCallbacksCalled(true, false);
    116 
    117         // Try to move to newer, but no newer messages
    118         assertFalse(mom.moveToNewer());
    119         assertEquals(0, mom.getCurrentPosition());
    120         assertEquals(11, mom.getCurrentMessageId()); // Still row 1
    121         mCallback.assertCallbacksCalled(false, false);
    122 
    123         // Move to row 2
    124         assertTrue(mom.moveToOlder());
    125         assertEquals(1, mom.getCurrentPosition());
    126         assertEquals(22, mom.getCurrentMessageId());
    127         assertCanMove(mom, true, true);
    128         mCallback.assertCallbacksCalled(true, false);
    129 
    130         // Move to row 3
    131         assertTrue(mom.moveToOlder());
    132         assertEquals(2, mom.getCurrentPosition());
    133         assertEquals(33, mom.getCurrentMessageId());
    134         assertCanMove(mom, true, true);
    135         mCallback.assertCallbacksCalled(true, false);
    136 
    137         // Move to row 4
    138         assertTrue(mom.moveToOlder());
    139         assertEquals(3, mom.getCurrentPosition());
    140         assertEquals(44, mom.getCurrentMessageId());
    141         assertCanMove(mom, true, false);
    142         mCallback.assertCallbacksCalled(true, false);
    143 
    144         // Try to move older, but no Older messages
    145         assertFalse(mom.moveToOlder());
    146         assertEquals(3, mom.getCurrentPosition());
    147         mCallback.assertCallbacksCalled(false, false);
    148 
    149         // Move to row 3
    150         assertTrue(mom.moveToNewer());
    151         assertEquals(2, mom.getCurrentPosition());
    152         assertEquals(33, mom.getCurrentMessageId());
    153         assertCanMove(mom, true, true);
    154         mCallback.assertCallbacksCalled(true, false);
    155     }
    156 
    157     /**
    158      * Test with actual message list.
    159      *
    160      * In this test, {@link MessageOrderManager#moveTo} is called BEFORE the cursor opens.
    161      */
    162     public void testWithList2() {
    163         MessageOrderManagerForTest mom = new MessageOrderManagerForTest(getContext(), 1, mCallback);
    164         mom.assertStartQueryCalledAndReset();
    165 
    166         // Callback not called yet.
    167         mCallback.assertCallbacksCalled(false, false);
    168 
    169         mom.moveTo(22);
    170         mCallback.assertCallbacksCalled(false, false); // Cursor not open, callback not called yet.
    171         assertEquals(22, mom.getCurrentMessageId());
    172 
    173         // cursor not open yet
    174         assertEquals(0, mom.getCurrentPosition());
    175         assertEquals(0, mom.getTotalMessageCount());
    176 
    177         // Inject mock cursor.  (Imitate async query done.)
    178         MyCursor cursor = new MyCursor(11, 22, 33, 44); // Newer to older
    179         mom.onCursorOpenDone(cursor);
    180 
    181         // As soon as the cursor opens, callback gets called.
    182         mCallback.assertCallbacksCalled(true, false);
    183         assertEquals(22, mom.getCurrentMessageId());
    184 
    185         assertEquals(1, mom.getCurrentPosition());
    186         assertEquals(4, mom.getTotalMessageCount());
    187     }
    188 
    189     public void testContentChanged() {
    190         MessageOrderManagerForTest mom = new MessageOrderManagerForTest(getContext(), 1, mCallback);
    191 
    192         // Inject mock cursor.  (Imitate async query done.)
    193         MyCursor cursor = new MyCursor(11, 22, 33, 44); // Newer to older
    194         mom.onCursorOpenDone(cursor);
    195 
    196         // Move to 22
    197         mom.moveTo(22);
    198         mCallback.assertCallbacksCalled(true, false);
    199         assertEquals(22, mom.getCurrentMessageId());
    200         assertCanMove(mom, true, true);
    201 
    202         // Delete 33
    203         mom.updateMessageList(11, 22, 44);
    204 
    205         mCallback.assertCallbacksCalled(true, false);
    206         assertEquals(22, mom.getCurrentMessageId());
    207         assertCanMove(mom, true, true);
    208 
    209         // Delete 44
    210         mom.updateMessageList(11, 22);
    211 
    212         mCallback.assertCallbacksCalled(true, false);
    213         assertEquals(22, mom.getCurrentMessageId());
    214         assertCanMove(mom, true, false); // Can't move to older
    215 
    216         // Append 55
    217         mom.updateMessageList(11, 22, 55);
    218 
    219         mCallback.assertCallbacksCalled(true, false);
    220         assertEquals(22, mom.getCurrentMessageId());
    221         assertCanMove(mom, true, true);
    222 
    223         // Delete 11
    224         mom.updateMessageList(22, 55);
    225 
    226         mCallback.assertCallbacksCalled(true, false);
    227         assertEquals(22, mom.getCurrentMessageId());
    228         assertCanMove(mom, false, true);
    229 
    230         // Delete 55
    231         mom.updateMessageList(22);
    232 
    233         mCallback.assertCallbacksCalled(true, false);
    234         assertEquals(22, mom.getCurrentMessageId());
    235         assertCanMove(mom, false, false); // Can't move either way
    236 
    237         // Delete 22 -- no messages left.
    238         mom.updateMessageList();
    239         mCallback.assertCallbacksCalled(false, true);
    240 
    241         // Test for the case where list is not empty, but the current message is gone.
    242         // First, set up a list with 22 as the current message.
    243         mom.updateMessageList(11, 22, 33, 44);
    244         mom.moveTo(22);
    245         assertEquals(22, mom.getCurrentMessageId());
    246         mCallback.assertCallbacksCalled(true, false);
    247 
    248         // Then remove the current message.
    249         mom.updateMessageList(11, 33, 44);
    250         mCallback.assertCallbacksCalled(false, true);
    251     }
    252 
    253     /**
    254      * Test using the actual {@link MessageOrderManager} rather than
    255      * {@link MessageOrderManagerForTest}.
    256      */
    257     public void testWithActualClass() {
    258         // There are not many things we can test synchronously.
    259         // Just open & close just to make sure it won't crash.
    260         MessageOrderManager mom = new MessageOrderManager(
    261                 getContext(), MessageListContext.forMailbox(1, 1), new MyCallback());
    262         mom.moveTo(123);
    263         mom.close();
    264     }
    265 
    266     private static class MyCallback implements MessageOrderManager.Callback {
    267         public boolean mCalledOnMessageNotFound;
    268         public boolean mCalledOnMessagesChanged;
    269 
    270         @Override public void onMessagesChanged() {
    271             mCalledOnMessagesChanged = true;
    272         }
    273 
    274         @Override public void onMessageNotFound() {
    275             mCalledOnMessageNotFound = true;
    276         }
    277 
    278         /**
    279          * Asserts that the callbacks have/have not been called, and reset the flags.
    280          */
    281         public void assertCallbacksCalled(boolean messagesChanged, boolean messageNotFound) {
    282             assertEquals(messagesChanged, mCalledOnMessagesChanged);
    283             assertEquals(messageNotFound, mCalledOnMessageNotFound);
    284 
    285             mCalledOnMessagesChanged = false;
    286             mCalledOnMessageNotFound = false;
    287         }
    288     }
    289 
    290     /**
    291      *  "Non" delayed operation -- runs the runnable immediately
    292      */
    293     private static final class NonDelayedOperations extends DelayedOperations {
    294         public NonDelayedOperations() {
    295             super(new Handler());
    296         }
    297 
    298         @Override
    299         public void post(Runnable r) {
    300             r.run();
    301         }
    302     }
    303 
    304     /**
    305      * MessageOrderManager for test.  Overrides {@link #startQuery}
    306      */
    307     private static class MessageOrderManagerForTest extends MessageOrderManager {
    308         private Cursor mLastCursor;
    309         public boolean mStartQueryCalled;
    310 
    311         public MessageOrderManagerForTest(Context context, long mailboxId, Callback callback) {
    312             super(context, MessageListContext.forMailbox(1, mailboxId),
    313                     callback, new NonDelayedOperations());
    314         }
    315 
    316         @Override void startQuery() {
    317             // To make tests synchronous, we replace this method.
    318             mStartQueryCalled = true;
    319         }
    320 
    321         @Override /* package */ Handler getHandlerForContentObserver() {
    322             return null;
    323         }
    324 
    325         @Override void onCursorOpenDone(Cursor cursor) {
    326             super.onCursorOpenDone(cursor);
    327             mLastCursor =  cursor;
    328         }
    329 
    330         /**
    331          * Utility method to emulate data set changed.
    332          */
    333         public void updateMessageList(long... idList) {
    334             assertNotNull(mLastCursor); // Make sure a cursor is set.
    335 
    336             // Notify dataset change -- it should end up startQuery() gets called.
    337             ((MyCursor) mLastCursor).notifyChanged();
    338             assertStartQueryCalledAndReset(); // Start
    339 
    340             // Set a new cursor with a new list.
    341             onCursorOpenDone(new MyCursor(idList));
    342         }
    343 
    344         public void assertStartQueryCalledAndReset() {
    345             assertTrue(mStartQueryCalled);
    346             mStartQueryCalled = false;
    347         }
    348     }
    349 
    350     private static class MyCursor extends AbstractCursor {
    351         private final long[] mList;
    352 
    353         public MyCursor(long... idList) {
    354             mList = (idList == null) ? new long[0] : idList;
    355         }
    356 
    357         public void notifyChanged() {
    358             onChange(false);
    359         }
    360 
    361         @Override public int getColumnCount() {
    362             return 1;
    363         }
    364 
    365         @Override public int getCount() {
    366             return mList.length;
    367         }
    368 
    369         @Override public String[] getColumnNames() {
    370             return new String[] {EmailContent.RECORD_ID};
    371         }
    372 
    373         @Override public long getLong(int columnIndex) {
    374             Assert.assertEquals(EmailContent.ID_PROJECTION_COLUMN, columnIndex);
    375             return mList[mPos];
    376         }
    377 
    378         @Override public double getDouble(int column) {
    379             throw new junit.framework.AssertionFailedError();
    380         }
    381 
    382         @Override public float getFloat(int column) {
    383             throw new junit.framework.AssertionFailedError();
    384         }
    385 
    386         @Override public int getInt(int column) {
    387             throw new junit.framework.AssertionFailedError();
    388         }
    389 
    390         @Override public short getShort(int column) {
    391             throw new junit.framework.AssertionFailedError();
    392         }
    393 
    394         @Override public String getString(int column) {
    395             throw new junit.framework.AssertionFailedError();
    396         }
    397 
    398         @Override public boolean isNull(int column) {
    399             throw new junit.framework.AssertionFailedError();
    400         }
    401     }
    402 }
    403