1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.ui.resources.dynamics;
6 
7 import static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertFalse;
9 import static org.junit.Assert.assertNotEquals;
10 import static org.junit.Assert.assertNotNull;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.Mockito.when;
13 import static org.mockito.MockitoAnnotations.initMocks;
14 
15 import static org.chromium.base.GarbageCollectionTestUtils.canBeGarbageCollected;
16 
17 import android.graphics.Bitmap;
18 import android.graphics.Canvas;
19 import android.graphics.Rect;
20 import android.view.View;
21 
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.mockito.Mock;
26 import org.robolectric.annotation.Config;
27 
28 import org.chromium.base.test.BaseRobolectricTestRunner;
29 
30 import java.lang.ref.WeakReference;
31 
32 /**
33  * Tests for {@link ViewResourceAdapter}.
34  */
35 @RunWith(BaseRobolectricTestRunner.class)
36 @Config(manifest = Config.NONE)
37 public class ViewResourceAdapterTest {
38     private int mViewWidth;
39     private int mViewHeight;
40     @Mock
41     private View mView;
42 
43     private ViewResourceAdapter mAdapter;
44 
45     @Before
setup()46     public void setup() {
47         initMocks(this);
48 
49         mViewWidth = 200;
50         mViewHeight = 100;
51 
52         when(mView.getWidth()).thenAnswer((invocation) -> mViewWidth);
53         when(mView.getHeight()).thenAnswer((invocation) -> mViewHeight);
54 
55         mAdapter = new ViewResourceAdapter(mView) {
56             /**
57              * Mock this out to avoid calling {@link View#draw(Canvas)} on the mocked mView.
58              * Otherwise the GC-related tests would fail.
59              */
60             @Override
61             protected void capture(Canvas canvas) {}
62         };
63 
64     }
65 
66     @Test
testGetBitmap()67     public void testGetBitmap() {
68         Bitmap bitmap = mAdapter.getBitmap();
69         assertNotNull(bitmap);
70         assertEquals(mViewWidth, bitmap.getWidth());
71         assertEquals(mViewHeight, bitmap.getHeight());
72     }
73 
74     @Test
testGetBitmapSize()75     public void testGetBitmapSize() {
76         Bitmap bitmap = mAdapter.getBitmap();
77         Rect rect = mAdapter.getBitmapSize();
78         assertEquals(bitmap.getWidth(), rect.width());
79         assertEquals(bitmap.getHeight(), rect.height());
80     }
81 
82     @Test
testSetDownsamplingSize()83     public void testSetDownsamplingSize() {
84         float scale = 0.5f;
85         mAdapter.setDownsamplingScale(scale);
86         Bitmap bitmap = mAdapter.getBitmap();
87         assertEquals(mViewWidth * scale, bitmap.getWidth(), 1);
88         assertEquals(mViewHeight * scale, bitmap.getHeight(), 1);
89 
90         Rect rect = mAdapter.getBitmapSize();
91         assertEquals(mViewWidth, rect.width());
92         assertEquals(mViewHeight, rect.height());
93     }
94 
95     @Test
testIsDirty()96     public void testIsDirty() {
97         assertTrue(mAdapter.isDirty());
98 
99         mAdapter.getBitmap();
100         assertFalse(mAdapter.isDirty());
101     }
102 
103     @Test
testOnLayoutChange()104     public void testOnLayoutChange() {
105         mAdapter.getBitmap();
106         assertFalse(mAdapter.isDirty());
107 
108         mAdapter.onLayoutChange(mView, 0, 0, 1, 2, 0, 0, mViewWidth, mViewHeight);
109         assertTrue(mAdapter.isDirty());
110 
111         Rect dirtyRect = mAdapter.getDirtyRect();
112         assertEquals(1, dirtyRect.width());
113         assertEquals(2, dirtyRect.height());
114     }
115 
116     @Test
testOnLayoutChangeDownsampled()117     public void testOnLayoutChangeDownsampled() {
118         mAdapter.setDownsamplingScale(0.5f);
119 
120         mAdapter.getBitmap();
121         assertFalse(mAdapter.isDirty());
122 
123         mAdapter.onLayoutChange(mView, 0, 0, 1, 2, 0, 0, mViewWidth, mViewHeight);
124         assertTrue(mAdapter.isDirty());
125 
126         Rect dirtyRect = mAdapter.getDirtyRect();
127         assertEquals(1, dirtyRect.width());
128         assertEquals(2, dirtyRect.height());
129     }
130 
131     @Test
testInvalidate()132     public void testInvalidate() {
133         mAdapter.getBitmap();
134         assertFalse(mAdapter.isDirty());
135 
136         mAdapter.invalidate(null);
137         assertTrue(mAdapter.isDirty());
138 
139         Rect dirtyRect = mAdapter.getDirtyRect();
140         assertEquals(mViewWidth, dirtyRect.width());
141         assertEquals(mViewHeight, dirtyRect.height());
142     }
143 
144     @Test
testInvalidateRect()145     public void testInvalidateRect() {
146         mAdapter.getBitmap();
147         assertFalse(mAdapter.isDirty());
148 
149         Rect dirtyRect = new Rect(1, 2, 3, 4);
150         mAdapter.invalidate(dirtyRect);
151         assertTrue(mAdapter.isDirty());
152         assertEquals(dirtyRect.toString(), mAdapter.getDirtyRect().toString());
153     }
154 
155     @Test
testInvalidateRectDownsampled()156     public void testInvalidateRectDownsampled() {
157         mAdapter.setDownsamplingScale(0.5f);
158 
159         mAdapter.getBitmap();
160         assertFalse(mAdapter.isDirty());
161 
162         Rect dirtyRect = new Rect(1, 2, 3, 4);
163         mAdapter.invalidate(dirtyRect);
164         assertTrue(mAdapter.isDirty());
165         assertEquals(dirtyRect.toString(), mAdapter.getDirtyRect().toString());
166     }
167 
168     @Test
testInvalidateRectUnion()169     public void testInvalidateRectUnion() {
170         mAdapter.getBitmap();
171         assertFalse(mAdapter.isDirty());
172 
173         mAdapter.invalidate(new Rect(1, 2, 3, 4));
174         mAdapter.invalidate(new Rect(5, 6, 7, 8));
175         assertTrue(mAdapter.isDirty());
176         Rect expected = new Rect(1, 2, 7, 8);
177         assertEquals(expected.toString(), mAdapter.getDirtyRect().toString());
178     }
179 
180     @Test
testGetBitmapResized()181     public void testGetBitmapResized() {
182         Bitmap bitmap = mAdapter.getBitmap();
183         assertNotNull(bitmap);
184         assertEquals(mViewWidth, bitmap.getWidth());
185         assertEquals(mViewHeight, bitmap.getHeight());
186 
187         mViewWidth = 10;
188         mViewHeight = 20;
189         mAdapter.invalidate(null);
190         Bitmap bitmap2 = mAdapter.getBitmap();
191         assertNotNull(bitmap2);
192         assertEquals(mViewWidth, bitmap2.getWidth());
193         assertEquals(mViewHeight, bitmap2.getHeight());
194         assertNotEquals(bitmap, bitmap2);
195     }
196 
197     @Test
testBitmapReused()198     public void testBitmapReused() {
199         Bitmap bitmap = mAdapter.getBitmap();
200         assertNotNull(bitmap);
201 
202         mAdapter.invalidate(null);
203         assertTrue(mAdapter.isDirty());
204         assertEquals(bitmap, mAdapter.getBitmap());
205     }
206 
207     @Test
testDropCachedBitmap()208     public void testDropCachedBitmap() {
209         Bitmap bitmap = mAdapter.getBitmap();
210         assertNotNull(bitmap);
211 
212         mAdapter.invalidate(null);
213         assertTrue(mAdapter.isDirty());
214         assertEquals(bitmap, mAdapter.getBitmap());
215 
216         mAdapter.dropCachedBitmap();
217         mAdapter.invalidate(null);
218         assertTrue(mAdapter.isDirty());
219         assertNotEquals(bitmap, mAdapter.getBitmap());
220     }
221 
222     @Test
testDropCachedBitmapNotDirty()223     public void testDropCachedBitmapNotDirty() {
224         mAdapter.getBitmap();
225         mAdapter.dropCachedBitmap();
226         assertFalse(mAdapter.isDirty());
227     }
228 
229     @Test
testDropCachedBitmapGCed()230     public void testDropCachedBitmapGCed() {
231         WeakReference<Bitmap> bitmapWeakReference = new WeakReference<>(mAdapter.getBitmap());
232         assertNotNull(bitmapWeakReference.get());
233         assertFalse(canBeGarbageCollected(bitmapWeakReference));
234 
235         mAdapter.dropCachedBitmap();
236         assertTrue(canBeGarbageCollected(bitmapWeakReference));
237     }
238 
239     @Test
testResizeGCed()240     public void testResizeGCed() {
241         WeakReference<Bitmap> bitmapWeakReference = new WeakReference<>(mAdapter.getBitmap());
242         assertNotNull(bitmapWeakReference.get());
243         assertFalse(canBeGarbageCollected(bitmapWeakReference));
244 
245         mViewWidth += 10;
246         mAdapter.invalidate(null);
247         mAdapter.getBitmap();
248         assertTrue(canBeGarbageCollected(bitmapWeakReference));
249     }
250 
251     @Test
testGetDirtyRect()252     public void testGetDirtyRect() {
253         mAdapter.getBitmap();
254         Rect rect = mAdapter.getDirtyRect();
255         assertTrue(rect.isEmpty());
256 
257         mAdapter.invalidate(null);
258         rect = mAdapter.getDirtyRect();
259         assertEquals(mViewWidth, rect.width());
260         assertEquals(mViewHeight, rect.height());
261     }
262 
263     @Test
testGetDirtyRectDownsampled()264     public void testGetDirtyRectDownsampled() {
265         mAdapter.setDownsamplingScale(0.5f);
266 
267         mAdapter.getBitmap();
268         Rect rect = mAdapter.getDirtyRect();
269         assertTrue(rect.isEmpty());
270 
271         mAdapter.invalidate(null);
272         rect = mAdapter.getDirtyRect();
273         assertEquals(mViewWidth, rect.width());
274         assertEquals(mViewHeight, rect.height());
275     }
276 }
277