1 /* 2 * Copyright (C) 2015 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.graphics.drawable.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.Matchers.any; 24 import static org.mockito.Matchers.anyBoolean; 25 import static org.mockito.Matchers.anyInt; 26 import static org.mockito.Matchers.anyLong; 27 import static org.mockito.Mockito.doNothing; 28 import static org.mockito.Mockito.mock; 29 import static org.mockito.Mockito.never; 30 import static org.mockito.Mockito.reset; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 35 import android.graphics.Canvas; 36 import android.graphics.Color; 37 import android.graphics.ColorFilter; 38 import android.graphics.PixelFormat; 39 import android.graphics.PorterDuff; 40 import android.graphics.PorterDuffColorFilter; 41 import android.graphics.Rect; 42 import android.graphics.cts.R; 43 import android.graphics.drawable.BitmapDrawable; 44 import android.graphics.drawable.ColorDrawable; 45 import android.graphics.drawable.Drawable; 46 import android.graphics.drawable.DrawableWrapper; 47 import android.support.test.InstrumentationRegistry; 48 import android.support.test.filters.SmallTest; 49 import android.support.test.runner.AndroidJUnit4; 50 import android.util.StateSet; 51 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 55 import java.util.Arrays; 56 57 @SmallTest 58 @RunWith(AndroidJUnit4.class) 59 public class DrawableWrapperTest { 60 static class MyWrapper extends DrawableWrapper { 61 public MyWrapper(Drawable dr) { 62 super(dr); 63 } 64 } 65 66 @SuppressWarnings("deprecation") 67 @Test 68 public void testConstructor() { 69 Drawable d = new BitmapDrawable(); 70 DrawableWrapper wrapper = new MyWrapper(d); 71 assertSame(d, wrapper.getDrawable()); 72 73 new MyWrapper(null); 74 } 75 76 @SuppressWarnings("deprecation") 77 @Test 78 public void testGetDrawable() { 79 Drawable d = new BitmapDrawable(); 80 DrawableWrapper wrapper = new MyWrapper(d); 81 assertSame(d, wrapper.getDrawable()); 82 } 83 84 @SuppressWarnings("deprecation") 85 @Test 86 public void testSetDrawable() { 87 Drawable d = new BitmapDrawable(); 88 DrawableWrapper wrapper = new MyWrapper(null); 89 assertSame(null, wrapper.getDrawable()); 90 91 wrapper.setDrawable(d); 92 assertSame(d, wrapper.getDrawable()); 93 } 94 95 @SuppressWarnings("deprecation") 96 @Test 97 public void testInvalidateDrawable() { 98 DrawableWrapper wrapper = new MyWrapper(new BitmapDrawable()); 99 100 Drawable.Callback cb = mock(Drawable.Callback.class); 101 wrapper.setCallback(cb); 102 wrapper.invalidateDrawable(null); 103 verify(cb, times(1)).invalidateDrawable(any()); 104 105 reset(cb); 106 wrapper.invalidateDrawable(new BitmapDrawable()); 107 verify(cb, times(1)).invalidateDrawable(any()); 108 109 reset(cb); 110 wrapper.setCallback(null); 111 wrapper.invalidateDrawable(null); 112 verify(cb, never()).invalidateDrawable(any()); 113 } 114 115 @SuppressWarnings("deprecation") 116 @Test 117 public void testScheduleDrawable() { 118 DrawableWrapper wrapper = new MyWrapper(new BitmapDrawable()); 119 120 Drawable.Callback cb = mock(Drawable.Callback.class); 121 wrapper.setCallback(cb); 122 wrapper.scheduleDrawable(null, null, 0); 123 verify(cb, times(1)).scheduleDrawable(any(), any(), anyLong()); 124 125 reset(cb); 126 wrapper.scheduleDrawable(new BitmapDrawable(), () -> {}, 1000L); 127 verify(cb, times(1)).scheduleDrawable(any(), any(), anyLong()); 128 129 reset(cb); 130 wrapper.setCallback(null); 131 wrapper.scheduleDrawable(null, null, 0); 132 verify(cb, never()).scheduleDrawable(any(), any(), anyLong()); 133 } 134 135 @SuppressWarnings("deprecation") 136 @Test 137 public void testUnscheduleDrawable() { 138 DrawableWrapper wrapper = new MyWrapper(new BitmapDrawable()); 139 140 Drawable.Callback cb = mock(Drawable.Callback.class); 141 wrapper.setCallback(cb); 142 wrapper.unscheduleDrawable(null, null); 143 verify(cb, times(1)).unscheduleDrawable(any(), any()); 144 145 reset(cb); 146 wrapper.unscheduleDrawable(new BitmapDrawable(), () -> {}); 147 verify(cb, times(1)).unscheduleDrawable(any(), any()); 148 149 reset(cb); 150 wrapper.setCallback(null); 151 wrapper.unscheduleDrawable(null, null); 152 verify(cb, never()).unscheduleDrawable(any(), any()); 153 } 154 155 @Test 156 public void testDraw() { 157 Drawable mockDrawable = spy(new ColorDrawable(Color.BLUE)); 158 doNothing().when(mockDrawable).draw(any()); 159 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 160 161 wrapper.draw(new Canvas()); 162 verify(mockDrawable, times(1)).draw(any()); 163 164 reset(mockDrawable); 165 doNothing().when(mockDrawable).draw(any()); 166 wrapper.draw(null); 167 verify(mockDrawable, times(1)).draw(any()); 168 } 169 170 @Test 171 public void testGetChangingConfigurations() { 172 final int SUPER_CONFIG = 1; 173 final int CONTAINED_DRAWABLE_CONFIG = 2; 174 175 MockDrawable mockDrawable = new MockDrawable(); 176 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 177 178 assertEquals(0, wrapper.getChangingConfigurations()); 179 180 mockDrawable.setChangingConfigurations(CONTAINED_DRAWABLE_CONFIG); 181 assertEquals(CONTAINED_DRAWABLE_CONFIG, wrapper.getChangingConfigurations()); 182 183 wrapper.setChangingConfigurations(SUPER_CONFIG); 184 assertEquals(SUPER_CONFIG | CONTAINED_DRAWABLE_CONFIG, 185 wrapper.getChangingConfigurations()); 186 } 187 188 @Test 189 public void testGetPadding() { 190 Drawable mockDrawable = spy(new ColorDrawable(Color.RED)); 191 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 192 193 // this method will call contained drawable's getPadding method. 194 wrapper.getPadding(new Rect()); 195 verify(mockDrawable, times(1)).getPadding(any()); 196 } 197 198 @Test 199 public void testColorFilter() { 200 Drawable wrappedDrawable = new MockDrawable(); 201 DrawableWrapper wrapper = new MyWrapper(wrappedDrawable); 202 PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(Color.BLUE, 203 PorterDuff.Mode.SRC_OVER); 204 wrapper.setColorFilter(colorFilter); 205 ColorFilter obtainedColorFilter = wrapper.getColorFilter(); 206 assertEquals("Color filters are not properly returned", colorFilter, obtainedColorFilter); 207 } 208 209 @Test(expected=NullPointerException.class) 210 public void testGetPaddingNull() { 211 DrawableWrapper wrapper = new MyWrapper(new ColorDrawable(Color.RED)); 212 213 wrapper.getPadding(null); 214 } 215 216 @Test 217 public void testSetVisible() { 218 Drawable mockDrawable = spy(new ColorDrawable(Color.YELLOW)); 219 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 220 assertTrue(wrapper.isVisible()); 221 222 assertTrue(wrapper.setVisible(false, false)); 223 assertFalse(wrapper.isVisible()); 224 verify(mockDrawable, times(1)).setVisible(anyBoolean(), anyBoolean()); 225 226 reset(mockDrawable); 227 assertFalse(wrapper.setVisible(false, false)); 228 assertFalse(wrapper.isVisible()); 229 verify(mockDrawable, times(1)).setVisible(anyBoolean(), anyBoolean()); 230 231 reset(mockDrawable); 232 assertTrue(wrapper.setVisible(true, false)); 233 assertTrue(wrapper.isVisible()); 234 verify(mockDrawable, times(1)).setVisible(anyBoolean(), anyBoolean()); 235 } 236 237 @Test 238 public void testSetAlpha() { 239 Drawable mockDrawable = spy(new ColorDrawable(Color.MAGENTA)); 240 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 241 242 // this method will call contained drawable's setAlpha method. 243 wrapper.setAlpha(100); 244 verify(mockDrawable, times(1)).setAlpha(anyInt()); 245 246 reset(mockDrawable); 247 wrapper.setAlpha(Integer.MAX_VALUE); 248 verify(mockDrawable, times(1)).setAlpha(anyInt()); 249 250 reset(mockDrawable); 251 wrapper.setAlpha(-1); 252 verify(mockDrawable, times(1)).setAlpha(anyInt()); 253 } 254 255 @Test 256 public void testSetColorFilter() { 257 Drawable mockDrawable = spy(new ColorDrawable(Color.GRAY)); 258 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 259 260 // this method will call contained drawable's setColorFilter method. 261 wrapper.setColorFilter(new ColorFilter()); 262 verify(mockDrawable, times(1)).setColorFilter(any()); 263 264 reset(mockDrawable); 265 wrapper.setColorFilter(null); 266 verify(mockDrawable, times(1)).setColorFilter(any()); 267 } 268 269 @Test 270 public void testGetOpacity() { 271 Drawable mockDrawable = spy(new ColorDrawable(Color.RED)); 272 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 273 274 // This method will call contained drawable's getOpacity method. 275 wrapper.setLevel(1); 276 wrapper.getOpacity(); 277 verify(mockDrawable, times(1)).getOpacity(); 278 } 279 280 @Test 281 public void testIsStateful() { 282 Drawable mockDrawable = spy(new ColorDrawable(Color.BLACK)); 283 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 284 285 // this method will call contained drawable's isStateful method. 286 wrapper.isStateful(); 287 verify(mockDrawable, times(1)).isStateful(); 288 } 289 290 @Test 291 public void testOnStateChange() { 292 Drawable d = new MockDrawable(); 293 MockDrawableWrapper wrapper = new MockDrawableWrapper(d); 294 assertEquals("initial child state is empty", d.getState(), StateSet.WILD_CARD); 295 296 int[] state = new int[] {1, 2, 3}; 297 assertFalse("child did not change", wrapper.onStateChange(state)); 298 assertEquals("child state did not change", d.getState(), StateSet.WILD_CARD); 299 300 d = InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.statelistdrawable); 301 wrapper = new MockDrawableWrapper(d); 302 assertEquals("initial child state is empty", d.getState(), StateSet.WILD_CARD); 303 wrapper.onStateChange(state); 304 assertTrue("child state changed", Arrays.equals(state, d.getState())); 305 306 // input null as param 307 wrapper.onStateChange(null); 308 // expected, no Exception thrown out, test success 309 } 310 311 @Test 312 public void testOnLevelChange() { 313 MockDrawable mockDrawable = new MockDrawable(); 314 MockDrawableWrapper mockDrawableWrapper = new MockDrawableWrapper(mockDrawable); 315 316 assertEquals(0, mockDrawable.getLevel()); 317 assertFalse(mockDrawableWrapper.onLevelChange(0)); 318 assertFalse(mockDrawable.hasCalledOnLevelChange()); 319 320 assertFalse(mockDrawableWrapper.onLevelChange(1000)); 321 assertTrue(mockDrawable.hasCalledOnLevelChange()); 322 assertEquals(1000, mockDrawable.getLevel()); 323 324 mockDrawable.reset(); 325 assertFalse(mockDrawableWrapper.onLevelChange(Integer.MIN_VALUE)); 326 assertTrue(mockDrawable.hasCalledOnLevelChange()); 327 } 328 329 @Test 330 public void testOnBoundsChange() { 331 MockDrawable mockDrawable = new MockDrawable(); 332 MockDrawableWrapper mockDrawableWrapper = new MockDrawableWrapper(mockDrawable); 333 Rect bounds = new Rect(2, 2, 26, 32); 334 mockDrawable.setBounds(bounds); 335 mockDrawableWrapper.onBoundsChange(bounds); 336 337 mockDrawableWrapper = new MockDrawableWrapper(mockDrawable); 338 mockDrawable.setBounds(bounds); 339 mockDrawableWrapper.onBoundsChange(bounds); 340 assertEquals(bounds.left, mockDrawable.getBounds().left); 341 assertEquals(bounds.top, mockDrawable.getBounds().top); 342 assertEquals(bounds.right, mockDrawable.getBounds().right); 343 assertEquals(bounds.bottom, mockDrawable.getBounds().bottom); 344 345 bounds = mockDrawable.getBounds(); 346 assertEquals(2, bounds.left); 347 assertEquals(2, bounds.top); 348 assertEquals(26, bounds.right); 349 assertEquals(32, bounds.bottom); 350 } 351 352 @Test(expected=NullPointerException.class) 353 public void testOnBoundsChangeNull() { 354 MockDrawable mockDrawable = new MockDrawable(); 355 MockDrawableWrapper mockDrawableWrapper = new MockDrawableWrapper(mockDrawable); 356 357 mockDrawableWrapper.onBoundsChange(null); 358 } 359 360 @Test 361 public void testGetIntrinsicWidth() { 362 Drawable mockDrawable = spy(new ColorDrawable(Color.WHITE)); 363 MyWrapper wrapper = new MyWrapper(mockDrawable); 364 365 // this method will call contained drawable's getIntrinsicWidth method. 366 wrapper.getIntrinsicWidth(); 367 verify(mockDrawable, times(1)).getIntrinsicWidth(); 368 } 369 370 @Test 371 public void testGetIntrinsicHeight() { 372 Drawable mockDrawable = spy(new ColorDrawable(Color.RED)); 373 DrawableWrapper wrapper = new MyWrapper(mockDrawable); 374 375 // this method will call contained drawable's getIntrinsicHeight method. 376 wrapper.getIntrinsicHeight(); 377 verify(mockDrawable, times(1)).getIntrinsicHeight(); 378 } 379 380 @SuppressWarnings("deprecation") 381 @Test 382 public void testGetConstantState() { 383 DrawableWrapper wrapper = new MyWrapper(new BitmapDrawable()); 384 wrapper.getConstantState(); 385 } 386 387 // Since Mockito can't mock or spy on protected methods, we have a custom extension 388 // of Drawable to track calls to protected methods. This class also has empty implementations 389 // of the base abstract methods. 390 private static class MockDrawable extends Drawable { 391 private boolean mCalledOnLevelChange = false; 392 private ColorFilter mColorFilter; 393 394 @Override 395 public void draw(Canvas canvas) { 396 } 397 398 @Override 399 public int getOpacity() { 400 return PixelFormat.OPAQUE; 401 } 402 403 @Override 404 public void setAlpha(int alpha) { 405 } 406 407 @Override 408 public void setColorFilter(ColorFilter cf) { 409 mColorFilter = cf; 410 } 411 412 @Override 413 public ColorFilter getColorFilter() { 414 return mColorFilter; 415 } 416 417 @Override 418 protected boolean onLevelChange(int level) { 419 mCalledOnLevelChange = true; 420 return super.onLevelChange(level); 421 } 422 423 public boolean hasCalledOnLevelChange() { 424 return mCalledOnLevelChange; 425 } 426 427 public void reset() { 428 mCalledOnLevelChange = false; 429 } 430 } 431 432 private static class MockDrawableWrapper extends DrawableWrapper { 433 MockDrawableWrapper() { 434 super(null); 435 } 436 437 public MockDrawableWrapper(Drawable drawable) { 438 super(drawable); 439 } 440 441 @Override 442 protected boolean onStateChange(int[] state) { 443 return super.onStateChange(state); 444 } 445 446 @Override 447 protected boolean onLevelChange(int level) { 448 return super.onLevelChange(level); 449 } 450 451 @Override 452 protected void onBoundsChange(Rect bounds) { 453 super.onBoundsChange(bounds); 454 } 455 } 456 } 457