1package org.robolectric.shadows;
2
3import static android.os.Build.VERSION_CODES.KITKAT_WATCH;
4import static android.os.Build.VERSION_CODES.LOLLIPOP;
5import static org.assertj.core.api.Assertions.assertThat;
6import static org.junit.Assert.assertEquals;
7import static org.junit.Assert.assertFalse;
8import static org.junit.Assert.assertNotNull;
9import static org.junit.Assert.assertNull;
10import static org.junit.Assert.assertTrue;
11import static org.robolectric.Shadows.shadowOf;
12
13import android.graphics.BitmapFactory;
14import android.graphics.Canvas;
15import android.graphics.ColorFilter;
16import android.graphics.Rect;
17import android.graphics.drawable.BitmapDrawable;
18import android.graphics.drawable.Drawable;
19import android.graphics.drawable.VectorDrawable;
20import java.io.ByteArrayInputStream;
21import java.io.InputStream;
22import org.junit.Test;
23import org.junit.runner.RunWith;
24import org.robolectric.R;
25import org.robolectric.RobolectricTestRunner;
26import org.robolectric.RuntimeEnvironment;
27import org.robolectric.annotation.Config;
28
29@RunWith(RobolectricTestRunner.class)
30public class ShadowDrawableTest {
31  @Test
32  public void createFromStream__shouldReturnNullWhenAskedToCreateADrawableFromACorruptedSourceStream() throws Exception {
33    String corruptedStreamSource = "http://foo.com/image.jpg";
34    ShadowDrawable.addCorruptStreamSource(corruptedStreamSource);
35    assertNull(ShadowDrawable.createFromStream(new ByteArrayInputStream(new byte[0]), corruptedStreamSource));
36  }
37
38  @Test
39  public void createFromResourceStream_shouldWorkWithoutSourceName() {
40    Drawable drawable = Drawable.createFromResourceStream(RuntimeEnvironment.application.getResources(),
41        null, new ByteArrayInputStream(new byte[0]), null, new BitmapFactory.Options());
42    assertNotNull(drawable);
43  }
44
45  @Test
46  public void createFromStream__shouldReturnDrawableWithSpecificSource() throws Exception {
47    Drawable drawable = ShadowDrawable.createFromStream(new ByteArrayInputStream(new byte[0]), "my_source");
48    assertNotNull(drawable);
49    assertEquals("my_source", ((ShadowBitmapDrawable) shadowOf(drawable)).getSource());
50  }
51
52  @Test
53  public void reset__shouldClearStaticState() throws Exception {
54    String src = "source1";
55    ShadowDrawable.addCorruptStreamSource(src);
56    assertTrue(ShadowDrawable.corruptStreamSources.contains(src));
57    ShadowDrawable.clearCorruptStreamSources();
58    assertFalse(ShadowDrawable.corruptStreamSources.contains(src));
59  }
60
61  @Test
62  public void testCreateFromStream_shouldSetTheInputStreamOnTheReturnedDrawable() throws Exception {
63    ByteArrayInputStream byteInputStream = new ByteArrayInputStream(new byte[0]);
64    Drawable drawable = Drawable.createFromStream(byteInputStream, "src name");
65    assertThat(shadowOf(drawable).getInputStream()).isEqualTo((InputStream) byteInputStream);
66  }
67
68  @Test
69  public void copyBoundsWithPassedRect() {
70    Drawable drawable = ShadowDrawable.createFromStream(new ByteArrayInputStream(new byte[0]), "my_source");
71    drawable.setBounds(1, 2, 3, 4);
72    Rect r = new Rect();
73    drawable.copyBounds(r);
74    assertThat(r.left).isEqualTo(1);
75    assertThat(r.top).isEqualTo(2);
76    assertThat(r.right).isEqualTo(3);
77    assertThat(r.bottom).isEqualTo(4);
78  }
79
80  @Test
81  public void copyBoundsToReturnedRect() {
82    Drawable drawable = ShadowDrawable.createFromStream(new ByteArrayInputStream(new byte[0]), "my_source");
83    drawable.setBounds(1, 2, 3, 4);
84    Rect r = drawable.copyBounds();
85    assertThat(r.left).isEqualTo(1);
86    assertThat(r.top).isEqualTo(2);
87    assertThat(r.right).isEqualTo(3);
88    assertThat(r.bottom).isEqualTo(4);
89  }
90
91  @Test
92  public void createFromPath__shouldReturnDrawableWithSpecificPath() throws Exception {
93    Drawable drawable = ShadowDrawable.createFromPath("/foo");
94    assertNotNull(drawable);
95    assertEquals("/foo", ((ShadowBitmapDrawable) shadowOf(drawable)).getPath());
96  }
97
98  @Test
99  public void testGetLoadedFromResourceId_shouldDefaultToNegativeOne() throws Exception {
100    Drawable drawable = new TestDrawable();
101    assertThat(shadowOf(drawable).getCreatedFromResId()).isEqualTo(-1);
102  }
103
104  @Test
105  public void testCreateFromResourceId_shouldSetTheId() throws Exception {
106    Drawable drawable = ShadowDrawable.createFromResourceId(34758);
107    ShadowDrawable shadowDrawable = shadowOf(drawable);
108    assertThat(shadowDrawable.getCreatedFromResId()).isEqualTo(34758);
109  }
110
111  @Test
112  public void testWasSelfInvalidated() throws Exception {
113    Drawable drawable = ShadowDrawable.createFromResourceId(34758);
114    ShadowDrawable shadowDrawable = shadowOf(drawable);
115    assertThat(shadowDrawable.wasInvalidated()).isFalse();
116    drawable.invalidateSelf();
117    assertThat(shadowDrawable.wasInvalidated()).isTrue();
118  }
119
120  @Test public void shouldLoadNinePatchFromDrawableXml() throws Exception {
121    assertThat(RuntimeEnvironment.application.getResources()
122        .getDrawable(R.drawable.drawable_with_nine_patch)).isNotNull();
123  }
124
125  @Test public void settingBoundsShouldInvokeCallback() {
126    TestDrawable drawable = new TestDrawable();
127    assertThat(drawable.boundsChanged).isFalse();
128    drawable.setBounds(0, 0, 10, 10);
129    assertThat(drawable.boundsChanged).isTrue();
130  }
131
132  @Test
133  public void drawableIntrinsicWidthAndHeightShouldBeCorrect() {
134    final Drawable anImage = RuntimeEnvironment.application.getResources().getDrawable(R.drawable.an_image);
135
136    assertThat(anImage.getIntrinsicHeight()).isEqualTo(53);
137    assertThat(anImage.getIntrinsicWidth()).isEqualTo(64);
138  }
139
140  @Test
141  @Config(qualifiers = "mdpi")
142  public void drawableShouldLoadImageOfCorrectSizeWithMdpiQualifier() {
143    final Drawable anImage = RuntimeEnvironment.application.getResources().getDrawable(R.drawable.robolectric);
144
145    assertThat(anImage.getIntrinsicHeight()).isEqualTo(167);
146    assertThat(anImage.getIntrinsicWidth()).isEqualTo(198);
147  }
148
149  @Test
150  @Config(qualifiers = "hdpi")
151  public void drawableShouldLoadImageOfCorrectSizeWithHdpiQualifier() {
152    final Drawable anImage = RuntimeEnvironment.application.getResources().getDrawable(R.drawable.robolectric);
153
154    assertThat(anImage.getIntrinsicHeight()).isEqualTo(251);
155    assertThat(anImage.getIntrinsicWidth()).isEqualTo(297);
156  }
157
158  @Test
159  @Config(maxSdk = KITKAT_WATCH)
160  public void testGetBitmapOrVectorDrawableAt19() {
161    final Drawable aDrawable = RuntimeEnvironment.application.getResources()
162        .getDrawable(R.drawable.an_image_or_vector);
163    assertThat(aDrawable).isInstanceOf(BitmapDrawable.class);
164  }
165
166  @Test
167  @Config(minSdk = LOLLIPOP)
168  public void testGetBitmapOrVectorDrawableAt21() {
169    final Drawable aDrawable = RuntimeEnvironment.application.getResources()
170        .getDrawable(R.drawable.an_image_or_vector);
171    assertThat(aDrawable).isInstanceOf(VectorDrawable.class);
172  }
173
174  private static class TestDrawable extends Drawable {
175    public boolean boundsChanged;
176
177    @Override
178    public void draw(Canvas canvas) {
179    }
180
181    @Override
182    public void setAlpha(int alpha) {
183    }
184
185    @Override
186    public void setColorFilter(ColorFilter cf) {
187    }
188
189    @Override
190    public int getOpacity() {
191      return 0;
192    }
193
194    @Override protected void onBoundsChange(Rect bounds) {
195      boundsChanged = true;
196      super.onBoundsChange(bounds);
197    }
198  }
199}
200