• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.cts;
18 
19 import android.widget.cts.R;
20 
21 
22 import android.content.Context;
23 import android.cts.util.WidgetTestUtils;
24 import android.database.Cursor;
25 import android.database.MatrixCursor;
26 import android.graphics.Bitmap;
27 import android.graphics.drawable.BitmapDrawable;
28 import android.test.InstrumentationTestCase;
29 import android.test.UiThreadTest;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.ImageView;
34 import android.widget.LinearLayout;
35 import android.widget.SimpleCursorAdapter;
36 import android.widget.TextView;
37 import android.widget.SimpleCursorAdapter.CursorToStringConverter;
38 import android.widget.SimpleCursorAdapter.ViewBinder;
39 
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.OutputStream;
43 
44 /**
45  * Test {@link SimpleCursorAdapter}.
46  * The simple cursor adapter's cursor will be set to
47  * {@link SimpleCursorAdapterTest#mCursor} It will use internal
48  * R.layout.simple_list_item_1.
49  */
50 public class SimpleCursorAdapterTest extends InstrumentationTestCase {
51     private static final int ADAPTER_ROW_COUNT = 20;
52 
53     private static final int DEFAULT_COLUMN_COUNT = 2;
54 
55     private static final int[] VIEWS_TO = new int[] { R.id.cursorAdapter_item0 };
56 
57     private static final String[] COLUMNS_FROM = new String[] { "column1" };
58 
59     private static final String SAMPLE_IMAGE_NAME = "testimage.jpg";
60 
61     private Context mContext;
62 
63     /**
64      * The original cursor and its content will be set to:
65      * <TABLE>
66      * <TR>
67      * <TH>Column0</TH>
68      * <TH>Column1</TH>
69      * </TR>
70      * <TR>
71      * <TD>00</TD>
72      * <TD>01</TD>
73      * </TR>
74      * <TR>
75      * <TD>10</TD>
76      * <TD>11</TD>
77      * </TR>
78      * <TR>
79      * <TD>...</TD>
80      * <TD>...</TD>
81      * </TR>
82      * <TR>
83      * <TD>190</TD>
84      * <TD>191</TD>
85      * </TR>
86      * </TABLE>
87      * It has 2 columns and 20 rows
88      */
89     private Cursor mCursor;
90 
91     @Override
setUp()92     protected void setUp() throws Exception {
93         super.setUp();
94         mContext = getInstrumentation().getTargetContext();
95 
96         mCursor = createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT);
97     }
98 
makeSimpleCursorAdapter()99     private SimpleCursorAdapter makeSimpleCursorAdapter() {
100         return new SimpleCursorAdapter(
101                 mContext, R.layout.cursoradapter_item0, mCursor, COLUMNS_FROM, VIEWS_TO);
102     }
103 
104     @UiThreadTest
testConstructor()105     public void testConstructor() {
106         new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0,
107                 createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT),
108                 COLUMNS_FROM, VIEWS_TO);
109     }
110 
111     @UiThreadTest
testBindView()112     public void testBindView() {
113         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
114         TextView listItem = (TextView) simpleCursorAdapter.newView(mContext, null, null);
115 
116         listItem.setText("");
117         mCursor.moveToFirst();
118         simpleCursorAdapter.bindView(listItem, null, mCursor);
119         assertEquals("01", listItem.getText().toString());
120 
121         mCursor.moveToLast();
122         simpleCursorAdapter.bindView(listItem, null, mCursor);
123         assertEquals("191", listItem.getText().toString());
124 
125         // the binder take care of binding
126         listItem.setText("");
127         MockViewBinder binder = new MockViewBinder(true);
128         simpleCursorAdapter.setViewBinder(binder);
129         binder.reset();
130         mCursor.moveToFirst();
131         simpleCursorAdapter.bindView(listItem, null, mCursor);
132         assertTrue(binder.hasCalledSetViewValueCalledCount());
133         assertEquals("", listItem.getText().toString());
134 
135         // the binder try to bind but fail
136         binder = new MockViewBinder(false);
137         simpleCursorAdapter.setViewBinder(binder);
138         mCursor.moveToLast();
139         simpleCursorAdapter.bindView(listItem, null, mCursor);
140         assertTrue(binder.hasCalledSetViewValueCalledCount());
141         assertEquals("191", listItem.getText().toString());
142 
143         final int [] to = { R.id.cursorAdapter_host };
144         simpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_host,
145                 mCursor, COLUMNS_FROM, to);
146         LinearLayout illegalView = (LinearLayout)simpleCursorAdapter.newView(mContext, null, null);
147         try {
148             // The IllegalStateException already gets thrown in the line above.
149             simpleCursorAdapter.bindView(illegalView, null, mCursor);
150             fail("Should throw IllegalStateException if the view is not TextView or ImageView");
151         } catch (IllegalStateException e) {
152             // expected
153         }
154     }
155 
156     @UiThreadTest
testAccessViewBinder()157     public void testAccessViewBinder() {
158         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
159         assertNull(simpleCursorAdapter.getViewBinder());
160 
161         MockViewBinder binder = new MockViewBinder(true);
162         simpleCursorAdapter.setViewBinder(binder);
163         assertSame(binder, simpleCursorAdapter.getViewBinder());
164 
165         binder = new MockViewBinder(false);
166         simpleCursorAdapter.setViewBinder(binder);
167         assertSame(binder, simpleCursorAdapter.getViewBinder());
168 
169         simpleCursorAdapter.setViewBinder(null);
170         assertNull(simpleCursorAdapter.getViewBinder());
171     }
172 
173     @UiThreadTest
testSetViewText()174     public void testSetViewText() {
175         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
176         TextView view = new TextView(mContext);
177         simpleCursorAdapter.setViewText(view, "expected");
178         assertEquals("expected", view.getText().toString());
179 
180         simpleCursorAdapter.setViewText(view, null);
181         assertEquals("", view.getText().toString());
182     }
183 
184     @UiThreadTest
testSetViewImage()185     public void testSetViewImage() {
186         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
187         // resId
188         int sceneryImgResId = android.widget.cts.R.drawable.scenery;
189         ImageView view = new ImageView(mContext);
190         assertNull(view.getDrawable());
191         simpleCursorAdapter.setViewImage(view, String.valueOf(sceneryImgResId));
192         assertNotNull(view.getDrawable());
193         BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(
194                 sceneryImgResId);
195         WidgetTestUtils.assertEquals(d.getBitmap(),
196                 ((BitmapDrawable) view.getDrawable()).getBitmap());
197 
198         // blank
199         view = new ImageView(mContext);
200         assertNull(view.getDrawable());
201         simpleCursorAdapter.setViewImage(view, "");
202         assertNull(view.getDrawable());
203 
204         // null
205         view = new ImageView(mContext);
206         assertNull(view.getDrawable());
207         try {
208             // Should declare NullPoinertException if the uri or value is null
209             simpleCursorAdapter.setViewImage(view, null);
210             fail("Should throw NullPointerException if the uri or value is null");
211         } catch (NullPointerException e) {
212             // expected
213         }
214 
215         // uri
216         view = new ImageView(mContext);
217         assertNull(view.getDrawable());
218         try {
219             int testimgRawId = android.widget.cts.R.raw.testimage;
220             simpleCursorAdapter.setViewImage(view,
221                     createTestImage(mContext, SAMPLE_IMAGE_NAME, testimgRawId));
222             assertNotNull(view.getDrawable());
223             Bitmap actualBitmap = ((BitmapDrawable) view.getDrawable()).getBitmap();
224             Bitmap testBitmap = WidgetTestUtils.getUnscaledAndDitheredBitmap(mContext.getResources(),
225                     testimgRawId, actualBitmap.getConfig());
226             WidgetTestUtils.assertEquals(testBitmap, actualBitmap);
227         } finally {
228             destroyTestImage(mContext, SAMPLE_IMAGE_NAME);
229         }
230     }
231 
232     @UiThreadTest
testAccessStringConversionColumn()233     public void testAccessStringConversionColumn() {
234         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
235         // default is -1
236         assertEquals(-1, simpleCursorAdapter.getStringConversionColumn());
237 
238         simpleCursorAdapter.setStringConversionColumn(1);
239         assertEquals(1, simpleCursorAdapter.getStringConversionColumn());
240 
241         // Should check whether the column index is out of bounds
242         simpleCursorAdapter.setStringConversionColumn(Integer.MAX_VALUE);
243         assertEquals(Integer.MAX_VALUE, simpleCursorAdapter.getStringConversionColumn());
244 
245         // Should check whether the column index is out of bounds
246         simpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
247         assertEquals(Integer.MIN_VALUE, simpleCursorAdapter.getStringConversionColumn());
248     }
249 
250     @UiThreadTest
testAccessCursorToStringConverter()251     public void testAccessCursorToStringConverter() {
252         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
253         // default is null
254         assertNull(simpleCursorAdapter.getCursorToStringConverter());
255 
256         CursorToStringConverter converter = new MockCursorToStringConverter();
257         simpleCursorAdapter.setCursorToStringConverter(converter);
258         assertSame(converter, simpleCursorAdapter.getCursorToStringConverter());
259 
260         simpleCursorAdapter.setCursorToStringConverter(null);
261         assertNull(simpleCursorAdapter.getCursorToStringConverter());
262     }
263 
264     @UiThreadTest
testChangeCursor()265     public void testChangeCursor() {
266         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
267         // have "column1"
268         Cursor curWith3Columns = createTestCursor(3, ADAPTER_ROW_COUNT);
269         simpleCursorAdapter.changeCursor(curWith3Columns);
270         assertSame(curWith3Columns, simpleCursorAdapter.getCursor());
271 
272         // does not have "column1"
273         Cursor curWith1Column = createTestCursor(1, ADAPTER_ROW_COUNT);
274         try {
275             simpleCursorAdapter.changeCursor(curWith1Column);
276             fail("Should throw exception if the cursor does not have the "
277                     + "original column passed in the constructor");
278         } catch (IllegalArgumentException e) {
279             // expected
280         }
281     }
282 
283     @UiThreadTest
testConvertToString()284     public void testConvertToString() {
285         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
286         mCursor.moveToFirst();
287         assertEquals("", simpleCursorAdapter.convertToString(null));
288 
289         // converter is null, StringConversionColumn is set to negative
290         simpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
291         assertEquals(mCursor.toString(), simpleCursorAdapter.convertToString(mCursor));
292 
293         // converter is null, StringConversionColumn is set to 1
294         simpleCursorAdapter.setStringConversionColumn(1);
295         assertEquals("01", simpleCursorAdapter.convertToString(mCursor));
296 
297         // converter is null, StringConversionColumn is set to 3 (larger than columns count)
298         // the cursor has 3 columns including column0, column1 and _id which is added automatically
299         simpleCursorAdapter.setStringConversionColumn(DEFAULT_COLUMN_COUNT + 1);
300         try {
301             simpleCursorAdapter.convertToString(mCursor);
302             fail("Should throw IndexOutOfBoundsException if index is beyond the columns count");
303         } catch (IndexOutOfBoundsException e) {
304             // expected
305         }
306 
307         Cursor curWith3Columns = createTestCursor(DEFAULT_COLUMN_COUNT + 1, ADAPTER_ROW_COUNT);
308         curWith3Columns.moveToFirst();
309 
310         // converter is null, StringConversionColumn is set to 3
311         // and covert with a cursor which has 4 columns
312         simpleCursorAdapter.setStringConversionColumn(2);
313         assertEquals("02", simpleCursorAdapter.convertToString(curWith3Columns));
314 
315         // converter is not null, StringConversionColumn is 1
316         CursorToStringConverter converter = new MockCursorToStringConverter();
317         simpleCursorAdapter.setCursorToStringConverter(converter);
318         simpleCursorAdapter.setStringConversionColumn(1);
319         ((MockCursorToStringConverter) converter).reset();
320         simpleCursorAdapter.convertToString(curWith3Columns);
321         assertTrue(((MockCursorToStringConverter) converter).hasCalledConvertToString());
322     }
323 
324     @UiThreadTest
testNewView()325     public void testNewView() {
326         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
327         LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
328                 Context.LAYOUT_INFLATER_SERVICE);
329         ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
330                 android.widget.cts.R.layout.cursoradapter_host, null);
331         View result = simpleCursorAdapter.newView(mContext, null, viewGroup);
332         assertNotNull(result);
333         assertEquals(R.id.cursorAdapter_item0, result.getId());
334 
335         result = simpleCursorAdapter.newView(mContext, null, null);
336         assertNotNull(result);
337         assertEquals(R.id.cursorAdapter_item0, result.getId());
338     }
339 
340     @UiThreadTest
testNewDropDownView()341     public void testNewDropDownView() {
342         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
343         LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
344                 Context.LAYOUT_INFLATER_SERVICE);
345         ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
346                 android.widget.cts.R.layout.cursoradapter_host, null);
347         View result = simpleCursorAdapter.newDropDownView(null, null, viewGroup);
348         assertNotNull(result);
349         assertEquals(R.id.cursorAdapter_item0, result.getId());
350     }
351 
352     @UiThreadTest
testChangeCursorAndColumns()353     public void testChangeCursorAndColumns() {
354         SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
355         assertSame(mCursor, simpleCursorAdapter.getCursor());
356 
357         TextView listItem = (TextView) simpleCursorAdapter.newView(mContext, null, null);
358 
359         mCursor.moveToFirst();
360         simpleCursorAdapter.bindView(listItem, null, mCursor);
361         assertEquals("01", listItem.getText().toString());
362 
363         mCursor.moveToLast();
364         simpleCursorAdapter.bindView(listItem, null, mCursor);
365         assertEquals("191", listItem.getText().toString());
366 
367         Cursor newCursor = createTestCursor(3, ADAPTER_ROW_COUNT);
368         final String[] from = new String[] { "column2" };
369         simpleCursorAdapter.changeCursorAndColumns(newCursor, from, VIEWS_TO);
370         assertSame(newCursor, simpleCursorAdapter.getCursor());
371         newCursor.moveToFirst();
372         simpleCursorAdapter.bindView(listItem, null, newCursor);
373         assertEquals("02", listItem.getText().toString());
374 
375         newCursor.moveToLast();
376         simpleCursorAdapter.bindView(listItem, null, newCursor);
377         assertEquals("192", listItem.getText().toString());
378 
379         simpleCursorAdapter.changeCursorAndColumns(null, null, null);
380         assertNull(simpleCursorAdapter.getCursor());
381     }
382 
383     /**
384      * Creates the test cursor.
385      *
386      * @param colCount the column count
387      * @param rowCount the row count
388      * @return the cursor
389      */
390     @SuppressWarnings("unchecked")
createTestCursor(int colCount, int rowCount)391     private Cursor createTestCursor(int colCount, int rowCount) {
392         String[] columns = new String[colCount + 1];
393         for (int i = 0; i < colCount; i++) {
394             columns[i] = "column" + i;
395         }
396         columns[colCount] = "_id";
397 
398         MatrixCursor cursor = new MatrixCursor(columns, rowCount);
399         Object[] row = new Object[colCount + 1];
400         for (int i = 0; i < rowCount; i++) {
401             for (int j = 0; j < colCount; j++) {
402                 row[j] = "" + i + "" + j;
403             }
404             row[colCount] = i;
405             cursor.addRow(row);
406         }
407         return cursor;
408     }
409 
410     private static class MockViewBinder implements ViewBinder {
411         private boolean mExpectedResult;
412 
413         private boolean mHasCalledSetViewValue;
414 
MockViewBinder(boolean expectedResult)415         public MockViewBinder(boolean expectedResult) {
416             mExpectedResult = expectedResult;
417         }
418 
reset()419         public void reset(){
420             mHasCalledSetViewValue = false;
421         }
422 
hasCalledSetViewValueCalledCount()423         public boolean hasCalledSetViewValueCalledCount() {
424             return mHasCalledSetViewValue;
425         }
426 
setViewValue(View view, Cursor cursor, int columnIndex)427         public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
428             mHasCalledSetViewValue = true;
429             return mExpectedResult;
430         }
431     }
432 
createTestImage(Context context, String fileName, int resId)433     public static String createTestImage(Context context, String fileName, int resId) {
434         InputStream source = null;
435         OutputStream target = null;
436 
437         try {
438             source = context.getResources().openRawResource(resId);
439             target = context.openFileOutput(fileName, Context.MODE_PRIVATE);
440 
441             byte[] buffer = new byte[1024];
442             for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
443                 target.write(buffer, 0, len);
444             }
445         } catch (IOException e) {
446             fail(e.getMessage());
447         } finally {
448             try {
449                 if (source != null) {
450                     source.close();
451                 }
452                 if (target != null) {
453                     target.close();
454                 }
455             } catch (IOException e) {
456                 // Ignore the IOException.
457             }
458         }
459 
460         return context.getFileStreamPath(fileName).getAbsolutePath();
461     }
462 
destroyTestImage(Context context, String fileName)463     public static void destroyTestImage(Context context, String fileName) {
464         context.deleteFile(fileName);
465     }
466 
467     private static class MockCursorToStringConverter implements CursorToStringConverter {
468         private boolean mHasCalledConvertToString;
469 
hasCalledConvertToString()470         public boolean hasCalledConvertToString() {
471             return mHasCalledConvertToString;
472         }
473 
reset()474         public void reset(){
475             mHasCalledConvertToString = false;
476         }
477 
convertToString(Cursor cursor)478         public CharSequence convertToString(Cursor cursor) {
479             mHasCalledConvertToString = true;
480             return null;
481         }
482     }
483 }
484