/*
* 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;
import com.google.android.collect.Lists;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import java.util.ArrayList;
import java.util.Random;
/**
* This is a series of tests of basic API contracts for SimpleCursorAdapter. It is
* incomplete and can use work.
*
* NOTE: This contract holds for underlying cursor types too and these should
* be extracted into a set of tests that can be run on any descendant of CursorAdapter.
*/
public class SimpleCursorAdapterTest extends AndroidTestCase {
String[] mFrom;
int[] mTo;
int mLayout;
Context mContext;
ArrayList<ArrayList> mData2x2;
Cursor mCursor2x2;
/**
* Set up basic columns and cursor for the tests
*/
@Override
public void setUp() throws Exception {
super.setUp();
// all the pieces needed for the various tests
mFrom = new String[]{"Column1", "Column2", "_id"};
mTo = new int[]{com.android.internal.R.id.text1, com.android.internal.R.id.text2};
mLayout = com.android.internal.R.layout.simple_list_item_2;
mContext = getContext();
// raw data for building a basic test cursor
mData2x2 = createTestList(2, 2);
mCursor2x2 = createCursor(mFrom, mData2x2);
}
/**
* Borrowed from CursorWindowTest.java
*/
private ArrayList<ArrayList> createTestList(int rows, int cols) {
ArrayList<ArrayList> list = Lists.newArrayList();
Random generator = new Random();
for (int i = 0; i < rows; i++) {
ArrayList<Integer> col = Lists.newArrayList();
list.add(col);
for (int j = 0; j < cols; j++) {
// generate random number
Integer r = generator.nextInt();
col.add(r);
}
col.add(i);
}
return list;
}
/**
* Test creating with a live cursor
*/
@SmallTest
public void testCreateLive() {
SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
// Now see if we can pull 2 rows from the adapter
assertEquals(2, ca.getCount());
}
/**
* Test creating with a null cursor
*/
@SmallTest
public void testCreateNull() {
SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, mFrom, mTo);
// The adapter should report zero rows
assertEquals(0, ca.getCount());
}
/**
* Test changeCursor() with live cursor
*/
@SmallTest
public void testChangeCursorLive() {
SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
// Now see if we can pull 2 rows from the adapter
assertEquals(2, ca.getCount());
// now put in a different cursor (5 rows)
ArrayList<ArrayList> data2 = createTestList(5, 2);
Cursor c2 = createCursor(mFrom, data2);
ca.changeCursor(c2);
// Now see if we can pull 5 rows from the adapter
assertEquals(5, ca.getCount());
}
/**
* Test changeCursor() with null cursor
*/
@SmallTest
public void testChangeCursorNull() {
SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo);
// Now see if we can pull 2 rows from the adapter
assertEquals(2, ca.getCount());
// now put in null
ca.changeCursor(null);
// The adapter should report zero rows
assertEquals(0, ca.getCount());
}
/**
* Test changeCursor() with differing column layout. This confirms that the Adapter can
* deal with cursors that have the same essential data (as defined by the original mFrom
* array) but it's OK if the physical structure of the cursor changes (columns rearranged).
*/
@SmallTest
public void testChangeCursorColumns() {
TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2,
mFrom, mTo);
// check columns of original - mFrom and mTo should line up
int[] columns = ca.getConvertedFrom();
assertEquals(columns[0], 0);
assertEquals(columns[1], 1);
// Now make a new cursor with similar data but rearrange the columns
String[] swappedFrom = new String[]{"Column2", "Column1", "_id"};
Cursor c2 = createCursor(swappedFrom, mData2x2);
ca.changeCursor(c2);
assertEquals(2, ca.getCount());
// check columns to see if rearrangement tracked (should be swapped now)
columns = ca.getConvertedFrom();
assertEquals(columns[0], 1);
assertEquals(columns[1], 0);
}
/**
* Test that you can safely construct with a null cursor *and* null to/from arrays.
* This is new functionality added in 12/2008.
*/
@SmallTest
public void testNullConstructor() {
SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, null, null);
assertEquals(0, ca.getCount());
}
/**
* Test going from a null cursor to a non-null cursor *and* setting the to/from arrays
* This is new functionality added in 12/2008.
*/
@SmallTest
public void testChangeNullToMapped() {
TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, null, null, null);
assertEquals(0, ca.getCount());
ca.changeCursorAndColumns(mCursor2x2, mFrom, mTo);
assertEquals(2, ca.getCount());
// check columns of original - mFrom and mTo should line up
int[] columns = ca.getConvertedFrom();
assertEquals(2, columns.length);
assertEquals(0, columns[0]);
assertEquals(1, columns[1]);
int[] viewIds = ca.getTo();
assertEquals(2, viewIds.length);
assertEquals(com.android.internal.R.id.text1, viewIds[0]);
assertEquals(com.android.internal.R.id.text2, viewIds[1]);
}
/**
* Test going from one mapping to a different mapping
* This is new functionality added in 12/2008.
*/
@SmallTest
public void testChangeMapping() {
TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2,
mFrom, mTo);
assertEquals(2, ca.getCount());
// Now create a new configuration with same cursor and just one column mapped
String[] singleFrom = new String[]{"Column1"};
int[] singleTo = new int[]{com.android.internal.R.id.text1};
ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo);
// And examine the results, make sure they're still consistent
int[] columns = ca.getConvertedFrom();
assertEquals(1, columns.length);
assertEquals(0, columns[0]);
int[] viewIds = ca.getTo();
assertEquals(1, viewIds.length);
assertEquals(com.android.internal.R.id.text1, viewIds[0]);
// And again, same cursor, different map
singleFrom = new String[]{"Column2"};
singleTo = new int[]{com.android.internal.R.id.text2};
ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo);
// And examine the results, make sure they're still consistent
columns = ca.getConvertedFrom();
assertEquals(1, columns.length);
assertEquals(1, columns[0]);
viewIds = ca.getTo();
assertEquals(1, viewIds.length);
assertEquals(com.android.internal.R.id.text2, viewIds[0]);
}
private static MatrixCursor createCursor(String[] columns, ArrayList<ArrayList> list) {
MatrixCursor cursor = new MatrixCursor(columns, list.size());
for (ArrayList row : list) {
cursor.addRow(row);
}
return cursor;
}
/**
* This is simply a way to sneak a look at the protected mFrom() array. A more API-
* friendly way to do this would be to mock out a View and a ViewBinder and exercise
* it via those seams.
*/
private static class TestSimpleCursorAdapter extends SimpleCursorAdapter {
public TestSimpleCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
}
int[] getConvertedFrom() {
return mFrom;
}
int[] getTo() {
return mTo;
}
}
}