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 static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertSame; 22 import static org.junit.Assert.assertTrue; 23 import static org.mockito.Mockito.atLeastOnce; 24 import static org.mockito.Mockito.reset; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 29 import android.app.Activity; 30 import android.app.Instrumentation; 31 import android.content.Context; 32 import android.content.res.ColorStateList; 33 import android.graphics.BlendMode; 34 import android.graphics.Color; 35 import android.graphics.PorterDuff; 36 import android.graphics.drawable.ColorDrawable; 37 import android.graphics.drawable.Drawable; 38 import android.util.AttributeSet; 39 import android.view.KeyEvent; 40 import android.widget.AbsSeekBar; 41 import android.widget.SeekBar; 42 import android.widget.cts.util.TestUtils; 43 44 import androidx.test.InstrumentationRegistry; 45 import androidx.test.annotation.UiThreadTest; 46 import androidx.test.filters.SmallTest; 47 import androidx.test.rule.ActivityTestRule; 48 import androidx.test.runner.AndroidJUnit4; 49 50 import com.android.compatibility.common.util.PollingCheck; 51 import com.android.compatibility.common.util.WidgetTestUtils; 52 53 import org.junit.Before; 54 import org.junit.Rule; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 import org.mockito.ArgumentCaptor; 58 59 import java.util.List; 60 61 /** 62 * Test {@link AbsSeekBar}. 63 */ 64 @SmallTest 65 @RunWith(AndroidJUnit4.class) 66 public class AbsSeekBarTest { 67 private Instrumentation mInstrumentation; 68 private Activity mActivity; 69 70 @Rule 71 public ActivityTestRule<AbsSeekBarCtsActivity> mActivityRule = 72 new ActivityTestRule<>(AbsSeekBarCtsActivity.class); 73 74 @Before setup()75 public void setup() { 76 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 77 mActivity = mActivityRule.getActivity(); 78 } 79 80 @Test testConstructor()81 public void testConstructor() { 82 new MyAbsSeekBar(mActivity); 83 84 new MyAbsSeekBar(mActivity, null); 85 86 new MyAbsSeekBar(mActivity, null, android.R.attr.progressBarStyle); 87 88 new MyAbsSeekBar(mActivity, null, 0, android.R.style.Widget_Material_Light_ProgressBar); 89 } 90 91 @Test testAccessThumbOffset()92 public void testAccessThumbOffset() { 93 AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 94 final int positive = 5; 95 final int negative = -5; 96 final int zero = 0; 97 98 myAbsSeekBar.setThumbOffset(positive); 99 assertEquals(positive, myAbsSeekBar.getThumbOffset()); 100 101 myAbsSeekBar.setThumbOffset(zero); 102 assertEquals(zero, myAbsSeekBar.getThumbOffset()); 103 104 myAbsSeekBar.setThumbOffset(negative); 105 assertEquals(negative, myAbsSeekBar.getThumbOffset()); 106 } 107 108 @Test testAccessThumb()109 public void testAccessThumb() { 110 // Both are pointing to the same object. This works around current limitation in CTS 111 // coverage report tool for properly reporting coverage of base class method calls. 112 final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 113 final AbsSeekBar absSeekBar = myAbsSeekBar; 114 115 Drawable drawable1 = mActivity.getDrawable(R.drawable.scenery); 116 Drawable drawable2 = mActivity.getDrawable(R.drawable.pass); 117 118 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 119 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 120 121 absSeekBar.setThumb(drawable1); 122 assertSame(drawable1, absSeekBar.getThumb()); 123 assertTrue(myAbsSeekBar.verifyDrawable(drawable1)); 124 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 125 126 absSeekBar.setThumb(drawable2); 127 assertSame(drawable2, absSeekBar.getThumb()); 128 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 129 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 130 } 131 132 @Test testAccessTickMark()133 public void testAccessTickMark() { 134 // Both are pointing to the same object. This works around current limitation in CTS 135 // coverage report tool for properly reporting coverage of base class method calls. 136 final MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 137 final AbsSeekBar absSeekBar = myAbsSeekBar; 138 139 Drawable drawable1 = mActivity.getDrawable(R.drawable.black); 140 Drawable drawable2 = mActivity.getDrawable(R.drawable.black); 141 142 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 143 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 144 145 absSeekBar.setTickMark(drawable1); 146 assertSame(drawable1, absSeekBar.getTickMark()); 147 assertTrue(myAbsSeekBar.verifyDrawable(drawable1)); 148 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 149 150 absSeekBar.setTickMark(drawable2); 151 assertSame(drawable2, absSeekBar.getTickMark()); 152 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 153 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 154 } 155 156 @Test testDrawableStateChanged()157 public void testDrawableStateChanged() { 158 MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 159 Drawable mockProgressDrawable = spy(new ColorDrawable(Color.YELLOW)); 160 myAbsSeekBar.setProgressDrawable(mockProgressDrawable); 161 162 ArgumentCaptor<Integer> alphaCaptor = ArgumentCaptor.forClass(Integer.class); 163 myAbsSeekBar.setEnabled(false); 164 myAbsSeekBar.drawableStateChanged(); 165 verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture()); 166 // Verify that the last call to setAlpha was with argument 0x00 167 List<Integer> alphaCaptures = alphaCaptor.getAllValues(); 168 assertTrue(!alphaCaptures.isEmpty()); 169 assertEquals(Integer.valueOf(0x00), alphaCaptures.get(alphaCaptures.size() - 1)); 170 171 alphaCaptor = ArgumentCaptor.forClass(Integer.class); 172 myAbsSeekBar.setEnabled(true); 173 myAbsSeekBar.drawableStateChanged(); 174 verify(mockProgressDrawable, atLeastOnce()).setAlpha(alphaCaptor.capture()); 175 // Verify that the last call to setAlpha was with argument 0xFF 176 alphaCaptures = alphaCaptor.getAllValues(); 177 assertTrue(!alphaCaptures.isEmpty()); 178 assertEquals(Integer.valueOf(0xFF), alphaCaptures.get(alphaCaptures.size() - 1)); 179 } 180 181 @Test testVerifyDrawable()182 public void testVerifyDrawable() { 183 MyAbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity); 184 Drawable drawable1 = mActivity.getDrawable(R.drawable.scenery); 185 Drawable drawable2 = mActivity.getDrawable(R.drawable.pass); 186 Drawable drawable3 = mActivity.getDrawable(R.drawable.blue); 187 Drawable drawable4 = mActivity.getDrawable(R.drawable.black); 188 189 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 190 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 191 assertFalse(myAbsSeekBar.verifyDrawable(drawable3)); 192 assertFalse(myAbsSeekBar.verifyDrawable(drawable4)); 193 194 myAbsSeekBar.setThumb(drawable1); 195 assertTrue(myAbsSeekBar.verifyDrawable(drawable1)); 196 assertFalse(myAbsSeekBar.verifyDrawable(drawable2)); 197 assertFalse(myAbsSeekBar.verifyDrawable(drawable3)); 198 assertFalse(myAbsSeekBar.verifyDrawable(drawable4)); 199 200 myAbsSeekBar.setThumb(drawable2); 201 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 202 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 203 assertFalse(myAbsSeekBar.verifyDrawable(drawable3)); 204 assertFalse(myAbsSeekBar.verifyDrawable(drawable4)); 205 206 myAbsSeekBar.setBackgroundDrawable(drawable2); 207 myAbsSeekBar.setProgressDrawable(drawable3); 208 myAbsSeekBar.setIndeterminateDrawable(drawable4); 209 assertFalse(myAbsSeekBar.verifyDrawable(drawable1)); 210 assertTrue(myAbsSeekBar.verifyDrawable(drawable2)); 211 assertTrue(myAbsSeekBar.verifyDrawable(drawable3)); 212 assertTrue(myAbsSeekBar.verifyDrawable(drawable4)); 213 } 214 215 @Test testAccessKeyProgressIncrement()216 public void testAccessKeyProgressIncrement() throws Throwable { 217 // AbsSeekBar is an abstract class, use its subclass: SeekBar to do this test. 218 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(), 219 () -> mActivity.setContentView(R.layout.seekbar_layout)); 220 221 final SeekBar seekBar = (SeekBar) mActivity.findViewById(R.id.seekBar); 222 final int keyProgressIncrement = 2; 223 mActivityRule.runOnUiThread(() -> { 224 seekBar.setKeyProgressIncrement(keyProgressIncrement); 225 seekBar.setFocusable(true); 226 seekBar.requestFocus(); 227 }); 228 PollingCheck.waitFor(1000, seekBar::hasWindowFocus); 229 assertEquals(keyProgressIncrement, seekBar.getKeyProgressIncrement()); 230 231 int oldProgress = seekBar.getProgress(); 232 KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT); 233 mInstrumentation.sendKeySync(keyEvent); 234 assertEquals(oldProgress + keyProgressIncrement, seekBar.getProgress()); 235 oldProgress = seekBar.getProgress(); 236 keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT); 237 mInstrumentation.sendKeySync(keyEvent); 238 assertEquals(oldProgress - keyProgressIncrement, seekBar.getProgress()); 239 } 240 241 @Test testAccessMax()242 public void testAccessMax() { 243 AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar); 244 245 int progress = 10; 246 myAbsSeekBar.setProgress(progress); 247 int max = progress + 1; 248 myAbsSeekBar.setMax(max); 249 assertEquals(max, myAbsSeekBar.getMax()); 250 assertEquals(progress, myAbsSeekBar.getProgress()); 251 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 252 253 max = progress - 1; 254 myAbsSeekBar.setMax(max); 255 assertEquals(max, myAbsSeekBar.getMax()); 256 assertEquals(max, myAbsSeekBar.getProgress()); 257 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 258 259 int keyProgressIncrement = 10; 260 myAbsSeekBar.setKeyProgressIncrement(keyProgressIncrement); 261 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 262 max = (keyProgressIncrement - 1) * 20; 263 myAbsSeekBar.setMax(max); 264 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 265 max = (keyProgressIncrement + 1) * 20; 266 myAbsSeekBar.setMax(max); 267 assertEquals(keyProgressIncrement + 1, myAbsSeekBar.getKeyProgressIncrement()); 268 } 269 270 @Test testAccessMin()271 public void testAccessMin() { 272 AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar); 273 274 int progress = -5; 275 int min = progress - 1; 276 int max = 5; 277 myAbsSeekBar.setMax(max); 278 myAbsSeekBar.setMin(min); 279 myAbsSeekBar.setProgress(progress); 280 assertEquals(min, myAbsSeekBar.getMin()); 281 assertEquals(progress, myAbsSeekBar.getProgress()); 282 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 283 284 min = progress + 1; 285 myAbsSeekBar.setMin(min); 286 assertEquals(min, myAbsSeekBar.getMin()); 287 assertEquals(min, myAbsSeekBar.getProgress()); 288 assertEquals(1, myAbsSeekBar.getKeyProgressIncrement()); 289 290 int keyProgressIncrement = 10; 291 myAbsSeekBar.setKeyProgressIncrement(keyProgressIncrement); 292 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 293 max = (keyProgressIncrement - 1) * 10; 294 min = -1 * keyProgressIncrement * 10; 295 myAbsSeekBar.setMax(max); 296 myAbsSeekBar.setMin(min); 297 assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement()); 298 299 max += 20; 300 myAbsSeekBar.setMax(max); 301 assertEquals(keyProgressIncrement + 1, myAbsSeekBar.getKeyProgressIncrement()); 302 assertEquals(min, myAbsSeekBar.getMin()); 303 assertEquals(max, myAbsSeekBar.getMax()); 304 } 305 306 @UiThreadTest 307 @Test testThumbTint()308 public void testThumbTint() { 309 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.thumb_tint); 310 311 assertEquals("Thumb tint inflated correctly", 312 Color.WHITE, inflatedView.getThumbTintList().getDefaultColor()); 313 assertEquals("Thumb tint mode inflated correctly", 314 PorterDuff.Mode.SRC_OVER, inflatedView.getThumbTintMode()); 315 316 Drawable mockThumb = spy(new ColorDrawable(Color.BLUE)); 317 318 inflatedView.setThumb(mockThumb); 319 verify(mockThumb, times(1)).setTintList(TestUtils.colorStateListOf(Color.WHITE)); 320 321 reset(mockThumb); 322 inflatedView.setThumbTintList(ColorStateList.valueOf(Color.RED)); 323 verify(mockThumb, times(1)) 324 .setTintList(TestUtils.colorStateListOf(Color.RED)); 325 326 inflatedView.setThumbTintMode(PorterDuff.Mode.DST_ATOP); 327 assertEquals("Thumb tint mode changed correctly", 328 PorterDuff.Mode.DST_ATOP, inflatedView.getThumbTintMode()); 329 330 reset(mockThumb); 331 inflatedView.setThumb(null); 332 inflatedView.setThumb(mockThumb); 333 verify(mockThumb, times(1)) 334 .setTintList(TestUtils.colorStateListOf(Color.RED)); 335 } 336 337 @UiThreadTest 338 @Test testThumbTintBlendMode()339 public void testThumbTintBlendMode() { 340 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.thumb_tint); 341 342 assertEquals("Thumb tint inflated correctly", 343 Color.WHITE, inflatedView.getThumbTintList().getDefaultColor()); 344 assertEquals("Thumb tint mode inflated correctly", 345 BlendMode.SRC_OVER, inflatedView.getThumbTintBlendMode()); 346 347 Drawable mockThumb = spy(new ColorDrawable(Color.BLUE)); 348 349 inflatedView.setThumb(mockThumb); 350 verify(mockThumb, times(1)) 351 .setTintList(TestUtils.colorStateListOf(Color.WHITE)); 352 353 reset(mockThumb); 354 inflatedView.setThumbTintList(ColorStateList.valueOf(Color.RED)); 355 verify(mockThumb, times(1)) 356 .setTintList(TestUtils.colorStateListOf(Color.RED)); 357 358 inflatedView.setThumbTintBlendMode(BlendMode.DST_ATOP); 359 assertEquals("Thumb tint mode changed correctly", 360 BlendMode.DST_ATOP, inflatedView.getThumbTintBlendMode()); 361 362 reset(mockThumb); 363 inflatedView.setThumb(null); 364 inflatedView.setThumb(mockThumb); 365 verify(mockThumb, times(1)) 366 .setTintList(TestUtils.colorStateListOf(Color.RED)); 367 } 368 369 @UiThreadTest 370 @Test testTickMarkTint()371 public void testTickMarkTint() { 372 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint); 373 374 assertEquals("TickMark tint inflated correctly", 375 Color.WHITE, inflatedView.getTickMarkTintList().getDefaultColor()); 376 assertEquals("TickMark tint mode inflated correctly", 377 PorterDuff.Mode.SRC_OVER, inflatedView.getTickMarkTintMode()); 378 379 Drawable mockTickMark = spy(new ColorDrawable(Color.BLUE)); 380 381 inflatedView.setTickMark(mockTickMark); 382 verify(mockTickMark, times(1)) 383 .setTintList(TestUtils.colorStateListOf(Color.WHITE)); 384 385 reset(mockTickMark); 386 inflatedView.setTickMarkTintList(ColorStateList.valueOf(Color.RED)); 387 verify(mockTickMark, times(1)) 388 .setTintList(TestUtils.colorStateListOf(Color.RED)); 389 390 inflatedView.setTickMarkTintMode(PorterDuff.Mode.DARKEN); 391 assertEquals("TickMark tint mode changed correctly", 392 PorterDuff.Mode.DARKEN, inflatedView.getTickMarkTintMode()); 393 394 reset(mockTickMark); 395 inflatedView.setTickMark(null); 396 inflatedView.setTickMark(mockTickMark); 397 verify(mockTickMark, times(1)) 398 .setTintList(TestUtils.colorStateListOf(Color.RED)); 399 } 400 401 @UiThreadTest 402 @Test testTickMarkTintBlendMode()403 public void testTickMarkTintBlendMode() { 404 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint); 405 406 assertEquals("TickMark tint inflated correctly", 407 Color.WHITE, inflatedView.getTickMarkTintList().getDefaultColor()); 408 assertEquals("TickMark tint mode inflated correctly", 409 BlendMode.SRC_OVER, inflatedView.getTickMarkTintBlendMode()); 410 411 Drawable mockTickMark = spy(new ColorDrawable(Color.BLUE)); 412 413 inflatedView.setTickMark(mockTickMark); 414 verify(mockTickMark, times(1)) 415 .setTintList(TestUtils.colorStateListOf(Color.WHITE)); 416 417 reset(mockTickMark); 418 inflatedView.setTickMarkTintList(ColorStateList.valueOf(Color.RED)); 419 verify(mockTickMark, times(1)) 420 .setTintList(TestUtils.colorStateListOf(Color.RED)); 421 422 inflatedView.setTickMarkTintBlendMode(BlendMode.DARKEN); 423 assertEquals("TickMark tint mode changed correctly", 424 BlendMode.DARKEN, inflatedView.getTickMarkTintBlendMode()); 425 426 reset(mockTickMark); 427 inflatedView.setTickMark(null); 428 inflatedView.setTickMark(mockTickMark); 429 verify(mockTickMark, times(1)) 430 .setTintList(TestUtils.colorStateListOf(Color.RED)); 431 } 432 433 @Test testAccessSplitTrack()434 public void testAccessSplitTrack() throws Throwable { 435 AbsSeekBar inflatedView = (AbsSeekBar) mActivity.findViewById(R.id.tick_mark_tint); 436 437 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, inflatedView, 438 () -> inflatedView.setSplitTrack(true)); 439 assertTrue(inflatedView.getSplitTrack()); 440 441 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, inflatedView, 442 () -> inflatedView.setSplitTrack(false)); 443 assertFalse(inflatedView.getSplitTrack()); 444 } 445 446 private static class MyAbsSeekBar extends AbsSeekBar { MyAbsSeekBar(Context context)447 public MyAbsSeekBar(Context context) { 448 super(context); 449 } 450 MyAbsSeekBar(Context context, AttributeSet attrs)451 public MyAbsSeekBar(Context context, AttributeSet attrs) { 452 super(context, attrs); 453 } 454 MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle)455 public MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle) { 456 super(context, attrs, defStyle); 457 } 458 MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle, int defStyleRes)459 public MyAbsSeekBar(Context context, AttributeSet attrs, int defStyle, int defStyleRes) { 460 super(context, attrs, defStyle, defStyleRes); 461 } 462 463 @Override drawableStateChanged()464 protected void drawableStateChanged() { 465 super.drawableStateChanged(); 466 } 467 468 @Override verifyDrawable(Drawable who)469 protected boolean verifyDrawable(Drawable who) { 470 return super.verifyDrawable(who); 471 } 472 } 473 } 474