/tests/tests/content/src/android/content/cts/ContentQueryMapTest.java

https://github.com/mkedwards/android_cts · Java · 431 lines · 334 code · 57 blank · 40 comment · 6 complexity · bf44d8557d82d615c9b86a8b84d46b84 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * 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, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package android.content.cts;
  17. import dalvik.annotation.TestLevel;
  18. import dalvik.annotation.TestTargetClass;
  19. import dalvik.annotation.TestTargetNew;
  20. import dalvik.annotation.TestTargets;
  21. import dalvik.annotation.ToBeFixed;
  22. import android.content.ContentQueryMap;
  23. import android.content.ContentResolver;
  24. import android.content.ContentValues;
  25. import android.database.Cursor;
  26. import android.os.Handler;
  27. import android.os.HandlerThread;
  28. import android.os.Looper;
  29. import android.test.AndroidTestCase;
  30. import java.util.Map;
  31. import java.util.Observable;
  32. import java.util.Observer;
  33. /**
  34. * Test {@link ContentQueryMap}.
  35. */
  36. @TestTargetClass(ContentQueryMap.class)
  37. public class ContentQueryMapTest extends AndroidTestCase {
  38. private static final int TEST_TIME_OUT = 5000;
  39. private static final String NAME0 = "name0";
  40. private static final String VALUE0 = "value0";
  41. private static final String NAME1 = "name1";
  42. private static final String VALUE1 = "value1";
  43. private static final String NAME2 = "name2";
  44. private static final String VALUE2 = "value2";
  45. private static final String NAME3 = "name3";
  46. private static final String VALUE3 = "value3";
  47. private static final String[] PROJECTIONS = new String[] {
  48. DummyProvider.NAME, DummyProvider.VALUE};
  49. private static final int ORIGINAL_ROW_COUNT = 2;
  50. private ContentResolver mResolver;
  51. private Cursor mCursor;
  52. private ContentQueryMap mContentQueryMap;
  53. @Override
  54. protected void setUp() throws Exception {
  55. super.setUp();
  56. mResolver = mContext.getContentResolver();
  57. ContentValues values0 = new ContentValues();
  58. values0.put(DummyProvider.NAME, NAME0);
  59. values0.put(DummyProvider.VALUE, VALUE0);
  60. mResolver.insert(DummyProvider.CONTENT_URI, values0);
  61. ContentValues values1 = new ContentValues();
  62. values1.put(DummyProvider.NAME, NAME1);
  63. values1.put(DummyProvider.VALUE, VALUE1);
  64. mResolver.insert(DummyProvider.CONTENT_URI, values1);
  65. mCursor = mResolver.query(DummyProvider.CONTENT_URI, PROJECTIONS, null, null, null);
  66. assertNotNull(mCursor);
  67. }
  68. @Override
  69. protected void tearDown() throws Exception {
  70. if (mContentQueryMap != null) {
  71. mContentQueryMap.close();
  72. mContentQueryMap = null;
  73. }
  74. if (mCursor != null) {
  75. mCursor.close();
  76. mCursor = null;
  77. }
  78. mResolver.delete(DummyProvider.CONTENT_URI, null, null);
  79. super.tearDown();
  80. }
  81. @TestTargetNew(
  82. level = TestLevel.COMPLETE,
  83. method = "ContentQueryMap",
  84. args = {android.database.Cursor.class, java.lang.String.class, boolean.class,
  85. android.os.Handler.class}
  86. )
  87. @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of "
  88. + "constructor when param cursor or columnNameOfKey is null")
  89. public void testConstructor() {
  90. new ContentQueryMap(mCursor, DummyProvider.NAME, true, null);
  91. new ContentQueryMap(mCursor, DummyProvider.VALUE, false, new Handler());
  92. try {
  93. new ContentQueryMap(mCursor, null, false, new Handler());
  94. fail("Should throw NullPointerException if param columnNameOfKey is null");
  95. } catch (NullPointerException e) {
  96. }
  97. try {
  98. new ContentQueryMap(null, DummyProvider.NAME, false, new Handler());
  99. fail("Should throw NullPointerException if param cursor is null");
  100. } catch (NullPointerException e) {
  101. }
  102. }
  103. @TestTargets({
  104. @TestTargetNew(
  105. level = TestLevel.COMPLETE,
  106. method = "getRows",
  107. args = {}
  108. ),
  109. @TestTargetNew(
  110. level = TestLevel.COMPLETE,
  111. method = "close",
  112. args = {}
  113. )
  114. })
  115. public void testGetRows() {
  116. // handler can be null
  117. mContentQueryMap = new ContentQueryMap(mCursor, DummyProvider.NAME, true, null);
  118. Map<String, ContentValues> rows = mContentQueryMap.getRows();
  119. assertEquals(ORIGINAL_ROW_COUNT, rows.size());
  120. assertTrue(rows.containsKey(NAME0));
  121. assertEquals(VALUE0, rows.get(NAME0).getAsString(DummyProvider.VALUE));
  122. assertTrue(rows.containsKey(NAME1));
  123. assertEquals(VALUE1, rows.get(NAME1).getAsString(DummyProvider.VALUE));
  124. mContentQueryMap.close();
  125. // the mCursor has been close
  126. mContentQueryMap = new ContentQueryMap(mCursor, DummyProvider.NAME, false, new Handler());
  127. rows = mContentQueryMap.getRows();
  128. assertFalse(rows.containsKey(NAME0));
  129. mContentQueryMap.requery();
  130. rows = mContentQueryMap.getRows();
  131. assertFalse(rows.containsKey(NAME0));
  132. }
  133. @TestTargets({
  134. @TestTargetNew(
  135. level = TestLevel.COMPLETE,
  136. method = "requery",
  137. args = {}
  138. ),
  139. @TestTargetNew(
  140. level = TestLevel.COMPLETE,
  141. method = "getValues",
  142. args = {java.lang.String.class}
  143. )
  144. })
  145. public void testRequery() {
  146. // Disable the keepUpdated to make sure requery() will not be called
  147. // from somewhere else
  148. mContentQueryMap = new ContentQueryMap(mCursor, DummyProvider.NAME, false, null);
  149. ContentValues contentValues = mContentQueryMap.getValues(NAME0);
  150. assertNotNull(contentValues);
  151. assertEquals(VALUE0, contentValues.getAsString(DummyProvider.VALUE));
  152. contentValues = mContentQueryMap.getValues(NAME1);
  153. assertNotNull(contentValues);
  154. assertEquals(VALUE1, contentValues.getAsString(DummyProvider.VALUE));
  155. contentValues = mContentQueryMap.getValues(NAME2);
  156. assertNull(contentValues);
  157. // update NAME0 and VALUE0
  158. ContentValues values = new ContentValues();
  159. values.put(DummyProvider.NAME, NAME2);
  160. values.put(DummyProvider.VALUE, VALUE2);
  161. mResolver.update(DummyProvider.CONTENT_URI, values,
  162. DummyProvider.NAME + " = '" + NAME0 + "'", null);
  163. mContentQueryMap.requery();
  164. contentValues = mContentQueryMap.getValues(NAME0);
  165. assertNull(contentValues);
  166. contentValues = mContentQueryMap.getValues(NAME1);
  167. assertNotNull(contentValues);
  168. assertEquals(VALUE1, contentValues.getAsString(DummyProvider.VALUE));
  169. contentValues = mContentQueryMap.getValues(NAME2);
  170. assertNotNull(contentValues);
  171. assertEquals(VALUE2, contentValues.getAsString(DummyProvider.VALUE));
  172. }
  173. @TestTargets({
  174. @TestTargetNew(
  175. level = TestLevel.COMPLETE,
  176. method = "setKeepUpdated",
  177. args = {boolean.class}
  178. ),
  179. @TestTargetNew(
  180. level = TestLevel.COMPLETE,
  181. method = "getValues",
  182. args = {java.lang.String.class}
  183. ),
  184. @TestTargetNew(
  185. level = TestLevel.COMPLETE,
  186. method = "requery",
  187. args = {}
  188. )
  189. })
  190. public void testSetKeepUpdated() throws InterruptedException {
  191. MockObserver observer = new MockObserver();
  192. // keepUpdated is false
  193. mContentQueryMap = new ContentQueryMap(mCursor, DummyProvider.NAME, false, null);
  194. mContentQueryMap.addObserver(observer);
  195. assertFalse(observer.hadUpdated(0));
  196. ContentValues contentValues = mContentQueryMap.getValues(NAME0);
  197. assertNotNull(contentValues);
  198. assertEquals(VALUE0, contentValues.getAsString(DummyProvider.VALUE));
  199. contentValues = mContentQueryMap.getValues(NAME2);
  200. assertNull(contentValues);
  201. // update NAME0 and VALUE0
  202. ContentValues values = new ContentValues();
  203. values.put(DummyProvider.NAME, NAME2);
  204. values.put(DummyProvider.VALUE, VALUE2);
  205. mResolver.update(DummyProvider.CONTENT_URI, values,
  206. DummyProvider.NAME + " = '" + NAME0 + "'", null);
  207. // values have not been updated
  208. assertFalse(observer.hadUpdated(0));
  209. contentValues = mContentQueryMap.getValues(NAME0);
  210. assertNotNull(contentValues);
  211. assertEquals(VALUE0, contentValues.getAsString(DummyProvider.VALUE));
  212. contentValues = mContentQueryMap.getValues(NAME2);
  213. assertNull(contentValues);
  214. // have to update manually
  215. mContentQueryMap.requery();
  216. assertTrue(observer.hadUpdated(0));
  217. assertSame(mContentQueryMap, observer.getObservable());
  218. contentValues = mContentQueryMap.getValues(NAME0);
  219. assertNull(contentValues);
  220. contentValues = mContentQueryMap.getValues(NAME2);
  221. assertNotNull(contentValues);
  222. assertEquals(VALUE2, contentValues.getAsString(DummyProvider.VALUE));
  223. observer.reset();
  224. contentValues = mContentQueryMap.getValues(NAME3);
  225. assertNull(contentValues);
  226. new Thread(new Runnable() {
  227. public void run() {
  228. Looper.prepare();
  229. mContentQueryMap.setKeepUpdated(true);
  230. Looper.loop();
  231. }
  232. }).start();
  233. // insert NAME3 and VALUE3
  234. values = new ContentValues();
  235. values.put(DummyProvider.NAME, NAME3);
  236. values.put(DummyProvider.VALUE, VALUE3);
  237. mResolver.insert(DummyProvider.CONTENT_URI, values);
  238. // should be updated automatically
  239. assertTrue(observer.hadUpdated(TEST_TIME_OUT));
  240. assertSame(mContentQueryMap, observer.getObservable());
  241. contentValues = mContentQueryMap.getValues(NAME3);
  242. assertNotNull(contentValues);
  243. assertEquals(VALUE3, contentValues.getAsString(DummyProvider.VALUE));
  244. observer.reset();
  245. new Thread(new Runnable() {
  246. public void run() {
  247. Looper.prepare();
  248. mContentQueryMap.setKeepUpdated(false);
  249. Looper.loop();
  250. }
  251. }).start();
  252. // update NAME3 and VALUE3
  253. values = new ContentValues();
  254. values.put(DummyProvider.NAME, NAME0);
  255. values.put(DummyProvider.VALUE, VALUE0);
  256. mResolver.update(DummyProvider.CONTENT_URI, values,
  257. DummyProvider.NAME + " = '" + NAME3 + "'", null);
  258. // values have not been updated
  259. assertFalse(observer.hadUpdated(TEST_TIME_OUT));
  260. contentValues = mContentQueryMap.getValues(NAME3);
  261. assertNotNull(contentValues);
  262. assertEquals(VALUE3, contentValues.getAsString(DummyProvider.VALUE));
  263. }
  264. @TestTargets({
  265. @TestTargetNew(
  266. level = TestLevel.COMPLETE,
  267. method = "setKeepUpdated",
  268. args = {boolean.class}
  269. ),
  270. @TestTargetNew(
  271. level = TestLevel.COMPLETE,
  272. method = "getValues",
  273. args = {java.lang.String.class}
  274. )
  275. })
  276. public void testSetKeepUpdatedWithHandler() throws InterruptedException {
  277. MockObserver observer = new MockObserver();
  278. HandlerThread thread = new HandlerThread("testSetKeepUpdatedWithHandler");
  279. thread.start();
  280. Handler handler = new Handler(thread.getLooper());
  281. // keepUpdated is false
  282. mContentQueryMap = new ContentQueryMap(mCursor, DummyProvider.NAME, false, handler);
  283. mContentQueryMap.addObserver(observer);
  284. assertFalse(observer.hadUpdated(0));
  285. ContentValues contentValues = mContentQueryMap.getValues(NAME0);
  286. assertNotNull(contentValues);
  287. assertEquals(VALUE0, contentValues.getAsString(DummyProvider.VALUE));
  288. contentValues = mContentQueryMap.getValues(NAME2);
  289. assertNull(contentValues);
  290. // update NAME0 and VALUE0
  291. ContentValues values = new ContentValues();
  292. values.put(DummyProvider.NAME, NAME2);
  293. values.put(DummyProvider.VALUE, VALUE2);
  294. mResolver.update(DummyProvider.CONTENT_URI, values,
  295. DummyProvider.NAME + " = '" + NAME0 + "'", null);
  296. // values have not been updated
  297. assertFalse(observer.hadUpdated(TEST_TIME_OUT));
  298. contentValues = mContentQueryMap.getValues(NAME0);
  299. assertNotNull(contentValues);
  300. assertEquals(VALUE0, contentValues.getAsString(DummyProvider.VALUE));
  301. contentValues = mContentQueryMap.getValues(NAME2);
  302. assertNull(contentValues);
  303. // have to update manually
  304. mContentQueryMap.requery();
  305. assertTrue(observer.hadUpdated(0));
  306. assertSame(mContentQueryMap, observer.getObservable());
  307. contentValues = mContentQueryMap.getValues(NAME0);
  308. assertNull(contentValues);
  309. contentValues = mContentQueryMap.getValues(NAME2);
  310. assertNotNull(contentValues);
  311. assertEquals(VALUE2, contentValues.getAsString(DummyProvider.VALUE));
  312. observer.reset();
  313. contentValues = mContentQueryMap.getValues(NAME3);
  314. assertNull(contentValues);
  315. mContentQueryMap.setKeepUpdated(true);
  316. // insert NAME3 and VALUE3
  317. values = new ContentValues();
  318. values.put(DummyProvider.NAME, NAME3);
  319. values.put(DummyProvider.VALUE, VALUE3);
  320. mResolver.insert(DummyProvider.CONTENT_URI, values);
  321. // should be updated automatically
  322. assertTrue(observer.hadUpdated(TEST_TIME_OUT));
  323. assertSame(mContentQueryMap, observer.getObservable());
  324. contentValues = mContentQueryMap.getValues(NAME3);
  325. assertNotNull(contentValues);
  326. assertEquals(VALUE3, contentValues.getAsString(DummyProvider.VALUE));
  327. observer.reset();
  328. mContentQueryMap.setKeepUpdated(false);
  329. // update NAME3 and VALUE3
  330. values = new ContentValues();
  331. values.put(DummyProvider.NAME, NAME0);
  332. values.put(DummyProvider.VALUE, VALUE0);
  333. mResolver.update(DummyProvider.CONTENT_URI, values,
  334. DummyProvider.NAME + " = '" + NAME3 + "'", null);
  335. // values have not been updated
  336. assertFalse(observer.hadUpdated(TEST_TIME_OUT));
  337. contentValues = mContentQueryMap.getValues(NAME3);
  338. assertNotNull(contentValues);
  339. assertEquals(VALUE3, contentValues.getAsString(DummyProvider.VALUE));
  340. }
  341. @TestTargetNew(
  342. level = TestLevel.COMPLETE,
  343. method = "getValues",
  344. args = {java.lang.String.class}
  345. )
  346. public void testGetValuesBoundary() {
  347. mContentQueryMap = new ContentQueryMap(mCursor, DummyProvider.NAME, false, null);
  348. assertNull(mContentQueryMap.getValues(null));
  349. assertNull(mContentQueryMap.getValues(""));
  350. }
  351. private static final class MockObserver implements Observer {
  352. private boolean mHadUpdated = false;
  353. private Observable mObservable;
  354. public void reset() {
  355. mHadUpdated = false;
  356. mObservable = null;
  357. }
  358. public synchronized void update(Observable observable, Object data) {
  359. mObservable = observable;
  360. mHadUpdated = true;
  361. notify();
  362. }
  363. public Observable getObservable() {
  364. return mObservable;
  365. }
  366. public synchronized boolean hadUpdated(long timeout) throws InterruptedException {
  367. // do not wait if timeout is 0
  368. if (timeout > 0 && !mHadUpdated) {
  369. wait(timeout);
  370. }
  371. return mHadUpdated;
  372. }
  373. }
  374. }