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; 18 19 import com.google.android.collect.Lists; 20 21 import android.content.Context; 22 import android.database.Cursor; 23 import android.database.MatrixCursor; 24 import android.test.AndroidTestCase; 25 import android.test.suitebuilder.annotation.SmallTest; 26 27 import java.util.ArrayList; 28 import java.util.Random; 29 30 /** 31 * This is a series of tests of basic API contracts for SimpleCursorAdapter. It is 32 * incomplete and can use work. 33 * 34 * NOTE: This contract holds for underlying cursor types too and these should 35 * be extracted into a set of tests that can be run on any descendant of CursorAdapter. 36 */ 37 public class SimpleCursorAdapterTest extends AndroidTestCase { 38 39 String[] mFrom; 40 int[] mTo; 41 int mLayout; 42 Context mContext; 43 44 ArrayList<ArrayList> mData2x2; 45 Cursor mCursor2x2; 46 47 /** 48 * Set up basic columns and cursor for the tests 49 */ 50 @Override 51 public void setUp() throws Exception { 52 super.setUp(); 53 54 // all the pieces needed for the various tests 55 mFrom = new String[]{"Column1", "Column2", "_id"}; 56 mTo = new int[]{com.android.internal.R.id.text1, com.android.internal.R.id.text2}; 57 mLayout = com.android.internal.R.layout.simple_list_item_2; 58 mContext = getContext(); 59 60 // raw data for building a basic test cursor 61 mData2x2 = createTestList(2, 2); 62 mCursor2x2 = createCursor(mFrom, mData2x2); 63 } 64 65 /** 66 * Borrowed from CursorWindowTest.java 67 */ 68 private ArrayList<ArrayList> createTestList(int rows, int cols) { 69 ArrayList<ArrayList> list = Lists.newArrayList(); 70 Random generator = new Random(); 71 72 for (int i = 0; i < rows; i++) { 73 ArrayList<Integer> col = Lists.newArrayList(); 74 list.add(col); 75 for (int j = 0; j < cols; j++) { 76 // generate random number 77 Integer r = generator.nextInt(); 78 col.add(r); 79 } 80 col.add(i); 81 } 82 return list; 83 } 84 85 /** 86 * Test creating with a live cursor 87 */ 88 @SmallTest 89 public void testCreateLive() { 90 SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo); 91 92 // Now see if we can pull 2 rows from the adapter 93 assertEquals(2, ca.getCount()); 94 } 95 96 /** 97 * Test creating with a null cursor 98 */ 99 @SmallTest 100 public void testCreateNull() { 101 SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, mFrom, mTo); 102 103 // The adapter should report zero rows 104 assertEquals(0, ca.getCount()); 105 } 106 107 /** 108 * Test changeCursor() with live cursor 109 */ 110 @SmallTest 111 public void testChangeCursorLive() { 112 SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo); 113 114 // Now see if we can pull 2 rows from the adapter 115 assertEquals(2, ca.getCount()); 116 117 // now put in a different cursor (5 rows) 118 ArrayList<ArrayList> data2 = createTestList(5, 2); 119 Cursor c2 = createCursor(mFrom, data2); 120 ca.changeCursor(c2); 121 122 // Now see if we can pull 5 rows from the adapter 123 assertEquals(5, ca.getCount()); 124 } 125 126 /** 127 * Test changeCursor() with null cursor 128 */ 129 @SmallTest 130 public void testChangeCursorNull() { 131 SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, mCursor2x2, mFrom, mTo); 132 133 // Now see if we can pull 2 rows from the adapter 134 assertEquals(2, ca.getCount()); 135 136 // now put in null 137 ca.changeCursor(null); 138 139 // The adapter should report zero rows 140 assertEquals(0, ca.getCount()); 141 } 142 143 /** 144 * Test changeCursor() with differing column layout. This confirms that the Adapter can 145 * deal with cursors that have the same essential data (as defined by the original mFrom 146 * array) but it's OK if the physical structure of the cursor changes (columns rearranged). 147 */ 148 @SmallTest 149 public void testChangeCursorColumns() { 150 TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2, 151 mFrom, mTo); 152 153 // check columns of original - mFrom and mTo should line up 154 int[] columns = ca.getConvertedFrom(); 155 assertEquals(columns[0], 0); 156 assertEquals(columns[1], 1); 157 158 // Now make a new cursor with similar data but rearrange the columns 159 String[] swappedFrom = new String[]{"Column2", "Column1", "_id"}; 160 Cursor c2 = createCursor(swappedFrom, mData2x2); 161 ca.changeCursor(c2); 162 assertEquals(2, ca.getCount()); 163 164 // check columns to see if rearrangement tracked (should be swapped now) 165 columns = ca.getConvertedFrom(); 166 assertEquals(columns[0], 1); 167 assertEquals(columns[1], 0); 168 } 169 170 /** 171 * Test that you can safely construct with a null cursor *and* null to/from arrays. 172 * This is new functionality added in 12/2008. 173 */ 174 @SmallTest 175 public void testNullConstructor() { 176 SimpleCursorAdapter ca = new SimpleCursorAdapter(mContext, mLayout, null, null, null); 177 assertEquals(0, ca.getCount()); 178 } 179 180 /** 181 * Test going from a null cursor to a non-null cursor *and* setting the to/from arrays 182 * This is new functionality added in 12/2008. 183 */ 184 @SmallTest 185 public void testChangeNullToMapped() { 186 TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, null, null, null); 187 assertEquals(0, ca.getCount()); 188 189 ca.changeCursorAndColumns(mCursor2x2, mFrom, mTo); 190 assertEquals(2, ca.getCount()); 191 192 // check columns of original - mFrom and mTo should line up 193 int[] columns = ca.getConvertedFrom(); 194 assertEquals(2, columns.length); 195 assertEquals(0, columns[0]); 196 assertEquals(1, columns[1]); 197 int[] viewIds = ca.getTo(); 198 assertEquals(2, viewIds.length); 199 assertEquals(com.android.internal.R.id.text1, viewIds[0]); 200 assertEquals(com.android.internal.R.id.text2, viewIds[1]); 201 } 202 203 /** 204 * Test going from one mapping to a different mapping 205 * This is new functionality added in 12/2008. 206 */ 207 @SmallTest 208 public void testChangeMapping() { 209 TestSimpleCursorAdapter ca = new TestSimpleCursorAdapter(mContext, mLayout, mCursor2x2, 210 mFrom, mTo); 211 assertEquals(2, ca.getCount()); 212 213 // Now create a new configuration with same cursor and just one column mapped 214 String[] singleFrom = new String[]{"Column1"}; 215 int[] singleTo = new int[]{com.android.internal.R.id.text1}; 216 ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo); 217 218 // And examine the results, make sure they're still consistent 219 int[] columns = ca.getConvertedFrom(); 220 assertEquals(1, columns.length); 221 assertEquals(0, columns[0]); 222 int[] viewIds = ca.getTo(); 223 assertEquals(1, viewIds.length); 224 assertEquals(com.android.internal.R.id.text1, viewIds[0]); 225 226 // And again, same cursor, different map 227 singleFrom = new String[]{"Column2"}; 228 singleTo = new int[]{com.android.internal.R.id.text2}; 229 ca.changeCursorAndColumns(mCursor2x2, singleFrom, singleTo); 230 231 // And examine the results, make sure they're still consistent 232 columns = ca.getConvertedFrom(); 233 assertEquals(1, columns.length); 234 assertEquals(1, columns[0]); 235 viewIds = ca.getTo(); 236 assertEquals(1, viewIds.length); 237 assertEquals(com.android.internal.R.id.text2, viewIds[0]); 238 } 239 240 private static MatrixCursor createCursor(String[] columns, ArrayList<ArrayList> list) { 241 MatrixCursor cursor = new MatrixCursor(columns, list.size()); 242 for (ArrayList row : list) { 243 cursor.addRow(row); 244 } 245 return cursor; 246 } 247 248 /** 249 * This is simply a way to sneak a look at the protected mFrom() array. A more API- 250 * friendly way to do this would be to mock out a View and a ViewBinder and exercise 251 * it via those seams. 252 */ 253 private static class TestSimpleCursorAdapter extends SimpleCursorAdapter { 254 255 public TestSimpleCursorAdapter(Context context, int layout, Cursor c, 256 String[] from, int[] to) { 257 super(context, layout, c, from, to); 258 } 259 260 int[] getConvertedFrom() { 261 return mFrom; 262 } 263 264 int[] getTo() { 265 return mTo; 266 } 267 } 268 } 269