blob: 8f3222839bb1456f8096d0e181c88838fceb58dc [file] [log] [blame]
/*
* 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 testBitmap = WidgetTestUtils.getUnscaledBitmap(mContext.getResources(),
testimgRawId);
WidgetTestUtils.assertEquals(testBitmap,
((BitmapDrawable) view.getDrawable()).getBitmap());
} 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;
}
}
}