blob: 880da983273133ddbb9968d0a18c149e6bf07e1d [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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
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 com.android.compatibility.common.util.WidgetTestUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Test {@link SimpleCursorAdapter}.
* The simple cursor adapter's cursor will be set to
* {@link SimpleCursorAdapterTest#mCursor} It will use internal
* R.layout.simple_list_item_1.
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SimpleCursorAdapterTest {
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";
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;
@Before
public void setup() {
mContext = InstrumentationRegistry.getTargetContext();
mCursor = createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT);
}
private SimpleCursorAdapter makeSimpleCursorAdapter() {
return new SimpleCursorAdapter(
mContext, R.layout.cursoradapter_item0, mCursor, COLUMNS_FROM, VIEWS_TO);
}
@UiThreadTest
@Test
public void testConstructor() {
new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0,
createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT),
COLUMNS_FROM, VIEWS_TO);
}
@UiThreadTest
@Test
public void testBindView() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
TextView listItem = (TextView) simpleCursorAdapter.newView(mContext, null, null);
listItem.setText("");
mCursor.moveToFirst();
simpleCursorAdapter.bindView(listItem, null, mCursor);
assertEquals("01", listItem.getText().toString());
mCursor.moveToLast();
simpleCursorAdapter.bindView(listItem, null, mCursor);
assertEquals("191", listItem.getText().toString());
// the binder take care of binding
listItem.setText("");
SimpleCursorAdapter.ViewBinder binder = mock(SimpleCursorAdapter.ViewBinder.class);
doReturn(true).when(binder).setViewValue(any(View.class), any(Cursor.class), anyInt());
simpleCursorAdapter.setViewBinder(binder);
mCursor.moveToFirst();
simpleCursorAdapter.bindView(listItem, null, mCursor);
verify(binder, times(1)).setViewValue(any(View.class), eq(mCursor), eq(1));
assertEquals("", listItem.getText().toString());
// the binder try to bind but fail
doReturn(false).when(binder).setViewValue(any(View.class), any(Cursor.class), anyInt());
reset(binder);
mCursor.moveToLast();
simpleCursorAdapter.bindView(listItem, null, mCursor);
verify(binder, times(1)).setViewValue(any(View.class), eq(mCursor), eq(1));
assertEquals("191", listItem.getText().toString());
final int [] to = { R.id.cursorAdapter_host };
simpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_host,
mCursor, COLUMNS_FROM, to);
LinearLayout illegalView = (LinearLayout)simpleCursorAdapter.newView(mContext, null, null);
try {
// The IllegalStateException already gets thrown in the line above.
simpleCursorAdapter.bindView(illegalView, null, mCursor);
fail("Should throw IllegalStateException if the view is not TextView or ImageView");
} catch (IllegalStateException e) {
// expected
}
}
@UiThreadTest
@Test
public void testAccessViewBinder() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
assertNull(simpleCursorAdapter.getViewBinder());
SimpleCursorAdapter.ViewBinder binder = mock(SimpleCursorAdapter.ViewBinder.class);
doReturn(true).when(binder).setViewValue(any(View.class), any(Cursor.class), anyInt());
simpleCursorAdapter.setViewBinder(binder);
assertSame(binder, simpleCursorAdapter.getViewBinder());
doReturn(false).when(binder).setViewValue(any(View.class), any(Cursor.class), anyInt());
simpleCursorAdapter.setViewBinder(binder);
assertSame(binder, simpleCursorAdapter.getViewBinder());
simpleCursorAdapter.setViewBinder(null);
assertNull(simpleCursorAdapter.getViewBinder());
}
@UiThreadTest
@Test
public void testSetViewText() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
TextView view = new TextView(mContext);
simpleCursorAdapter.setViewText(view, "expected");
assertEquals("expected", view.getText().toString());
simpleCursorAdapter.setViewText(view, null);
assertEquals("", view.getText().toString());
}
@UiThreadTest
@Test
public void testSetViewImage() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
// resId
int sceneryImgResId = R.drawable.scenery;
ImageView view = new ImageView(mContext);
assertNull(view.getDrawable());
simpleCursorAdapter.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());
simpleCursorAdapter.setViewImage(view, "");
assertNull(view.getDrawable());
// null
view = new ImageView(mContext);
assertNull(view.getDrawable());
try {
// Should declare NullPoinertException if the uri or value is null
simpleCursorAdapter.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 = R.raw.testimage;
simpleCursorAdapter.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);
}
}
@UiThreadTest
@Test
public void testAccessStringConversionColumn() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
// default is -1
assertEquals(-1, simpleCursorAdapter.getStringConversionColumn());
simpleCursorAdapter.setStringConversionColumn(1);
assertEquals(1, simpleCursorAdapter.getStringConversionColumn());
// Should check whether the column index is out of bounds
simpleCursorAdapter.setStringConversionColumn(Integer.MAX_VALUE);
assertEquals(Integer.MAX_VALUE, simpleCursorAdapter.getStringConversionColumn());
// Should check whether the column index is out of bounds
simpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
assertEquals(Integer.MIN_VALUE, simpleCursorAdapter.getStringConversionColumn());
}
@UiThreadTest
@Test
public void testAccessCursorToStringConverter() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
// default is null
assertNull(simpleCursorAdapter.getCursorToStringConverter());
SimpleCursorAdapter.CursorToStringConverter converter =
mock(SimpleCursorAdapter.CursorToStringConverter.class);
simpleCursorAdapter.setCursorToStringConverter(converter);
assertSame(converter, simpleCursorAdapter.getCursorToStringConverter());
simpleCursorAdapter.setCursorToStringConverter(null);
assertNull(simpleCursorAdapter.getCursorToStringConverter());
}
@UiThreadTest
@Test
public void testChangeCursor() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
// have "column1"
Cursor curWith3Columns = createTestCursor(3, ADAPTER_ROW_COUNT);
simpleCursorAdapter.changeCursor(curWith3Columns);
assertSame(curWith3Columns, simpleCursorAdapter.getCursor());
// does not have "column1"
Cursor curWith1Column = createTestCursor(1, ADAPTER_ROW_COUNT);
try {
simpleCursorAdapter.changeCursor(curWith1Column);
fail("Should throw exception if the cursor does not have the "
+ "original column passed in the constructor");
} catch (IllegalArgumentException e) {
// expected
}
}
@UiThreadTest
@Test
public void testConvertToString() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
mCursor.moveToFirst();
assertEquals("", simpleCursorAdapter.convertToString(null));
// converter is null, StringConversionColumn is set to negative
simpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
assertEquals(mCursor.toString(), simpleCursorAdapter.convertToString(mCursor));
// converter is null, StringConversionColumn is set to 1
simpleCursorAdapter.setStringConversionColumn(1);
assertEquals("01", simpleCursorAdapter.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
simpleCursorAdapter.setStringConversionColumn(DEFAULT_COLUMN_COUNT + 1);
try {
simpleCursorAdapter.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
simpleCursorAdapter.setStringConversionColumn(2);
assertEquals("02", simpleCursorAdapter.convertToString(curWith3Columns));
// converter is not null, StringConversionColumn is 1
SimpleCursorAdapter.CursorToStringConverter converter =
mock(SimpleCursorAdapter.CursorToStringConverter.class);
simpleCursorAdapter.setCursorToStringConverter(converter);
simpleCursorAdapter.setStringConversionColumn(1);
simpleCursorAdapter.convertToString(curWith3Columns);
verify(converter, times(1)).convertToString(curWith3Columns);
}
@UiThreadTest
@Test
public void testNewView() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
R.layout.cursoradapter_host, null);
View result = simpleCursorAdapter.newView(mContext, null, viewGroup);
assertNotNull(result);
assertEquals(R.id.cursorAdapter_item0, result.getId());
result = simpleCursorAdapter.newView(mContext, null, null);
assertNotNull(result);
assertEquals(R.id.cursorAdapter_item0, result.getId());
}
@UiThreadTest
@Test
public void testNewDropDownView() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
R.layout.cursoradapter_host, null);
View result = simpleCursorAdapter.newDropDownView(null, null, viewGroup);
assertNotNull(result);
assertEquals(R.id.cursorAdapter_item0, result.getId());
}
@UiThreadTest
@Test
public void testChangeCursorAndColumns() {
SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
assertSame(mCursor, simpleCursorAdapter.getCursor());
TextView listItem = (TextView) simpleCursorAdapter.newView(mContext, null, null);
mCursor.moveToFirst();
simpleCursorAdapter.bindView(listItem, null, mCursor);
assertEquals("01", listItem.getText().toString());
mCursor.moveToLast();
simpleCursorAdapter.bindView(listItem, null, mCursor);
assertEquals("191", listItem.getText().toString());
Cursor newCursor = createTestCursor(3, ADAPTER_ROW_COUNT);
final String[] from = new String[] { "column2" };
simpleCursorAdapter.changeCursorAndColumns(newCursor, from, VIEWS_TO);
assertSame(newCursor, simpleCursorAdapter.getCursor());
newCursor.moveToFirst();
simpleCursorAdapter.bindView(listItem, null, newCursor);
assertEquals("02", listItem.getText().toString());
newCursor.moveToLast();
simpleCursorAdapter.bindView(listItem, null, newCursor);
assertEquals("192", listItem.getText().toString());
simpleCursorAdapter.changeCursorAndColumns(null, null, null);
assertNull(simpleCursorAdapter.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) {
String[] columns = new String[colCount + 1];
for (int i = 0; i < colCount; i++) {
columns[i] = "column" + i;
}
columns[colCount] = "_id";
MatrixCursor cursor = new MatrixCursor(columns, rowCount);
Object[] row = new Object[colCount + 1];
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < colCount; j++) {
row[j] = "" + i + "" + j;
}
row[colCount] = i;
cursor.addRow(row);
}
return cursor;
}
public static String createTestImage(Context context, String fileName, int resId) {
try (InputStream source = context.getResources().openRawResource(resId);
OutputStream target = context.openFileOutput(fileName, Context.MODE_PRIVATE)) {
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());
}
return context.getFileStreamPath(fileName).getAbsolutePath();
}
public static void destroyTestImage(Context context, String fileName) {
context.deleteFile(fileName);
}
}