1fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank/* 2fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * Copyright (C) 2010 The Android Open Source Project 3fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * 4fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 5fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * you may not use this file except in compliance with the License. 6fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * You may obtain a copy of the License at 7fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * 8fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * http://www.apache.org/licenses/LICENSE-2.0 9fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * 10fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * Unless required by applicable law or agreed to in writing, software 11fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * distributed under the License is distributed on an "AS IS" BASIS, 12fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * See the License for the specific language governing permissions and 14fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * limitations under the License. 15fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank */ 16fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 17fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankpackage com.android.email.provider; 18fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 19fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport com.android.email.provider.ContentCache.CacheToken; 20fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport com.android.email.provider.ContentCache.CachedCursor; 21fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport com.android.email.provider.ContentCache.TokenList; 22f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport com.android.emailcommon.provider.Account; 2331d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.provider.EmailContent; 2453ea83ebf91f820692e8fa8e781f5cc982dd94dbBen Komaloimport com.android.emailcommon.provider.Mailbox; 25fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 26fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.content.ContentResolver; 27fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.content.ContentUris; 28fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.content.Context; 29fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.database.Cursor; 30fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.database.CursorWrapper; 31fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.database.MatrixCursor; 32fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.net.Uri; 33fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankimport android.test.ProviderTestCase2; 34fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 35fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank/** 36fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * Tests of ContentCache 37fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * 38fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * You can run this entire test case with: 39fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank * runtest -c com.android.email.provider.ContentCacheTests email 40fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank */ 41fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blankpublic class ContentCacheTests extends ProviderTestCase2<EmailProvider> { 42fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 43fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank EmailProvider mProvider; 44fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Context mMockContext; 45fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 46fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank public ContentCacheTests() { 4731d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blank super(EmailProvider.class, EmailContent.AUTHORITY); 48fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 49fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 50fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank @Override 51fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank public void setUp() throws Exception { 52fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank super.setUp(); 53fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank mMockContext = getMockContext(); 54fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 55fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 56fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank @Override 57fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank public void tearDown() throws Exception { 58fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank super.tearDown(); 59fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 60fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 61fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank public void testCounterMap() { 62fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank ContentCache.CounterMap<String> map = new ContentCache.CounterMap<String>(4); 63fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Make sure we can find added items 64fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank map.add("1"); 65fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(map.contains("1")); 66fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank map.add("2"); 67fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank map.add("2"); 68fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Make sure we can remove once for each add 692199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler map.subtract("2"); 70fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(map.contains("2")); 712199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler map.subtract("2"); 72fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Make sure that over-removing throws an exception 73fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank try { 742199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler map.subtract("2"); 75fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank fail("Removing a third time should throw an exception"); 76fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } catch (IllegalStateException e) { 77fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 78fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank try { 792199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler map.subtract("3"); 80fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank fail("Removing object never added should throw an exception"); 81fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } catch (IllegalStateException e) { 82fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 83fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // There should only be one item in the map ("1") 84fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(1, map.size()); 85fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(map.contains("1")); 86fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 87fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 88fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank public void testTokenList() { 89fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank TokenList list = new TokenList("Name"); 90fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 91fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Add two tokens for "1" 92fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CacheToken token1a = list.add("1"); 93fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(token1a.isValid()); 94fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals("1", token1a.getId()); 95fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(1, list.size()); 96fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CacheToken token1b = list.add("1"); 97fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(token1b.isValid()); 98fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals("1", token1b.getId()); 99fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(token1a.equals(token1b)); 100fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(2, list.size()); 101fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 102fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Add a token for "2" 103fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CacheToken token2 = list.add("2"); 104fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(token1a.equals(token2)); 105fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(3, list.size()); 106fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 107fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Invalidate "1"; there should be two tokens invalidated 108fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(2, list.invalidateTokens("1")); 109fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(token1a.isValid()); 110fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(token1b.isValid()); 111fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Token2 should still be valid 112fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(token2.isValid()); 113fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Only token2 should be in the list now (invalidation removes tokens) 114fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(1, list.size()); 115fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(token2, list.get(0)); 116fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 117fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Add 3 tokens for "3" 118fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CacheToken token3a = list.add("3"); 119fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CacheToken token3b = list.add("3"); 120fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CacheToken token3c = list.add("3"); 121fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Remove two of them 122fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(list.remove(token3a)); 123fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(list.remove(token3b)); 124fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Removing tokens doesn't invalidate them 125fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(token3a.isValid()); 126fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(token3b.isValid()); 127fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(token3c.isValid()); 128fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // There should be two items left "3" and "2" 129fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(2, list.size()); 130fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 131fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 132fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank public void testCachedCursors() { 133fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank final ContentResolver resolver = mMockContext.getContentResolver(); 134fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank final Context context = mMockContext; 135fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 136fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Create account and two mailboxes 137fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Account acct = ProviderTestUtils.setupAccount("account", true, context); 138fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 139fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Mailbox box = ProviderTestUtils.setupMailbox("box2", acct.mId, true, context); 140fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 141fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // We need to test with a query that only returns one row (others can't be put in a 142fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // CachedCursor) 143fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box.mId); 144fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Cursor cursor = 145fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank resolver.query(uri, Mailbox.CONTENT_PROJECTION, null, null, null); 146fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // ContentResolver gives us back a wrapper 147fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(cursor instanceof CursorWrapper); 148fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // The wrappedCursor should be a CachedCursor 149fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Cursor wrappedCursor = ((CursorWrapper)cursor).getWrappedCursor(); 150fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(wrappedCursor instanceof CachedCursor); 151fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CachedCursor cachedCursor = (CachedCursor)wrappedCursor; 152fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // The cursor wrapped in cachedCursor is the underlying cursor 153fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Cursor activeCursor = cachedCursor.getWrappedCursor(); 154fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 155fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // The cursor should be in active cursors 1562199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler int activeCount = ContentCache.sActiveCursors.getCount(activeCursor); 1572199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler assertEquals(1, activeCount); 158fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 159fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Some basic functionality that shouldn't throw exceptions and should otherwise act as the 160fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // underlying cursor would 161fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank String[] columnNames = cursor.getColumnNames(); 162fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(Mailbox.CONTENT_PROJECTION.length, columnNames.length); 163fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank for (int i = 0; i < Mailbox.CONTENT_PROJECTION.length; i++) { 164fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(Mailbox.CONTENT_PROJECTION[i], columnNames[i]); 165fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 166fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 167fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(1, cursor.getCount()); 168fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cursor.moveToNext(); 169fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(0, cursor.getPosition()); 170fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cursor.moveToPosition(0); 171fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(0, cursor.getPosition()); 17268dc380d62b29b4b6733bc1b20e44b8931c1d341Marc Blank assertFalse(cursor.moveToPosition(1)); 173fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 174fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cursor.close(); 175fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // We've closed the cached cursor; make sure 176fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(cachedCursor.isClosed()); 177fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // The underlying cursor shouldn't be closed because it's in a cache (we'll test 178fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // that in testContentCache) 179fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(activeCursor.isClosed()); 180fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Our cursor should no longer be in the active cursors map 1812199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler assertFalse(ContentCache.sActiveCursors.contains(activeCursor)); 1822199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler 1832199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler // TODO - change the code or the test to enforce the assertion that a cached cursor 1842199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler // should have only zero or one rows. We cannot test this in the constructor, however, 1852199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler // due to potential for deadlock. 1862199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// // Make sure that we won't accept cursors with multiple rows 1872199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// cursor = resolver.query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION, null, null, null); 1882199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// try { 1892199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// cursor = new CachedCursor(cursor, null, "Foo"); 1902199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// fail("Mustn't accept cursor with more than one row"); 1912199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// } catch (IllegalArgumentException e) { 1922199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// // Correct 1932199c7ddf5d497e816bef1a1b7473098369a1bdfAndy Stadler// } 194fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 195fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 196fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank private static final String[] SIMPLE_PROJECTION = new String[] {"Foo"}; 197fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank private static final Object[] SIMPLE_ROW = new Object[] {"Bar"}; 198fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank private Cursor getOneRowCursor() { 199fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank MatrixCursor cursor = new MatrixCursor(SIMPLE_PROJECTION, 1); 200fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cursor.addRow(SIMPLE_ROW); 201fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank return cursor; 202fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 203fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 204fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank public void testContentCacheRemoveEldestEntry() { 205fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Create a cache of size 2 206fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank ContentCache cache = new ContentCache("Name", SIMPLE_PROJECTION, 2); 207fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Random cursor; what's in it doesn't matter 208fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Cursor cursor1 = getOneRowCursor(); 209fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Get a token for arbitrary object named "1" 210fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank CacheToken token = cache.getCacheToken("1"); 211fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Put the cursor in the cache 212fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cache.putCursor(cursor1, "1", SIMPLE_PROJECTION, token); 213fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(1, cache.size()); 214fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 215fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Add another random cursor; what's in it doesn't matter 216fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Cursor cursor2 = getOneRowCursor(); 217fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Get a token for arbitrary object named "2" 218fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank token = cache.getCacheToken("2"); 219fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Put the cursor in the cache 220fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cache.putCursor(cursor1, "2", SIMPLE_PROJECTION, token); 221fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(2, cache.size()); 222fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 223fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // We should be able to find both now in the cache 224fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Cursor cachedCursor = cache.getCachedCursor("1", SIMPLE_PROJECTION); 225fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertNotNull(cachedCursor); 226fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(cachedCursor instanceof CachedCursor); 227fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cachedCursor = cache.getCachedCursor("2", SIMPLE_PROJECTION); 228fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertNotNull(cachedCursor); 229fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(cachedCursor instanceof CachedCursor); 230fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 231fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Both cursors should be open 232fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(cursor1.isClosed()); 233fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(cursor2.isClosed()); 234fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 235fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Add another random cursor; what's in it doesn't matter 236fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank Cursor cursor3 = getOneRowCursor(); 237fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Get a token for arbitrary object named "3" 238fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank token = cache.getCacheToken("3"); 239fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Put the cursor in the cache 240fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cache.putCursor(cursor1, "3", SIMPLE_PROJECTION, token); 241fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // We should never have more than 2 entries in the cache 242fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertEquals(2, cache.size()); 243fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 244fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // The first cursor we added should no longer be in the cache (it's the eldest) 245fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cachedCursor = cache.getCachedCursor("1", SIMPLE_PROJECTION); 246fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertNull(cachedCursor); 247fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // The cursors for 2 and 3 should be cached 248fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cachedCursor = cache.getCachedCursor("2", SIMPLE_PROJECTION); 249fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertNotNull(cachedCursor); 250fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(cachedCursor instanceof CachedCursor); 251fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank cachedCursor = cache.getCachedCursor("3", SIMPLE_PROJECTION); 252fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertNotNull(cachedCursor); 253fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertTrue(cachedCursor instanceof CachedCursor); 254fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank 255fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank // Even cursor1 should be open, since all cached cursors are in mActiveCursors until closed 256fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(cursor1.isClosed()); 257fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(cursor2.isClosed()); 258fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank assertFalse(cursor3.isClosed()); 259fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank } 2603aee641aab491a3da53364aafb9074ae69dd2212Jesse Wilson 261c159d32be05ee744f3726579d9cd8eed39545137Marc Blank public void testCloseCachedCursor() { 262c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // Create a cache of size 2 263c159d32be05ee744f3726579d9cd8eed39545137Marc Blank ContentCache cache = new ContentCache("Name", SIMPLE_PROJECTION, 2); 264c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // Random cursor; what's in it doesn't matter 265c159d32be05ee744f3726579d9cd8eed39545137Marc Blank Cursor underlyingCursor = getOneRowCursor(); 266c159d32be05ee744f3726579d9cd8eed39545137Marc Blank Cursor cachedCursor1 = new CachedCursor(underlyingCursor, cache, "1"); 267c159d32be05ee744f3726579d9cd8eed39545137Marc Blank Cursor cachedCursor2 = new CachedCursor(underlyingCursor, cache, "1"); 268c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertEquals(2, ContentCache.sActiveCursors.getCount(underlyingCursor)); 269c159d32be05ee744f3726579d9cd8eed39545137Marc Blank cachedCursor1.close(); 270c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertTrue(cachedCursor1.isClosed()); 271c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // Underlying cursor should be open (still one cached cursor open) 272c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertFalse(underlyingCursor.isClosed()); 273c159d32be05ee744f3726579d9cd8eed39545137Marc Blank cachedCursor2.close(); 274c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertTrue(cachedCursor2.isClosed()); 275c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertEquals(0, ContentCache.sActiveCursors.getCount(underlyingCursor)); 276c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // Underlying cursor should be closed (no cached cursors open) 277c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertTrue(underlyingCursor.isClosed()); 2783aee641aab491a3da53364aafb9074ae69dd2212Jesse Wilson 279c159d32be05ee744f3726579d9cd8eed39545137Marc Blank underlyingCursor = getOneRowCursor(); 2803aee641aab491a3da53364aafb9074ae69dd2212Jesse Wilson cachedCursor1 = cache.putCursor( 2813aee641aab491a3da53364aafb9074ae69dd2212Jesse Wilson underlyingCursor, "2", SIMPLE_PROJECTION, cache.getCacheToken("2")); 282c159d32be05ee744f3726579d9cd8eed39545137Marc Blank cachedCursor2 = new CachedCursor(underlyingCursor, cache, "2"); 283c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertEquals(2, ContentCache.sActiveCursors.getCount(underlyingCursor)); 284c159d32be05ee744f3726579d9cd8eed39545137Marc Blank cachedCursor1.close(); 285c159d32be05ee744f3726579d9cd8eed39545137Marc Blank cachedCursor2.close(); 286c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertEquals(0, ContentCache.sActiveCursors.getCount(underlyingCursor)); 287c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // Underlying cursor should still be open; it's in the cache 288c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertFalse(underlyingCursor.isClosed()); 289c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // Cache a new cursor 290c159d32be05ee744f3726579d9cd8eed39545137Marc Blank cachedCursor2 = new CachedCursor(underlyingCursor, cache, "2"); 291c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertEquals(1, ContentCache.sActiveCursors.getCount(underlyingCursor)); 292c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // Remove "2" from the cache and close the cursor 2933aee641aab491a3da53364aafb9074ae69dd2212Jesse Wilson cache.invalidate(); 294c159d32be05ee744f3726579d9cd8eed39545137Marc Blank cachedCursor2.close(); 295c159d32be05ee744f3726579d9cd8eed39545137Marc Blank // The underlying cursor should now be closed (not in the cache and no cached cursors) 296c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertEquals(0, ContentCache.sActiveCursors.getCount(underlyingCursor)); 297c159d32be05ee744f3726579d9cd8eed39545137Marc Blank assertTrue(underlyingCursor.isClosed()); 298c159d32be05ee744f3726579d9cd8eed39545137Marc Blank } 299fab77f147f85766d2f75d8aece0aaa4ffb3838e8Marc Blank} 300