PageRenderTime 142ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/src/com/android/email/provider/ContentCacheTests.java

https://gitlab.com/Atomic-ROM/packages_apps_Email
Java | 302 lines | 188 code | 32 blank | 82 comment | 1 complexity | 6ee5d879bacafb7885d5a86ee0742824 MD5 | raw file
  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. package com.android.email.provider;
  17. import android.content.ContentResolver;
  18. import android.content.ContentUris;
  19. import android.content.Context;
  20. import android.database.Cursor;
  21. import android.database.CursorWrapper;
  22. import android.database.MatrixCursor;
  23. import android.net.Uri;
  24. import android.test.ProviderTestCase2;
  25. import android.test.suitebuilder.annotation.Suppress;
  26. import com.android.email.provider.ContentCache.CacheToken;
  27. import com.android.email.provider.ContentCache.CachedCursor;
  28. import com.android.email.provider.ContentCache.TokenList;
  29. import com.android.emailcommon.provider.Account;
  30. import com.android.emailcommon.provider.EmailContent;
  31. import com.android.emailcommon.provider.Mailbox;
  32. import com.android.mail.utils.MatrixCursorWithCachedColumns;
  33. /**
  34. * Tests of ContentCache
  35. *
  36. * You can run this entire test case with:
  37. * runtest -c com.android.email.provider.ContentCacheTests email
  38. */
  39. @Suppress
  40. public class ContentCacheTests extends ProviderTestCase2<EmailProvider> {
  41. EmailProvider mProvider;
  42. Context mMockContext;
  43. public ContentCacheTests() {
  44. super(EmailProvider.class, EmailContent.AUTHORITY);
  45. }
  46. @Override
  47. public void setUp() throws Exception {
  48. super.setUp();
  49. mMockContext = getMockContext();
  50. }
  51. @Override
  52. public void tearDown() throws Exception {
  53. super.tearDown();
  54. }
  55. public void testCounterMap() {
  56. ContentCache.CounterMap<String> map = new ContentCache.CounterMap<String>(4);
  57. // Make sure we can find added items
  58. map.add("1");
  59. assertTrue(map.contains("1"));
  60. map.add("2");
  61. map.add("2");
  62. // Make sure we can remove once for each add
  63. map.subtract("2");
  64. assertTrue(map.contains("2"));
  65. map.subtract("2");
  66. // Make sure that over-removing throws an exception
  67. try {
  68. map.subtract("2");
  69. fail("Removing a third time should throw an exception");
  70. } catch (IllegalStateException e) {
  71. }
  72. try {
  73. map.subtract("3");
  74. fail("Removing object never added should throw an exception");
  75. } catch (IllegalStateException e) {
  76. }
  77. // There should only be one item in the map ("1")
  78. assertEquals(1, map.size());
  79. assertTrue(map.contains("1"));
  80. }
  81. public void testTokenList() {
  82. TokenList list = new TokenList("Name");
  83. // Add two tokens for "1"
  84. CacheToken token1a = list.add("1");
  85. assertTrue(token1a.isValid());
  86. assertEquals("1", token1a.getId());
  87. assertEquals(1, list.size());
  88. CacheToken token1b = list.add("1");
  89. assertTrue(token1b.isValid());
  90. assertEquals("1", token1b.getId());
  91. assertTrue(token1a.equals(token1b));
  92. assertEquals(2, list.size());
  93. // Add a token for "2"
  94. CacheToken token2 = list.add("2");
  95. assertFalse(token1a.equals(token2));
  96. assertEquals(3, list.size());
  97. // Invalidate "1"; there should be two tokens invalidated
  98. assertEquals(2, list.invalidateTokens("1"));
  99. assertFalse(token1a.isValid());
  100. assertFalse(token1b.isValid());
  101. // Token2 should still be valid
  102. assertTrue(token2.isValid());
  103. // Only token2 should be in the list now (invalidation removes tokens)
  104. assertEquals(1, list.size());
  105. assertEquals(token2, list.get(0));
  106. // Add 3 tokens for "3"
  107. CacheToken token3a = list.add("3");
  108. CacheToken token3b = list.add("3");
  109. CacheToken token3c = list.add("3");
  110. // Remove two of them
  111. assertTrue(list.remove(token3a));
  112. assertTrue(list.remove(token3b));
  113. // Removing tokens doesn't invalidate them
  114. assertTrue(token3a.isValid());
  115. assertTrue(token3b.isValid());
  116. assertTrue(token3c.isValid());
  117. // There should be two items left "3" and "2"
  118. assertEquals(2, list.size());
  119. }
  120. public void testCachedCursors() {
  121. final ContentResolver resolver = mMockContext.getContentResolver();
  122. final Context context = mMockContext;
  123. // Create account and two mailboxes
  124. Account acct = ProviderTestUtils.setupAccount("account", true, context);
  125. ProviderTestUtils.setupMailbox("box1", acct.mId, true, context);
  126. Mailbox box = ProviderTestUtils.setupMailbox("box2", acct.mId, true, context);
  127. // We need to test with a query that only returns one row (others can't be put in a
  128. // CachedCursor)
  129. Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box.mId);
  130. Cursor cursor =
  131. resolver.query(uri, Mailbox.CONTENT_PROJECTION, null, null, null);
  132. // ContentResolver gives us back a wrapper
  133. assertTrue(cursor instanceof CursorWrapper);
  134. // The wrappedCursor should be a CachedCursor
  135. Cursor wrappedCursor = ((CursorWrapper)cursor).getWrappedCursor();
  136. assertTrue(wrappedCursor instanceof CachedCursor);
  137. CachedCursor cachedCursor = (CachedCursor)wrappedCursor;
  138. // The cursor wrapped in cachedCursor is the underlying cursor
  139. Cursor activeCursor = cachedCursor.getWrappedCursor();
  140. // The cursor should be in active cursors
  141. int activeCount = ContentCache.sActiveCursors.getCount(activeCursor);
  142. assertEquals(1, activeCount);
  143. // Some basic functionality that shouldn't throw exceptions and should otherwise act as the
  144. // underlying cursor would
  145. String[] columnNames = cursor.getColumnNames();
  146. assertEquals(Mailbox.CONTENT_PROJECTION.length, columnNames.length);
  147. for (int i = 0; i < Mailbox.CONTENT_PROJECTION.length; i++) {
  148. assertEquals(Mailbox.CONTENT_PROJECTION[i], columnNames[i]);
  149. }
  150. assertEquals(1, cursor.getCount());
  151. cursor.moveToNext();
  152. assertEquals(0, cursor.getPosition());
  153. cursor.moveToPosition(0);
  154. assertEquals(0, cursor.getPosition());
  155. assertFalse(cursor.moveToPosition(1));
  156. cursor.close();
  157. // We've closed the cached cursor; make sure
  158. assertTrue(cachedCursor.isClosed());
  159. // The underlying cursor shouldn't be closed because it's in a cache (we'll test
  160. // that in testContentCache)
  161. assertFalse(activeCursor.isClosed());
  162. // Our cursor should no longer be in the active cursors map
  163. assertFalse(ContentCache.sActiveCursors.contains(activeCursor));
  164. // TODO - change the code or the test to enforce the assertion that a cached cursor
  165. // should have only zero or one rows. We cannot test this in the constructor, however,
  166. // due to potential for deadlock.
  167. // // Make sure that we won't accept cursors with multiple rows
  168. // cursor = resolver.query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION, null, null, null);
  169. // try {
  170. // cursor = new CachedCursor(cursor, null, "Foo");
  171. // fail("Mustn't accept cursor with more than one row");
  172. // } catch (IllegalArgumentException e) {
  173. // // Correct
  174. // }
  175. }
  176. private static final String[] SIMPLE_PROJECTION = new String[] {"Foo"};
  177. private static final Object[] SIMPLE_ROW = new Object[] {"Bar"};
  178. private Cursor getOneRowCursor() {
  179. MatrixCursor cursor = new MatrixCursorWithCachedColumns(SIMPLE_PROJECTION, 1);
  180. cursor.addRow(SIMPLE_ROW);
  181. return cursor;
  182. }
  183. public void testContentCacheRemoveEldestEntry() {
  184. // Create a cache of size 2
  185. ContentCache cache = new ContentCache("Name", SIMPLE_PROJECTION, 2);
  186. // Random cursor; what's in it doesn't matter
  187. Cursor cursor1 = getOneRowCursor();
  188. // Get a token for arbitrary object named "1"
  189. CacheToken token = cache.getCacheToken("1");
  190. // Put the cursor in the cache
  191. cache.putCursor(cursor1, "1", SIMPLE_PROJECTION, token);
  192. assertEquals(1, cache.size());
  193. // Add another random cursor; what's in it doesn't matter
  194. Cursor cursor2 = getOneRowCursor();
  195. // Get a token for arbitrary object named "2"
  196. token = cache.getCacheToken("2");
  197. // Put the cursor in the cache
  198. cache.putCursor(cursor1, "2", SIMPLE_PROJECTION, token);
  199. assertEquals(2, cache.size());
  200. // We should be able to find both now in the cache
  201. Cursor cachedCursor = cache.getCachedCursor("1", SIMPLE_PROJECTION);
  202. assertNotNull(cachedCursor);
  203. assertTrue(cachedCursor instanceof CachedCursor);
  204. cachedCursor = cache.getCachedCursor("2", SIMPLE_PROJECTION);
  205. assertNotNull(cachedCursor);
  206. assertTrue(cachedCursor instanceof CachedCursor);
  207. // Both cursors should be open
  208. assertFalse(cursor1.isClosed());
  209. assertFalse(cursor2.isClosed());
  210. // Add another random cursor; what's in it doesn't matter
  211. Cursor cursor3 = getOneRowCursor();
  212. // Get a token for arbitrary object named "3"
  213. token = cache.getCacheToken("3");
  214. // Put the cursor in the cache
  215. cache.putCursor(cursor1, "3", SIMPLE_PROJECTION, token);
  216. // We should never have more than 2 entries in the cache
  217. assertEquals(2, cache.size());
  218. // The first cursor we added should no longer be in the cache (it's the eldest)
  219. cachedCursor = cache.getCachedCursor("1", SIMPLE_PROJECTION);
  220. assertNull(cachedCursor);
  221. // The cursors for 2 and 3 should be cached
  222. cachedCursor = cache.getCachedCursor("2", SIMPLE_PROJECTION);
  223. assertNotNull(cachedCursor);
  224. assertTrue(cachedCursor instanceof CachedCursor);
  225. cachedCursor = cache.getCachedCursor("3", SIMPLE_PROJECTION);
  226. assertNotNull(cachedCursor);
  227. assertTrue(cachedCursor instanceof CachedCursor);
  228. // Even cursor1 should be open, since all cached cursors are in mActiveCursors until closed
  229. assertFalse(cursor1.isClosed());
  230. assertFalse(cursor2.isClosed());
  231. assertFalse(cursor3.isClosed());
  232. }
  233. public void testCloseCachedCursor() {
  234. // Create a cache of size 2
  235. ContentCache cache = new ContentCache("Name", SIMPLE_PROJECTION, 2);
  236. // Random cursor; what's in it doesn't matter
  237. Cursor underlyingCursor = getOneRowCursor();
  238. Cursor cachedCursor1 = new CachedCursor(underlyingCursor, cache, "1");
  239. Cursor cachedCursor2 = new CachedCursor(underlyingCursor, cache, "1");
  240. assertEquals(2, ContentCache.sActiveCursors.getCount(underlyingCursor));
  241. cachedCursor1.close();
  242. assertTrue(cachedCursor1.isClosed());
  243. // Underlying cursor should be open (still one cached cursor open)
  244. assertFalse(underlyingCursor.isClosed());
  245. cachedCursor2.close();
  246. assertTrue(cachedCursor2.isClosed());
  247. assertEquals(0, ContentCache.sActiveCursors.getCount(underlyingCursor));
  248. // Underlying cursor should be closed (no cached cursors open)
  249. assertTrue(underlyingCursor.isClosed());
  250. underlyingCursor = getOneRowCursor();
  251. cachedCursor1 = cache.putCursor(
  252. underlyingCursor, "2", SIMPLE_PROJECTION, cache.getCacheToken("2"));
  253. cachedCursor2 = new CachedCursor(underlyingCursor, cache, "2");
  254. assertEquals(2, ContentCache.sActiveCursors.getCount(underlyingCursor));
  255. cachedCursor1.close();
  256. cachedCursor2.close();
  257. assertEquals(0, ContentCache.sActiveCursors.getCount(underlyingCursor));
  258. // Underlying cursor should still be open; it's in the cache
  259. assertFalse(underlyingCursor.isClosed());
  260. // Cache a new cursor
  261. cachedCursor2 = new CachedCursor(underlyingCursor, cache, "2");
  262. assertEquals(1, ContentCache.sActiveCursors.getCount(underlyingCursor));
  263. // Remove "2" from the cache and close the cursor
  264. cache.invalidate();
  265. cachedCursor2.close();
  266. // The underlying cursor should now be closed (not in the cache and no cached cursors)
  267. assertEquals(0, ContentCache.sActiveCursors.getCount(underlyingCursor));
  268. assertTrue(underlyingCursor.isClosed());
  269. }
  270. }