1 /*
2  * Copyright (C) 2008 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 android.widget;
18 
19 import android.test.suitebuilder.annotation.Suppress;
20 import com.google.android.collect.Lists;
21 
22 import android.content.Context;
23 import android.database.Cursor;
24 import android.database.MatrixCursor;
25 import android.test.AndroidTestCase;
26 import android.test.suitebuilder.annotation.SmallTest;
27 
28 import java.util.ArrayList;
29 import java.util.Random;
30 
31 /**
32  * This is a series of tests of basic API contracts for SimpleCursorAdapter.  It is
33  * incomplete and can use work.
34  *
35  * NOTE:  This contract holds for underlying cursor types too and these should
36  * be extracted into a set of tests that can be run on any descendant of CursorAdapter.
37  */
38 @Suppress // Failing.
39 public class SimpleCursorAdapterTest extends AndroidTestCase {
40 
41     String[] mFrom;
42     int[] mTo;
43     int mLayout;
44     Context mContext;
45 
46     ArrayList<ArrayList> mData2x2;
47     Cursor mCursor2x2;
48 
49     /**
50      * Set up basic columns and cursor for the tests
51      */
52     @Override
setUp()53     public void setUp() throws Exception {
54         super.setUp();
55 
56         // all the pieces needed for the various tests
57         mFrom = new String[]{"Column1", "Column2", "_id"};
58         mTo = new int[]{com.android.internal.R.id.text1, com.android.internal.R.id.text2};
59         mLayout = com.android.internal.R.layout.simple_list_item_2;
60         mContext = getContext();
61 
62         // raw data for building a basic test cursor
63         mData2x2 = createTestList(2, 2);
64         mCursor2x2 = createCursor(mFrom, mData2x2);
65     }
66 
67     /**
68      * Borrowed from CursorWindowTest.java
69      */
createTestList(int rows, int cols)70     private ArrayList<ArrayList> createTestList(int rows, int cols) {
71         ArrayList<ArrayList> list = Lists.newArrayList();
72         Random generator = new Random();
73 
74         for (int i = 0; i < rows; i++) {
75             ArrayList<Integer> col = Lists.newArrayList();
76             list.add(col);
77             for (int j = 0; j < cols; j++) {
78                 // generate random number
79                 Integer r = generator.nextInt();
80                 col.add(r);
81             }
82             col.add(i);
83         }
84         return list;
85     }
86 
87     /**
88      * Test creating with a live cursor
89      */
90     @SmallTest
testCreateLive()91     public void testCreateLive() {
92         SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
93 
94         // Now see if we can pull 2 rows from the adapter
95         assertEquals(2, ca.getCount());
96     }
97 
98     /**
99      * Test creating with a null cursor
100      */
101     @SmallTest
testCreateNull()102     public void testCreateNull() {
103         SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, mFrom, mTo);
104 
105         // The adapter should report zero rows
106         assertEquals(0, ca.getCount());
107     }
108 
109     /**
110      * Test changeCursor() with live cursor
111      */
112     @SmallTest
testChangeCursorLive()113     public void testChangeCursorLive() {
114         SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
115 
116         // Now see if we can pull 2 rows from the adapter
117         assertEquals(2, ca.getCount());
118 
119         // now put in a different cursor (5 rows)
120         ArrayList<ArrayList> data2 = createTestList(5, 2);
121         Cursor c2 = createCursor(mFrom, data2);
122         ca.changeCursor(c2);
123 
124         // Now see if we can pull 5 rows from the adapter
125         assertEquals(5, ca.getCount());
126     }
127 
128     /**
129      * Test changeCursor() with null cursor
130      */
131     @SmallTest
testChangeCursorNull()132     public void testChangeCursorNull() {
133         SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
134 
135         // Now see if we can pull 2 rows from the adapter
136         assertEquals(2, ca.getCount());
137 
138         // now put in null
139         ca.changeCursor(null);
140 
141         // The adapter should report zero rows
142         assertEquals(0, ca.getCount());
143     }
144 
145     /**
146      * Test changeCursor() with differing column layout.  This confirms that the Adapter can
147      * deal with cursors that have the same essential data (as defined by the original mFrom
148      * array) but it's OK if the physical structure of the cursor changes (columns rearranged).
149      */
150     @SmallTest
testChangeCursorColumns()151     public void testChangeCursorColumns() {
152         TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2,
153                 mFrom, mTo);
154 
155         // check columns of original - mFrom and mTo should line up
156         int[] columns = ca.getConvertedFrom();
157         assertEquals(columns[0], 0);
158         assertEquals(columns[1], 1);
159 
160         // Now make a new cursor with similar data but rearrange the columns
161         String[] swappedFrom = new String[]{"Column2", "Column1", "_id"};
162         Cursor c2 = createCursor(swappedFrom, mData2x2);
163         ca.changeCursor(c2);
164         assertEquals(2, ca.getCount());
165 
166         // check columns to see if rearrangement tracked (should be swapped now)
167         columns = ca.getConvertedFrom();
168         assertEquals(columns[0], 1);
169         assertEquals(columns[1], 0);
170     }
171 
172     /**
173      * Test that you can safely construct with a null cursor *and* null to/from arrays.
174      * This is new functionality added in 12/2008.
175      */
176     @SmallTest
testNullConstructor()177     public void testNullConstructor() {
178         SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, null, null);
179         assertEquals(0, ca.getCount());
180     }
181 
182     /**
183      * Test going from a null cursor to a non-null cursor *and* setting the to/from arrays
184      * This is new functionality added in 12/2008.
185      */
186     @SmallTest
testChangeNullToMapped()187     public void testChangeNullToMapped() {
188         TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, null, null, null);
189         assertEquals(0, ca.getCount());
190 
191         ca.changeCursorAndColumns(mCursor2x2, mFrom, mTo);
192         assertEquals(2, ca.getCount());
193 
194         // check columns of original - mFrom and mTo should line up
195         int[] columns = ca.getConvertedFrom();
196         assertEquals(2, columns.length);
197         assertEquals(0, columns[0]);
198         assertEquals(1, columns[1]);
199         int[] viewIds = ca.getTo();
200         assertEquals(2, viewIds.length);
201         assertEquals(com.android.internal.R.id.text1, viewIds[0]);
202         assertEquals(com.android.internal.R.id.text2, viewIds[1]);
203     }
204 
205     /**
206      * Test going from one mapping to a different mapping
207      * This is new functionality added in 12/2008.
208      */
209     @SmallTest
testChangeMapping()210     public void testChangeMapping() {
211         TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2,
212                 mFrom, mTo);
213         assertEquals(2, ca.getCount());
214 
215         // Now create a new configuration with same cursor and just one column mapped
216         String[] singleFrom = new String[]{"Column1"};
217         int[] singleTo = new int[]{com.android.internal.R.id.text1};
218         ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo);
219 
220         // And examine the results, make sure they're still consistent
221         int[] columns = ca.getConvertedFrom();
222         assertEquals(1, columns.length);
223         assertEquals(0, columns[0]);
224         int[] viewIds = ca.getTo();
225         assertEquals(1, viewIds.length);
226         assertEquals(com.android.internal.R.id.text1, viewIds[0]);
227 
228         // And again, same cursor, different map
229         singleFrom = new String[]{"Column2"};
230         singleTo = new int[]{com.android.internal.R.id.text2};
231         ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo);
232 
233         // And examine the results, make sure they're still consistent
234         columns = ca.getConvertedFrom();
235         assertEquals(1, columns.length);
236         assertEquals(1, columns[0]);
237         viewIds = ca.getTo();
238         assertEquals(1, viewIds.length);
239         assertEquals(com.android.internal.R.id.text2, viewIds[0]);
240     }
241 
createCursor(String[] columns, ArrayList<ArrayList> list)242     private static MatrixCursor createCursor(String[] columns, ArrayList<ArrayList> list) {
243         MatrixCursor cursor = new MatrixCursor(columns, list.size());
244         for (ArrayList row : list) {
245             cursor.addRow(row);
246         }
247         return cursor;
248     }
249 
250     /**
251      * This is simply a way to sneak a look at the protected mFrom() array.  A more API-
252      * friendly way to do this would be to mock out a View and a ViewBinder and exercise
253      * it via those seams.
254      */
255     private static class TestSimpleCursorAdapter extends SimpleCursorAdapter {
256 
TestSimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to)257         public TestSimpleCursorAdapter(Context context, int layout, Cursor c,
258                 String[] from, int[] to) {
259             super(context, layout, c, from, to);
260         }
261 
getConvertedFrom()262         int[] getConvertedFrom() {
263             return mFrom;
264         }
265 
getTo()266         int[] getTo() {
267             return mTo;
268         }
269     }
270 }
271