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 com.android.cts.stub.R; 20 21 import dalvik.annotation.TestLevel; 22 import dalvik.annotation.TestTargetClass; 23 import dalvik.annotation.TestTargetNew; 24 import dalvik.annotation.TestTargets; 25 import dalvik.annotation.ToBeFixed; 26 27 import org.xmlpull.v1.XmlPullParser; 28 29 import android.content.Context; 30 import android.database.DataSetObserver; 31 import android.graphics.Rect; 32 import android.os.Parcelable; 33 import android.test.ActivityInstrumentationTestCase2; 34 import android.test.UiThreadTest; 35 import android.util.AttributeSet; 36 import android.util.Xml; 37 import android.view.View; 38 import android.view.ViewGroup; 39 import android.widget.AbsSpinner; 40 import android.widget.AdapterView; 41 import android.widget.ArrayAdapter; 42 import android.widget.Gallery; 43 import android.widget.ImageView; 44 import android.widget.Spinner; 45 import android.widget.SpinnerAdapter; 46 47 @TestTargetClass(AbsSpinner.class) 48 public class AbsSpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutStubActivity> { 49 private Context mContext; 50 51 public AbsSpinnerTest() { 52 super("com.android.cts.stub", RelativeLayoutStubActivity.class); 53 } 54 55 @Override 56 protected void setUp() throws Exception { 57 super.setUp(); 58 mContext = getInstrumentation().getTargetContext(); 59 } 60 61 @ToBeFixed(bug="1448885", explanation="AbsSpinner is an abstract class and its abstract " + 62 "method layout(int, boolean) is package private, we can not extends it directly " + 63 "to test. So, we use its subclass Spinner and Gallery to test") 64 65 @TestTargets({ 66 @TestTargetNew( 67 level = TestLevel.COMPLETE, 68 notes = "", 69 method = "AbsSpinner", 70 args = {android.content.Context.class} 71 ), 72 @TestTargetNew( 73 level = TestLevel.COMPLETE, 74 notes = "", 75 method = "AbsSpinner", 76 args = {android.content.Context.class, android.util.AttributeSet.class} 77 ), 78 @TestTargetNew( 79 level = TestLevel.COMPLETE, 80 notes = "", 81 method = "AbsSpinner", 82 args = {android.content.Context.class, android.util.AttributeSet.class, int.class} 83 ) 84 }) 85 public void testConstructor() { 86 new Spinner(mContext); 87 88 new Spinner(mContext, null); 89 90 new Spinner(mContext, null, com.android.internal.R.attr.spinnerStyle); 91 92 new Gallery(mContext); 93 new Gallery(mContext, null); 94 new Gallery(mContext, null, 0); 95 96 XmlPullParser parser = mContext.getResources().getXml(R.layout.gallery_test); 97 AttributeSet attrs = Xml.asAttributeSet(parser); 98 new Gallery(mContext, attrs); 99 new Gallery(mContext, attrs, 0); 100 } 101 102 @TestTargets({ 103 @TestTargetNew( 104 level = TestLevel.COMPLETE, 105 notes = "", 106 method = "setSelection", 107 args = {int.class, boolean.class} 108 ) 109 }) 110 @ToBeFixed(bug = "1695243", explanation = "the javadoc for setSelection() is incomplete." + 111 "1. no description about the @param and @return.") 112 @UiThreadTest 113 /** 114 * Check points: 115 * 1. Jump to the specific item. 116 */ 117 public void testSetSelectionIntBoolean() { 118 AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1); 119 ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext, 120 com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item); 121 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 122 absSpinner.setAdapter(adapter); 123 assertEquals(0, absSpinner.getSelectedItemPosition()); 124 125 absSpinner.setSelection(1, true); 126 assertEquals(1, absSpinner.getSelectedItemPosition()); 127 128 absSpinner.setSelection(absSpinner.getCount() - 1, false); 129 assertEquals(absSpinner.getCount() - 1, absSpinner.getSelectedItemPosition()); 130 131 // The animation effect depends on implementation in AbsSpinner's subClass. 132 // It is not meaningful to check it. 133 } 134 135 @TestTargets({ 136 @TestTargetNew( 137 level = TestLevel.COMPLETE, 138 notes = "", 139 method = "setSelection", 140 args = {int.class} 141 ) 142 }) 143 @ToBeFixed(bug = "1695243", explanation = "the javadoc for setSelection() is incomplete." + 144 "1. no description about the @param and @return.") 145 @UiThreadTest 146 /** 147 * Check points: 148 * 1. the currently selected item should be the one which set using this method. 149 */ 150 public void testSetSelectionInt() { 151 AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1); 152 ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext, 153 com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item); 154 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 155 absSpinner.setAdapter(adapter); 156 assertEquals(0, absSpinner.getSelectedItemPosition()); 157 158 absSpinner.setSelection(1); 159 assertEquals(1, absSpinner.getSelectedItemPosition()); 160 161 absSpinner.setSelection(absSpinner.getCount() - 1); 162 assertEquals(absSpinner.getCount() - 1, absSpinner.getSelectedItemPosition()); 163 } 164 165 @TestTargets({ 166 @TestTargetNew( 167 level = TestLevel.COMPLETE, 168 notes = "", 169 method = "setAdapter", 170 args = {android.widget.SpinnerAdapter.class} 171 ), 172 @TestTargetNew( 173 level = TestLevel.COMPLETE, 174 notes = "", 175 method = "getAdapter", 176 args = {} 177 ) 178 }) 179 @ToBeFixed(bug = "1695243", explanation = "the javadoc for setAdapter() is incomplete." + 180 "1. no description about the situation that adapter is null.") 181 @UiThreadTest 182 /** 183 * Check points: 184 * 1. the adapter returned from getAdapter() should be the one specified using setAdapter(). 185 * 2. the adapter provides methods to transform spinner items based on their position 186 * relative to the selected item. 187 */ 188 public void testAccessAdapter() { 189 AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1); 190 ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext, 191 com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item); 192 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 193 194 absSpinner.setAdapter(adapter); 195 assertSame(adapter, absSpinner.getAdapter()); 196 assertEquals(adapter.getCount(), absSpinner.getCount()); 197 assertEquals(0, absSpinner.getSelectedItemPosition()); 198 assertEquals(adapter.getItemId(0), absSpinner.getSelectedItemId()); 199 absSpinner.setSelection(1); 200 assertEquals(1, absSpinner.getSelectedItemPosition()); 201 assertEquals(adapter.getItemId(1), absSpinner.getSelectedItemId()); 202 203 // issue 1695243, if adapter is null, NullPointerException will be thrown when do layout. 204 // There is neither limit in code nor description about it in javadoc. 205 } 206 207 @TestTargetNew( 208 level = TestLevel.COMPLETE, 209 notes = "", 210 method = "requestLayout", 211 args = {} 212 ) 213 public void testRequestLayout() { 214 AbsSpinner absSpinner = new Spinner(mContext); 215 absSpinner.layout(0, 0, 200, 300); 216 assertFalse(absSpinner.isLayoutRequested()); 217 218 absSpinner.requestLayout(); 219 assertTrue(absSpinner.isLayoutRequested()); 220 } 221 222 @TestTargetNew( 223 level = TestLevel.COMPLETE, 224 notes = "", 225 method = "getCount", 226 args = {} 227 ) 228 @UiThreadTest 229 /** 230 * Check points: 231 * 1. The value returned from getCount() equals the count of Adapter associated with 232 * this AdapterView. 233 */ 234 public void testGetCount() { 235 AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1); 236 237 ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(mContext, 238 com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item); 239 240 absSpinner.setAdapter(adapter1); 241 assertEquals(adapter1.getCount(), absSpinner.getCount()); 242 243 CharSequence anotherStringArray[] = { "another array string 1", "another array string 2" }; 244 ArrayAdapter<CharSequence> adapter2 = new ArrayAdapter<CharSequence>(mContext, 245 android.R.layout.simple_spinner_item, anotherStringArray); 246 247 absSpinner.setAdapter(adapter2); 248 assertEquals(anotherStringArray.length, absSpinner.getCount()); 249 } 250 251 @TestTargetNew( 252 level = TestLevel.COMPLETE, 253 notes = "", 254 method = "pointToPosition", 255 args = {int.class, int.class} 256 ) 257 /** 258 * Check points: 259 * 1. Should return the position of the item which contains the specified point. 260 * 2. Should return INVALID_POSITION if the point does not intersect an item 261 */ 262 public void testPointToPosition() { 263 AbsSpinner absSpinner = new Gallery(mContext); 264 MockSpinnerAdapter adapter = new MockSpinnerAdapter(); 265 assertEquals(AdapterView.INVALID_POSITION, absSpinner.pointToPosition(10, 10)); 266 267 adapter.setCount(3); 268 absSpinner.setAdapter(adapter); 269 absSpinner.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); 270 Rect rc = new Rect(0, 0, 100, 100); 271 Rect rcChild0 = new Rect(0, 0, 20, rc.bottom); 272 Rect rcChild1 = new Rect(rcChild0.right, 0, 70, rc.bottom); 273 Rect rcChild2 = new Rect(rcChild1.right, 0, rc.right, rc.bottom); 274 absSpinner.layout(rc.left, rc.top, rc.right, rc.bottom); 275 absSpinner.getChildAt(0).layout(rcChild0.left, rcChild0.top, 276 rcChild0.right, rcChild0.bottom); 277 absSpinner.getChildAt(1).layout(rcChild1.left, rcChild1.top, 278 rcChild1.right, rcChild1.bottom); 279 absSpinner.getChildAt(2).layout(rcChild2.left, rcChild2.top, 280 rcChild2.right, rcChild2.bottom); 281 282 assertEquals(AdapterView.INVALID_POSITION, absSpinner.pointToPosition(-1, -1)); 283 assertEquals(0, absSpinner.pointToPosition(rcChild0.left + 1, rc.bottom - 1)); 284 assertEquals(1, absSpinner.pointToPosition(rcChild1.left + 1, rc.bottom - 1)); 285 assertEquals(2, absSpinner.pointToPosition(rcChild2.left + 1, rc.bottom - 1)); 286 assertEquals(AdapterView.INVALID_POSITION, 287 absSpinner.pointToPosition(rc.right + 1, rc.bottom - 1)); 288 289 } 290 291 @TestTargetNew( 292 level = TestLevel.COMPLETE, 293 notes = "", 294 method = "getSelectedView", 295 args = {} 296 ) 297 /** 298 * Check points: 299 * 1. Should return the view corresponding to the currently selected item. 300 * 2. Should return null if nothing is selected. 301 */ 302 public void testGetSelectedView() { 303 AbsSpinner absSpinner = new Gallery(mContext); 304 MockSpinnerAdapter adapter = new MockSpinnerAdapter(); 305 assertNull(absSpinner.getSelectedView()); 306 307 absSpinner.setAdapter(adapter); 308 absSpinner.layout(0, 0, 20, 20); 309 assertSame(absSpinner.getChildAt(0), absSpinner.getSelectedView()); 310 311 absSpinner.setSelection(1, true); 312 assertSame(absSpinner.getChildAt(1), absSpinner.getSelectedView()); 313 314 } 315 316 @TestTargets({ 317 @TestTargetNew( 318 level = TestLevel.COMPLETE, 319 notes = "", 320 method = "onSaveInstanceState", 321 args = {} 322 ), 323 @TestTargetNew( 324 level = TestLevel.COMPLETE, 325 notes = "", 326 method = "onRestoreInstanceState", 327 args = {android.os.Parcelable.class} 328 ) 329 }) 330 @UiThreadTest 331 /** 332 * Check points: 333 * 1. the view's current state saved by onSaveInstanceState() should be correctly restored 334 * after onRestoreInstanceState(). 335 */ 336 public void testOnSaveAndRestoreInstanceState() { 337 AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1); 338 ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext, 339 com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item); 340 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 341 absSpinner.setAdapter(adapter); 342 assertEquals(0, absSpinner.getSelectedItemPosition()); 343 assertEquals(adapter.getItemId(0), absSpinner.getSelectedItemId()); 344 Parcelable parcelable = absSpinner.onSaveInstanceState(); 345 346 absSpinner.setSelection(1); 347 assertEquals(1, absSpinner.getSelectedItemPosition()); 348 assertEquals(adapter.getItemId(1), absSpinner.getSelectedItemId()); 349 350 absSpinner.onRestoreInstanceState(parcelable); 351 absSpinner.measure(View.MeasureSpec.EXACTLY, View.MeasureSpec.EXACTLY); 352 absSpinner.layout(absSpinner.getLeft(), absSpinner.getTop(), absSpinner.getRight(), 353 absSpinner.getBottom()); 354 assertEquals(0, absSpinner.getSelectedItemPosition()); 355 assertEquals(adapter.getItemId(0), absSpinner.getSelectedItemId()); 356 } 357 358 @TestTargetNew( 359 level = TestLevel.COMPLETE, 360 notes = "", 361 method = "generateDefaultLayoutParams", 362 args = {} 363 ) 364 @ToBeFixed(bug = "1448885", explanation = "AbsSpinner#generateDefaultLayoutParams() is" + 365 " protected method, we have to test it in MockSpinner which extends from" + 366 " AbsSpinner. class MockSpinner must implement the inherited abstract method" + 367 " AbsSpinner.layout(int, boolean), but cannot override it since it is not" + 368 " visible from MockSpinner. So we cannot test this method.") 369 public void testGenerateDefaultLayoutParams() { 370 // final MockSpinner absSpinner = new MockSpinner(mContext); 371 // LayoutParams layoutParams = (LayoutParams) absSpinner.generateDefaultLayoutParams(); 372 // assertEquals(LayoutParams.MATCH_PARENT, layoutParams.width); 373 // assertEquals(LayoutParams.WRAP_CONTENT, layoutParams.height); 374 } 375 376 @TestTargetNew( 377 level = TestLevel.NOT_NECESSARY, 378 notes = "Test onMeasure(int, int) function.", 379 method = "onMeasure", 380 args = {int.class, int.class} 381 ) 382 public void testOnMeasure() { 383 // onMeasure() is implementation details, do NOT test 384 } 385 386 /* 387 * The Mock class of SpinnerAdapter to be used in test. 388 */ 389 private class MockSpinnerAdapter implements SpinnerAdapter { 390 public static final int DEFAULT_COUNT = 1; 391 private int mCount = DEFAULT_COUNT; 392 393 public View getDropDownView(int position, View convertView, 394 ViewGroup parent) { 395 return null; 396 } 397 398 public int getCount() { 399 return mCount; 400 } 401 402 public void setCount(int count) { 403 mCount = count; 404 } 405 406 public Object getItem(int position) { 407 return null; 408 } 409 410 public long getItemId(int position) { 411 return position; 412 } 413 414 public int getItemViewType(int position) { 415 return 0; 416 } 417 418 public View getView(int position, View convertView, ViewGroup parent) { 419 return new ImageView(mContext); 420 } 421 422 public int getViewTypeCount() { 423 return 0; 424 } 425 426 public boolean hasStableIds() { 427 return false; 428 } 429 430 public boolean isEmpty() { 431 return false; 432 } 433 434 public void registerDataSetObserver(DataSetObserver observer) { 435 } 436 437 public void unregisterDataSetObserver(DataSetObserver observer) { 438 } 439 } 440 } 441