| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.widget.cts; |
| |
| import com.android.cts.stub.R; |
| import com.android.common.ArrayListCursor; |
| |
| import dalvik.annotation.TestLevel; |
| import dalvik.annotation.TestTargetClass; |
| import dalvik.annotation.TestTargetNew; |
| import dalvik.annotation.TestTargets; |
| import dalvik.annotation.ToBeFixed; |
| |
| import android.content.Context; |
| import android.database.Cursor; |
| import android.graphics.Bitmap; |
| import android.graphics.drawable.BitmapDrawable; |
| import android.test.InstrumentationTestCase; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.ImageView; |
| import android.widget.LinearLayout; |
| import android.widget.SimpleCursorAdapter; |
| import android.widget.TextView; |
| import android.widget.SimpleCursorAdapter.CursorToStringConverter; |
| import android.widget.SimpleCursorAdapter.ViewBinder; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.ArrayList; |
| |
| /** |
| * Test {@link SimpleCursorAdapter}. |
| */ |
| @TestTargetClass(SimpleCursorAdapter.class) |
| public class SimpleCursorAdapterTest extends InstrumentationTestCase { |
| private static final int ADAPTER_ROW_COUNT = 20; |
| |
| private static final int DEFAULT_COLUMN_COUNT = 2; |
| |
| private static final int[] VIEWS_TO = new int[] { R.id.cursorAdapter_item0 }; |
| |
| private static final String[] COLUMNS_FROM = new String[] { "column1" }; |
| |
| private static final String SAMPLE_IMAGE_NAME = "testimage.jpg"; |
| |
| /** |
| * The simple cursor adapter. Its cursor will be set to |
| * {@link SimpleCursorAdapterTest#mCursor} It will use internal |
| * R.layout.simple_list_item_1. |
| */ |
| private SimpleCursorAdapter mSimpleCursorAdapter; |
| |
| private Context mContext; |
| |
| /** |
| * The original cursor and its content will be set to: |
| * <TABLE> |
| * <TR> |
| * <TH>Column0</TH> |
| * <TH>Column1</TH> |
| * </TR> |
| * <TR> |
| * <TD>00</TD> |
| * <TD>01</TD> |
| * </TR> |
| * <TR> |
| * <TD>10</TD> |
| * <TD>11</TD> |
| * </TR> |
| * <TR> |
| * <TD>...</TD> |
| * <TD>...</TD> |
| * </TR> |
| * <TR> |
| * <TD>190</TD> |
| * <TD>191</TD> |
| * </TR> |
| * </TABLE> |
| * It has 2 columns and 20 rows |
| */ |
| private Cursor mCursor; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| mContext = getInstrumentation().getTargetContext(); |
| |
| mCursor = createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT); |
| mSimpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0, |
| mCursor, COLUMNS_FROM, VIEWS_TO); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "SimpleCursorAdapter", |
| args = {android.content.Context.class, int.class, android.database.Cursor.class, |
| java.lang.String[].class, int[].class} |
| ) |
| public void testConstructor() { |
| new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0, |
| createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT), |
| COLUMNS_FROM, VIEWS_TO); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "bindView", |
| args = {android.view.View.class, android.content.Context.class, |
| android.database.Cursor.class} |
| ) |
| @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of " |
| + "SimpleCursorAdapter#bindView(View, Context, Cursor) if the param view is " |
| + "not TextView or ImageView and ViewBinder failed to bind the view") |
| public void testBindView() { |
| TextView listItem = (TextView) mSimpleCursorAdapter.newView(mContext, null, null); |
| |
| listItem.setText(""); |
| mCursor.moveToFirst(); |
| mSimpleCursorAdapter.bindView(listItem, null, mCursor); |
| assertEquals("01", listItem.getText().toString()); |
| |
| mCursor.moveToLast(); |
| mSimpleCursorAdapter.bindView(listItem, null, mCursor); |
| assertEquals("191", listItem.getText().toString()); |
| |
| // the binder take care of binding |
| listItem.setText(""); |
| MockViewBinder binder = new MockViewBinder(true); |
| mSimpleCursorAdapter.setViewBinder(binder); |
| binder.reset(); |
| mCursor.moveToFirst(); |
| mSimpleCursorAdapter.bindView(listItem, null, mCursor); |
| assertTrue(binder.hasCalledSetViewValueCalledCount()); |
| assertEquals("", listItem.getText().toString()); |
| |
| // the binder try to bind but fail |
| binder = new MockViewBinder(false); |
| mSimpleCursorAdapter.setViewBinder(binder); |
| mCursor.moveToLast(); |
| mSimpleCursorAdapter.bindView(listItem, null, mCursor); |
| assertTrue(binder.hasCalledSetViewValueCalledCount()); |
| assertEquals("191", listItem.getText().toString()); |
| |
| final int [] to = { R.id.cursorAdapter_host }; |
| mSimpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_host, |
| mCursor, COLUMNS_FROM, to); |
| LinearLayout illegalView = (LinearLayout)mSimpleCursorAdapter.newView(mContext, null, null); |
| try { |
| // The IllegalStateException already gets thrown in the line above. |
| mSimpleCursorAdapter.bindView(illegalView, null, mCursor); |
| fail("Should throw IllegalStateException if the view is not TextView or ImageView"); |
| } catch (IllegalStateException e) { |
| // expected |
| } |
| } |
| |
| @TestTargets({ |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "getViewBinder", |
| args = {} |
| ), |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "setViewBinder", |
| args = {ViewBinder.class} |
| ) |
| }) |
| public void testAccessViewBinder() { |
| assertNull(mSimpleCursorAdapter.getViewBinder()); |
| |
| MockViewBinder binder = new MockViewBinder(true); |
| mSimpleCursorAdapter.setViewBinder(binder); |
| assertSame(binder, mSimpleCursorAdapter.getViewBinder()); |
| |
| binder = new MockViewBinder(false); |
| mSimpleCursorAdapter.setViewBinder(binder); |
| assertSame(binder, mSimpleCursorAdapter.getViewBinder()); |
| |
| mSimpleCursorAdapter.setViewBinder(null); |
| assertNull(mSimpleCursorAdapter.getViewBinder()); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "setViewText", |
| args = {TextView.class, String.class} |
| ) |
| public void testSetViewText() { |
| TextView view = new TextView(mContext); |
| mSimpleCursorAdapter.setViewText(view, "expected"); |
| assertEquals("expected", view.getText().toString()); |
| |
| mSimpleCursorAdapter.setViewText(view, null); |
| assertEquals("", view.getText().toString()); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "setViewImage", |
| args = {ImageView.class, String.class} |
| ) |
| @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of " |
| + "SimpleCursorAdapter#setViewImage(ImageView, String) if the param String is null") |
| public void testSetViewImage() { |
| // resId |
| int sceneryImgResId = com.android.cts.stub.R.drawable.scenery; |
| ImageView view = new ImageView(mContext); |
| assertNull(view.getDrawable()); |
| mSimpleCursorAdapter.setViewImage(view, String.valueOf(sceneryImgResId)); |
| assertNotNull(view.getDrawable()); |
| BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable( |
| sceneryImgResId); |
| WidgetTestUtils.assertEquals(d.getBitmap(), |
| ((BitmapDrawable) view.getDrawable()).getBitmap()); |
| |
| // blank |
| view = new ImageView(mContext); |
| assertNull(view.getDrawable()); |
| mSimpleCursorAdapter.setViewImage(view, ""); |
| assertNull(view.getDrawable()); |
| |
| // null |
| view = new ImageView(mContext); |
| assertNull(view.getDrawable()); |
| try { |
| // Should declare NullPoinertException if the uri or value is null |
| mSimpleCursorAdapter.setViewImage(view, null); |
| fail("Should throw NullPointerException if the uri or value is null"); |
| } catch (NullPointerException e) { |
| // expected |
| } |
| |
| // uri |
| view = new ImageView(mContext); |
| assertNull(view.getDrawable()); |
| try { |
| int testimgRawId = com.android.cts.stub.R.raw.testimage; |
| mSimpleCursorAdapter.setViewImage(view, |
| createTestImage(mContext, SAMPLE_IMAGE_NAME, testimgRawId)); |
| assertNotNull(view.getDrawable()); |
| Bitmap actualBitmap = ((BitmapDrawable) view.getDrawable()).getBitmap(); |
| Bitmap testBitmap = WidgetTestUtils.getUnscaledAndDitheredBitmap(mContext.getResources(), |
| testimgRawId, actualBitmap.getConfig()); |
| WidgetTestUtils.assertEquals(testBitmap, actualBitmap); |
| } finally { |
| destroyTestImage(mContext, SAMPLE_IMAGE_NAME); |
| } |
| } |
| |
| @TestTargets({ |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "getStringConversionColumn", |
| args = {} |
| ), |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "setStringConversionColumn", |
| args = {int.class} |
| ) |
| }) |
| @ToBeFixed(explanation = "SimpleCursorAdapter#setStringConversionColumn(int) " |
| + "should check whether the param stringConversionColumn is out of index") |
| public void testAccessStringConversionColumn() { |
| // default is -1 |
| assertEquals(-1, mSimpleCursorAdapter.getStringConversionColumn()); |
| |
| mSimpleCursorAdapter.setStringConversionColumn(1); |
| assertEquals(1, mSimpleCursorAdapter.getStringConversionColumn()); |
| |
| // Should check whether the column index is out of bounds |
| mSimpleCursorAdapter.setStringConversionColumn(Integer.MAX_VALUE); |
| assertEquals(Integer.MAX_VALUE, mSimpleCursorAdapter.getStringConversionColumn()); |
| |
| // Should check whether the column index is out of bounds |
| mSimpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE); |
| assertEquals(Integer.MIN_VALUE, mSimpleCursorAdapter.getStringConversionColumn()); |
| } |
| |
| @TestTargets({ |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "getCursorToStringConverter", |
| args = {} |
| ), |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "setCursorToStringConverter", |
| args = {CursorToStringConverter.class} |
| ) |
| }) |
| public void testAccessCursorToStringConverter() { |
| // default is null |
| assertNull(mSimpleCursorAdapter.getCursorToStringConverter()); |
| |
| CursorToStringConverter converter = new MockCursorToStringConverter(); |
| mSimpleCursorAdapter.setCursorToStringConverter(converter); |
| assertSame(converter, mSimpleCursorAdapter.getCursorToStringConverter()); |
| |
| mSimpleCursorAdapter.setCursorToStringConverter(null); |
| assertNull(mSimpleCursorAdapter.getCursorToStringConverter()); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| notes = "Test {@link SimpleCursorAdapter#changeCursor(Cursor)}", |
| method = "changeCursor", |
| args = {Cursor.class} |
| ) |
| @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of " |
| + "SimpleCursorAdapter#changeCursor(Cursor) if the param cursor does not contain" |
| + "any column passed in the constructor") |
| public void testChangeCursor() { |
| // have "column1" |
| Cursor curWith3Columns = createTestCursor(3, ADAPTER_ROW_COUNT); |
| mSimpleCursorAdapter.changeCursor(curWith3Columns); |
| assertSame(curWith3Columns, mSimpleCursorAdapter.getCursor()); |
| |
| // does not have "column1" |
| Cursor curWith1Column = createTestCursor(1, ADAPTER_ROW_COUNT); |
| try { |
| mSimpleCursorAdapter.changeCursor(curWith1Column); |
| fail("Should throw exception if the cursor does not have the " |
| + "original column passed in the constructor"); |
| } catch (IllegalArgumentException e) { |
| // expected |
| } |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| notes = "Test {@link SimpleCursorAdapter#convertToString(Cursor)}", |
| method = "convertToString", |
| args = {Cursor.class} |
| ) |
| @ToBeFixed(bug = "1417734", explanation = "should add @throws clause into javadoc of " |
| + "SimpleCursorAdapter#convertToString(Cursor) if the StringConversionColumn set " |
| + "by SimpleCursorAdapter#setStringConversionColumn(int) is beyond the columns count") |
| public void testConvertToString() { |
| mCursor.moveToFirst(); |
| assertEquals("", mSimpleCursorAdapter.convertToString(null)); |
| |
| // converter is null, StringConversionColumn is set to negative |
| mSimpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE); |
| assertEquals(mCursor.toString(), mSimpleCursorAdapter.convertToString(mCursor)); |
| |
| // converter is null, StringConversionColumn is set to 1 |
| mSimpleCursorAdapter.setStringConversionColumn(1); |
| assertEquals("01", mSimpleCursorAdapter.convertToString(mCursor)); |
| |
| // converter is null, StringConversionColumn is set to 3 (larger than columns count) |
| // the cursor has 3 columns including column0, column1 and _id which is added automatically |
| mSimpleCursorAdapter.setStringConversionColumn(DEFAULT_COLUMN_COUNT + 1); |
| try { |
| mSimpleCursorAdapter.convertToString(mCursor); |
| fail("Should throw IndexOutOfBoundsException if index is beyond the columns count"); |
| } catch (IndexOutOfBoundsException e) { |
| // expected |
| } |
| |
| Cursor curWith3Columns = createTestCursor(DEFAULT_COLUMN_COUNT + 1, ADAPTER_ROW_COUNT); |
| curWith3Columns.moveToFirst(); |
| |
| // converter is null, StringConversionColumn is set to 3 |
| // and covert with a cursor which has 4 columns |
| mSimpleCursorAdapter.setStringConversionColumn(2); |
| assertEquals("02", mSimpleCursorAdapter.convertToString(curWith3Columns)); |
| |
| // converter is not null, StringConversionColumn is 1 |
| CursorToStringConverter converter = new MockCursorToStringConverter(); |
| mSimpleCursorAdapter.setCursorToStringConverter(converter); |
| mSimpleCursorAdapter.setStringConversionColumn(1); |
| ((MockCursorToStringConverter) converter).reset(); |
| mSimpleCursorAdapter.convertToString(curWith3Columns); |
| assertTrue(((MockCursorToStringConverter) converter).hasCalledConvertToString()); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "newView", |
| args = {Context.class, Cursor.class, ViewGroup.class} |
| ) |
| public void testNewView() { |
| LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService( |
| Context.LAYOUT_INFLATER_SERVICE); |
| ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate( |
| com.android.cts.stub.R.layout.cursoradapter_host, null); |
| View result = mSimpleCursorAdapter.newView(mContext, null, viewGroup); |
| assertNotNull(result); |
| assertEquals(R.id.cursorAdapter_item0, result.getId()); |
| |
| result = mSimpleCursorAdapter.newView(mContext, null, null); |
| assertNotNull(result); |
| assertEquals(R.id.cursorAdapter_item0, result.getId()); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "newDropDownView", |
| args = {Context.class, Cursor.class, ViewGroup.class} |
| ) |
| public void testNewDropDownView() { |
| LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService( |
| Context.LAYOUT_INFLATER_SERVICE); |
| ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate( |
| com.android.cts.stub.R.layout.cursoradapter_host, null); |
| View result = mSimpleCursorAdapter.newDropDownView(null, null, viewGroup); |
| assertNotNull(result); |
| assertEquals(R.id.cursorAdapter_item0, result.getId()); |
| } |
| |
| @TestTargetNew( |
| level = TestLevel.COMPLETE, |
| method = "changeCursorAndColumns", |
| args = {Cursor.class, String[].class, int[].class} |
| ) |
| public void testChangeCursorAndColumns() { |
| assertSame(mCursor, mSimpleCursorAdapter.getCursor()); |
| |
| TextView listItem = (TextView) mSimpleCursorAdapter.newView(mContext, null, null); |
| |
| mCursor.moveToFirst(); |
| mSimpleCursorAdapter.bindView(listItem, null, mCursor); |
| assertEquals("01", listItem.getText().toString()); |
| |
| mCursor.moveToLast(); |
| mSimpleCursorAdapter.bindView(listItem, null, mCursor); |
| assertEquals("191", listItem.getText().toString()); |
| |
| Cursor newCursor = createTestCursor(3, ADAPTER_ROW_COUNT); |
| final String[] from = new String[] { "column2" }; |
| mSimpleCursorAdapter.changeCursorAndColumns(newCursor, from, VIEWS_TO); |
| assertSame(newCursor, mSimpleCursorAdapter.getCursor()); |
| newCursor.moveToFirst(); |
| mSimpleCursorAdapter.bindView(listItem, null, newCursor); |
| assertEquals("02", listItem.getText().toString()); |
| |
| newCursor.moveToLast(); |
| mSimpleCursorAdapter.bindView(listItem, null, newCursor); |
| assertEquals("192", listItem.getText().toString()); |
| |
| mSimpleCursorAdapter.changeCursorAndColumns(null, null, null); |
| assertNull(mSimpleCursorAdapter.getCursor()); |
| } |
| |
| /** |
| * Creates the test cursor. |
| * |
| * @param colCount the column count |
| * @param rowCount the row count |
| * @return the cursor |
| */ |
| @SuppressWarnings("unchecked") |
| private Cursor createTestCursor(int colCount, int rowCount) { |
| ArrayList<ArrayList> list = new ArrayList<ArrayList>(); |
| String[] columns = new String[colCount]; |
| for (int i = 0; i < colCount; i++) { |
| columns[i] = "column" + i; |
| } |
| |
| for (int i = 0; i < rowCount; i++) { |
| ArrayList<String> row = new ArrayList<String>(); |
| for (int j = 0; j < colCount; j++) { |
| row.add("" + i + "" + j); |
| } |
| list.add(row); |
| } |
| |
| return new ArrayListCursor(columns, list); |
| } |
| |
| private static class MockViewBinder implements ViewBinder { |
| private boolean mExpectedResult; |
| |
| private boolean mHasCalledSetViewValue; |
| |
| public MockViewBinder(boolean expectedResult) { |
| mExpectedResult = expectedResult; |
| } |
| |
| public void reset(){ |
| mHasCalledSetViewValue = false; |
| } |
| |
| public boolean hasCalledSetViewValueCalledCount() { |
| return mHasCalledSetViewValue; |
| } |
| |
| public boolean setViewValue(View view, Cursor cursor, int columnIndex) { |
| mHasCalledSetViewValue = true; |
| return mExpectedResult; |
| } |
| } |
| |
| public static String createTestImage(Context context, String fileName, int resId) { |
| InputStream source = null; |
| OutputStream target = null; |
| |
| try { |
| source = context.getResources().openRawResource(resId); |
| target = context.openFileOutput(fileName, Context.MODE_WORLD_WRITEABLE); |
| |
| byte[] buffer = new byte[1024]; |
| for (int len = source.read(buffer); len > 0; len = source.read(buffer)) { |
| target.write(buffer, 0, len); |
| } |
| } catch (IOException e) { |
| fail(e.getMessage()); |
| } finally { |
| try { |
| if (source != null) { |
| source.close(); |
| } |
| if (target != null) { |
| target.close(); |
| } |
| } catch (IOException e) { |
| // Ignore the IOException. |
| } |
| } |
| |
| return context.getFileStreamPath(fileName).getAbsolutePath(); |
| } |
| |
| public static void destroyTestImage(Context context, String fileName) { |
| context.deleteFile(fileName); |
| } |
| |
| private static class MockCursorToStringConverter implements CursorToStringConverter { |
| private boolean mHasCalledConvertToString; |
| |
| public boolean hasCalledConvertToString() { |
| return mHasCalledConvertToString; |
| } |
| |
| public void reset(){ |
| mHasCalledConvertToString = false; |
| } |
| |
| public CharSequence convertToString(Cursor cursor) { |
| mHasCalledConvertToString = true; |
| return null; |
| } |
| } |
| } |