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.cts; 18 19 import java.util.ArrayList; 20 import java.util.Comparator; 21 import java.util.List; 22 23 import android.database.DataSetObserver; 24 import android.test.AndroidTestCase; 25 import android.widget.ArrayAdapter; 26 import android.widget.Filter; 27 import android.widget.TextView; 28 29 import com.android.cts.stub.R; 30 31 32 public class ArrayAdapterTest extends AndroidTestCase { 33 34 private static final int INVALD_ID = -1; 35 private static final String STR1 = "string1"; 36 private static final String STR2 = "string2"; 37 private static final String STR3 = "string3"; 38 39 private ArrayAdapter<String> mArrayAdapter; 40 @Override 41 protected void setUp() throws Exception { 42 super.setUp(); 43 mArrayAdapter = new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line); 44 } 45 46 public void testConstructor() { 47 48 new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line); 49 new ArrayAdapter<String>(mContext, INVALD_ID);// invalid resource id 50 51 new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1); 52 new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, INVALD_ID); 53 54 new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, 55 new String[] {"str1", "str2"}); 56 57 new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1, 58 new String[] {"str1", "str2"}); 59 60 List<String> list = new ArrayList<String>(); 61 list.add(STR1); 62 list.add(STR2); 63 64 new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, list); 65 66 new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line, R.id.text1, list); 67 68 // invalid input 69 try { 70 new ArrayAdapter<String>(null, R.layout.simple_dropdown_item_1line); 71 fail("should throw NullPointerException"); 72 } catch (NullPointerException e) { 73 // expected exception 74 } 75 } 76 77 public void testDataChangeEvent() { 78 final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver(); 79 mArrayAdapter.registerDataSetObserver(mockDataSetObserver); 80 81 // enable automatically notifying. 82 mArrayAdapter.setNotifyOnChange(true); 83 assertEquals(0, mockDataSetObserver.getCalledOnChangedCount()); 84 mArrayAdapter.add(STR1); 85 assertEquals(1, mArrayAdapter.getCount()); 86 assertEquals(1, mockDataSetObserver.getCalledOnChangedCount()); 87 mArrayAdapter.add(STR2); 88 assertEquals(2, mArrayAdapter.getCount()); 89 assertEquals(2, mockDataSetObserver.getCalledOnChangedCount()); 90 91 // reset data 92 mArrayAdapter.clear(); 93 // clear notify changed 94 assertEquals(3, mockDataSetObserver.getCalledOnChangedCount()); 95 assertEquals(0, mArrayAdapter.getCount()); 96 // if empty before, clear also notify changed 97 mArrayAdapter.clear(); 98 assertEquals(4, mockDataSetObserver.getCalledOnChangedCount()); 99 mockDataSetObserver.clearCount(); 100 assertEquals(0, mockDataSetObserver.getCalledOnChangedCount()); 101 102 // disable auto notify 103 mArrayAdapter.setNotifyOnChange(false); 104 105 mArrayAdapter.add(STR3); 106 assertEquals(1, mArrayAdapter.getCount()); 107 assertEquals(0, mockDataSetObserver.getCalledOnChangedCount()); 108 109 // manually notify 110 mArrayAdapter.notifyDataSetChanged(); 111 assertEquals(1, mockDataSetObserver.getCalledOnChangedCount()); 112 // no data changed, but force notify 113 mArrayAdapter.notifyDataSetChanged(); 114 assertEquals(2, mockDataSetObserver.getCalledOnChangedCount()); 115 // once called notify, auto notify enabled 116 mArrayAdapter.add(STR3); 117 assertEquals(3, mockDataSetObserver.getCalledOnChangedCount()); 118 } 119 120 public void testAccessView() { 121 final TextView textView = new TextView(mContext); 122 textView.setText(STR3); 123 124 assertNotNull(mArrayAdapter.getContext()); 125 126 assertEquals(0, mArrayAdapter.getCount()); 127 128 mArrayAdapter.add(STR1); 129 mArrayAdapter.add(STR2); 130 mArrayAdapter.add(STR3); 131 132 assertEquals(3, mArrayAdapter.getCount()); 133 134 assertEquals(STR1, ((TextView) mArrayAdapter.getView(0, null, null)).getText()); 135 assertEquals(STR2, ((TextView) mArrayAdapter.getView(1, null, null)).getText()); 136 assertEquals(STR3, ((TextView) mArrayAdapter.getDropDownView(2, null, null)).getText()); 137 138 assertEquals(STR3, textView.getText()); 139 assertSame(textView, mArrayAdapter.getView(0, textView, null)); 140 assertSame(textView, mArrayAdapter.getDropDownView(0, textView, null)); 141 assertEquals(STR1, textView.getText()); 142 143 try { 144 assertEquals(textView, mArrayAdapter.getView(-1, textView, null)); 145 fail("should throw IndexOutOfBoundsException"); 146 } catch (IndexOutOfBoundsException e) { 147 } 148 149 try { 150 assertEquals(textView, mArrayAdapter.getDropDownView(-1, textView, null)); 151 fail("should throw IndexOutOfBoundsException"); 152 } catch (IndexOutOfBoundsException e) { 153 } 154 155 try { 156 assertEquals(textView, 157 mArrayAdapter.getView(mArrayAdapter.getCount(), textView, null)); 158 fail("should throw IndexOutOfBoundsException"); 159 } catch (IndexOutOfBoundsException e) { 160 } 161 162 try { 163 assertEquals(textView, 164 mArrayAdapter.getDropDownView(mArrayAdapter.getCount(), textView, null)); 165 fail("should throw IndexOutOfBoundsException"); 166 } catch (IndexOutOfBoundsException e) { 167 } 168 } 169 170 public void testGetFilter() { 171 Filter filter = mArrayAdapter.getFilter(); 172 173 assertNotNull(mArrayAdapter.getFilter()); 174 assertSame(filter, mArrayAdapter.getFilter()); 175 } 176 177 /** 178 * just simple change the resource id from which the drop view inflate from 179 * we set a xml that not contain a textview, so exception should throw to lete us know 180 * sucessfully change the dropdown xml, but should not affect the normal view by getview 181 */ 182 public void testSetDropDownViewResouce() { 183 mArrayAdapter.add(STR1); 184 185 mArrayAdapter.getDropDownView(0, null, null); 186 187 mArrayAdapter.setDropDownViewResource(R.layout.tabhost_layout); 188 // getview is ok 189 mArrayAdapter.getView(0, null, null); 190 // getDropDownView error for it changed 191 try { 192 mArrayAdapter.getDropDownView(0, null, null); 193 fail("should throw IllegalStateException"); 194 } catch (IllegalStateException e) { 195 // expected exception 196 } 197 198 mArrayAdapter.setDropDownViewResource(INVALD_ID); 199 } 200 201 /** 202 * insert the item to the specific position, notify data changed 203 * check -1, normal, > count 204 */ 205 public void testInsert() { 206 mArrayAdapter.setNotifyOnChange(true); 207 final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver(); 208 mArrayAdapter.registerDataSetObserver(mockDataSetObserver); 209 210 mArrayAdapter.insert(STR1, 0); 211 assertEquals(1, mArrayAdapter.getCount()); 212 assertEquals(0, mArrayAdapter.getPosition(STR1)); 213 assertEquals(1, mockDataSetObserver.getCalledOnChangedCount()); 214 215 mArrayAdapter.insert(STR2, 0); 216 assertEquals(2, mArrayAdapter.getCount()); 217 assertEquals(1, mArrayAdapter.getPosition(STR1)); 218 assertEquals(0, mArrayAdapter.getPosition(STR2)); 219 220 mArrayAdapter.insert(STR3, mArrayAdapter.getCount()); 221 assertEquals(mArrayAdapter.getCount() - 1, mArrayAdapter.getPosition(STR3)); 222 223 mArrayAdapter.insert(null, 0); 224 assertEquals(0, mArrayAdapter.getPosition(null)); 225 226 try { 227 mArrayAdapter.insert(STR1, -1); 228 fail("should throw IndexOutOfBoundsException"); 229 } catch (IndexOutOfBoundsException e) { 230 // expected exception 231 } 232 233 try { 234 mArrayAdapter.insert(STR1, mArrayAdapter.getCount() + 1); 235 fail("should throw IndexOutOfBoundsException"); 236 } catch (IndexOutOfBoundsException e) { 237 // expected exception 238 } 239 } 240 241 /** 242 * return the given position obj 243 * test range: -1, normal, > count 244 */ 245 public void testGetItem() { 246 mArrayAdapter.add(STR1); 247 mArrayAdapter.add(STR2); 248 mArrayAdapter.add(STR3); 249 250 assertSame(STR1, mArrayAdapter.getItem(0)); 251 assertSame(STR2, mArrayAdapter.getItem(1)); 252 assertSame(STR3, mArrayAdapter.getItem(2)); 253 254 // test invalid input 255 try { 256 mArrayAdapter.getItem(-1); 257 fail("should throw IndexOutOfBoundsException"); 258 } catch (IndexOutOfBoundsException e) { 259 // expected exception 260 } 261 262 try { 263 mArrayAdapter.getItem(mArrayAdapter.getCount()); 264 fail("should throw IndexOutOfBoundsException"); 265 } catch (IndexOutOfBoundsException e) { 266 // expected exception 267 } 268 } 269 270 /** 271 * just return the given position 272 */ 273 public void testGetItemId() { 274 mArrayAdapter.add(STR1); 275 mArrayAdapter.add(STR2); 276 mArrayAdapter.add(STR3); 277 278 assertEquals(0, mArrayAdapter.getItemId(0)); 279 assertEquals(1, mArrayAdapter.getItemId(1)); 280 assertEquals(2, mArrayAdapter.getItemId(2)); 281 282 // test invalid input 283 assertEquals(-1, mArrayAdapter.getItemId(-1)); 284 assertEquals(mArrayAdapter.getCount(), 285 mArrayAdapter.getItemId(mArrayAdapter.getCount())); 286 } 287 288 /* 289 * return the obj position that in the array, if there are same objs, return the first one 290 */ 291 public void testGetPosition() { 292 mArrayAdapter.add(STR1); 293 mArrayAdapter.add(STR2); 294 mArrayAdapter.add(STR1); 295 296 assertEquals(0, mArrayAdapter.getPosition(STR1)); 297 assertEquals(1, mArrayAdapter.getPosition(STR2)); 298 // return the first one if same obj exsit 299 assertEquals(0, mArrayAdapter.getPosition(STR1)); 300 301 assertEquals(-1, mArrayAdapter.getPosition(STR3)); 302 303 // test invalid input 304 assertEquals(-1, mArrayAdapter.getPosition(null)); 305 } 306 307 /** 308 * Removes the specified object from the array. notify data changed 309 * remove first one if duplicated string in the array 310 */ 311 public void testRemove() { 312 final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver(); 313 mArrayAdapter.registerDataSetObserver(mockDataSetObserver); 314 mArrayAdapter.setNotifyOnChange(true); 315 316 // remove the not exist one 317 assertEquals(0, mArrayAdapter.getCount()); 318 assertEquals(0, mockDataSetObserver.getCalledOnChangedCount()); 319 // remove the item not exist also notify change 320 mArrayAdapter.remove(STR1); 321 assertEquals(1, mockDataSetObserver.getCalledOnChangedCount()); 322 323 mArrayAdapter.add(STR1); 324 mArrayAdapter.add(STR2); 325 mArrayAdapter.add(STR3); 326 mArrayAdapter.add(STR2); 327 mockDataSetObserver.clearCount(); 328 assertEquals(0, mockDataSetObserver.getCalledOnChangedCount()); 329 assertEquals(4, mArrayAdapter.getCount()); 330 331 mArrayAdapter.remove(STR1); 332 assertEquals(3, mArrayAdapter.getCount()); 333 assertEquals(-1, mArrayAdapter.getPosition(STR1)); 334 assertEquals(0, mArrayAdapter.getPosition(STR2)); 335 assertEquals(1, mArrayAdapter.getPosition(STR3)); 336 assertEquals(1, mockDataSetObserver.getCalledOnChangedCount()); 337 338 mArrayAdapter.remove(STR2); 339 assertEquals(2, mArrayAdapter.getCount()); 340 // remove the first one if dumplicated 341 assertEquals(1, mArrayAdapter.getPosition(STR2)); 342 assertEquals(0, mArrayAdapter.getPosition(STR3)); 343 344 mArrayAdapter.remove(STR2); 345 assertEquals(1, mArrayAdapter.getCount()); 346 assertEquals(-1, mArrayAdapter.getPosition(STR2)); 347 assertEquals(0, mArrayAdapter.getPosition(STR3)); 348 } 349 350 /* 351 * Creates a new ArrayAdapter from external resources. The content of the array is 352 * obtained through {@link android.content.res.Resources#getTextArray(int)}. 353 */ 354 public void testCreateFromResource() { 355 ArrayAdapter.createFromResource(mContext, R.array.string, R.layout.simple_spinner_item); 356 357 // invalid input 358 try { 359 ArrayAdapter.createFromResource(null, R.array.string, R.layout.simple_spinner_item); 360 fail("should throw NullPointerException"); 361 } catch (NullPointerException e) { 362 // expected exception 363 } 364 365 try { 366 ArrayAdapter.createFromResource(mContext, INVALD_ID, R.layout.simple_spinner_item); 367 fail("should throw NullPointerException"); 368 } catch (NullPointerException e) { 369 // expected exception 370 } 371 372 ArrayAdapter.createFromResource(mContext, R.array.string, INVALD_ID); 373 } 374 375 public void testSort() { 376 final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver(); 377 mArrayAdapter.registerDataSetObserver(mockDataSetObserver); 378 mArrayAdapter.setNotifyOnChange(true); 379 assertEquals(0, mockDataSetObserver.getCalledOnChangedCount()); 380 381 mArrayAdapter.sort( new Comparator<String>() { 382 public int compare(String o1, String o2) { 383 return 0; 384 } 385 }); 386 assertEquals(1, mockDataSetObserver.getCalledOnChangedCount()); 387 388 mArrayAdapter.sort(null); 389 assertEquals(2, mockDataSetObserver.getCalledOnChangedCount()); 390 } 391 392 /** 393 * insert multiple items via add, notify data changed 394 * check count and content 395 */ 396 public void testAdd() { 397 mArrayAdapter.setNotifyOnChange(true); 398 final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver(); 399 mArrayAdapter.registerDataSetObserver(mockDataSetObserver); 400 401 mArrayAdapter.clear(); 402 assertEquals(mArrayAdapter.getCount(), 0); 403 404 mArrayAdapter.add("testing"); 405 mArrayAdapter.add("android"); 406 assertEquals(mArrayAdapter.getCount(), 2); 407 assertEquals(mArrayAdapter.getItem(0), "testing"); 408 assertEquals(mArrayAdapter.getItem(1), "android"); 409 } 410 411 /** 412 * insert multiple items via addAll, notify data changed 413 * check count and content 414 */ 415 public void testAddAllCollection() { 416 mArrayAdapter.setNotifyOnChange(true); 417 final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver(); 418 mArrayAdapter.registerDataSetObserver(mockDataSetObserver); 419 420 List<String> list = new ArrayList<String>(); 421 list.add(""); 422 list.add("hello"); 423 list.add("android"); 424 list.add("!"); 425 426 mArrayAdapter.clear(); 427 assertEquals(mArrayAdapter.getCount(), 0); 428 429 mArrayAdapter.addAll(list); 430 assertEquals(mArrayAdapter.getCount(), list.size()); 431 432 assertEquals(mArrayAdapter.getItem(0), list.get(0)); 433 assertEquals(mArrayAdapter.getItem(1), list.get(1)); 434 assertEquals(mArrayAdapter.getItem(2), list.get(2)); 435 assertEquals(mArrayAdapter.getItem(3), list.get(3)); 436 } 437 438 /** 439 * insert multiple items via addAll, notify data changed 440 * check count and content 441 */ 442 public void testAddAllParams() { 443 mArrayAdapter.setNotifyOnChange(true); 444 final MockDataSetObserver mockDataSetObserver = new MockDataSetObserver(); 445 mArrayAdapter.registerDataSetObserver(mockDataSetObserver); 446 447 mArrayAdapter.clear(); 448 assertEquals(mArrayAdapter.getCount(), 0); 449 450 mArrayAdapter.addAll("this", "is", "a", "unit", "test"); 451 assertEquals(mArrayAdapter.getCount(), 5); 452 assertEquals(mArrayAdapter.getItem(0), "this"); 453 assertEquals(mArrayAdapter.getItem(1), "is"); 454 assertEquals(mArrayAdapter.getItem(2), "a"); 455 assertEquals(mArrayAdapter.getItem(3), "unit"); 456 assertEquals(mArrayAdapter.getItem(4), "test"); 457 } 458 459 private static class MockDataSetObserver extends DataSetObserver { 460 461 private int mCalledOnChangedCount; 462 private int mOnCalledInvalidatedCount; 463 464 public MockDataSetObserver() { 465 clearCount(); 466 } 467 468 public int getCalledOnChangedCount() { 469 return mCalledOnChangedCount; 470 } 471 472 public int getCalledOnInvalidatedCount() { 473 return mOnCalledInvalidatedCount; 474 } 475 476 public void clearCount() { 477 mCalledOnChangedCount = 0; 478 mOnCalledInvalidatedCount = 0; 479 } 480 481 public void onChanged() { 482 mCalledOnChangedCount++; 483 } 484 485 public void onInvalidated() { 486 mOnCalledInvalidatedCount++; 487 } 488 } 489 } 490