189d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes/*
289d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * Copyright (C) 2016 The Android Open Source Project
389d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes *
489d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
589d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * you may not use this file except in compliance with the License.
689d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * You may obtain a copy of the License at
789d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes *
889d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
989d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes *
1089d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * Unless required by applicable law or agreed to in writing, software
1189d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1289d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1389d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * See the License for the specific language governing permissions and
1489d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes * limitations under the License.
1589d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes */
1689d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.core.graphics;
1889d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
19754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertEquals;
20754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertNotNull;
21754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertNotSame;
22754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertSame;
23754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Mockito.mock;
24754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Mockito.times;
25754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Mockito.verify;
26754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikas
27be678137d44778590a6220ae0ef13649e83363a9Chris Banesimport android.content.res.ColorStateList;
28be678137d44778590a6220ae0ef13649e83363a9Chris Banesimport android.graphics.Color;
29be678137d44778590a6220ae0ef13649e83363a9Chris Banesimport android.graphics.PorterDuff;
3089d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banesimport android.graphics.Rect;
3189d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banesimport android.graphics.drawable.Drawable;
3289d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banesimport android.graphics.drawable.GradientDrawable;
33be678137d44778590a6220ae0ef13649e83363a9Chris Banesimport android.os.Build;
34754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.SmallTest;
35f5ec4487510a0e7226636704860a884f4c1d0ab6Kirill Grouchnikovimport android.support.test.runner.AndroidJUnit4;
369dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikas
37ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.graphics.drawable.DrawableCompat;
38754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikas
39881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikovimport org.junit.Test;
40881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikovimport org.junit.runner.RunWith;
4189d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
42881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikov@RunWith(AndroidJUnit4.class)
43881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikov@SmallTest
44881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikovpublic class DrawableCompatTest {
45881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikov    @Test
46be678137d44778590a6220ae0ef13649e83363a9Chris Banes    public void testDrawableWrap() {
47be678137d44778590a6220ae0ef13649e83363a9Chris Banes        final Drawable original = new GradientDrawable();
48be678137d44778590a6220ae0ef13649e83363a9Chris Banes        final Drawable wrappedDrawable = DrawableCompat.wrap(original);
49be678137d44778590a6220ae0ef13649e83363a9Chris Banes
50be678137d44778590a6220ae0ef13649e83363a9Chris Banes        if (Build.VERSION.SDK_INT < 23) {
51be678137d44778590a6220ae0ef13649e83363a9Chris Banes            assertNotSame(original, wrappedDrawable);
52be678137d44778590a6220ae0ef13649e83363a9Chris Banes        } else {
53be678137d44778590a6220ae0ef13649e83363a9Chris Banes            assertSame(original, wrappedDrawable);
54be678137d44778590a6220ae0ef13649e83363a9Chris Banes        }
55be678137d44778590a6220ae0ef13649e83363a9Chris Banes    }
56be678137d44778590a6220ae0ef13649e83363a9Chris Banes
575f5ffb9bea7e6db394d6879f37ab1aadb8d2fdebChris Banes    @Test
5889d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes    public void testDrawableUnwrap() {
5989d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes        final Drawable original = new GradientDrawable();
6089d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes        final Drawable wrappedDrawable = DrawableCompat.wrap(original);
6189d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes        assertSame(original, DrawableCompat.unwrap(wrappedDrawable));
6289d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes    }
6389d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
64881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikov    @Test
6589d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes    public void testDrawableChangeBoundsCopy() {
6689d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes        final Rect bounds = new Rect(0, 0, 10, 10);
6789d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
68be61247c92b085602d3f671be6f506e9813aba19Chris Banes        final Drawable drawable = new GradientDrawable();
69be61247c92b085602d3f671be6f506e9813aba19Chris Banes
70be61247c92b085602d3f671be6f506e9813aba19Chris Banes        final Drawable wrapper = DrawableCompat.wrap(drawable);
71be61247c92b085602d3f671be6f506e9813aba19Chris Banes        wrapper.setBounds(bounds);
7289d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
73be61247c92b085602d3f671be6f506e9813aba19Chris Banes        // Assert that the bounds were given to the original drawable
74be61247c92b085602d3f671be6f506e9813aba19Chris Banes        assertEquals(bounds, drawable.getBounds());
7589d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes    }
7689d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
77881c193f64d35ea2a106a2f76c30bd711a971bb1Kirill Grouchnikov    @Test
78d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes    public void testWrapCopiesDrawableState() {
79d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        final Rect bounds = new Rect(0, 0, 10, 10);
80d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes
81d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        // Create a drawable and set some bounds
82d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        final Drawable drawable = new GradientDrawable();
83d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        drawable.setBounds(bounds);
84d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes
85d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        // Now wrap it
86d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        final Drawable wrapper = DrawableCompat.wrap(drawable);
87d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes
88d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        // Assert that the bounds were copied to the wrapper
89d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes        assertEquals(bounds, wrapper.getBounds());
90d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes    }
91d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes
92d8ae10da39a28468fad19ed564799c52354a8d1fChris Banes    @Test
9389d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes    public void testDrawableWrapOnlyWrapsOnce() {
9489d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes        final Drawable wrappedDrawable = DrawableCompat.wrap(new GradientDrawable());
9589d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes        assertSame(wrappedDrawable, DrawableCompat.wrap(wrappedDrawable));
9689d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes    }
9789d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes
98a0af9ab1fbfa7f4e1c1d90278ec3ff3167a7ec60Chris Banes    @Test
994da36b0dfa8436b197314094337fa3102fcca1bcChris Banes    public void testWrapMutatedDrawableHasConstantState() {
1004da36b0dfa8436b197314094337fa3102fcca1bcChris Banes        // First create a Drawable, and mutated it so that it has a constant state
1014da36b0dfa8436b197314094337fa3102fcca1bcChris Banes        Drawable drawable = new GradientDrawable();
1024da36b0dfa8436b197314094337fa3102fcca1bcChris Banes        drawable = drawable.mutate();
1034da36b0dfa8436b197314094337fa3102fcca1bcChris Banes        assertNotNull(drawable.getConstantState());
1044da36b0dfa8436b197314094337fa3102fcca1bcChris Banes
1054da36b0dfa8436b197314094337fa3102fcca1bcChris Banes        // Now wrap and assert that the wrapper also returns a constant state
1064da36b0dfa8436b197314094337fa3102fcca1bcChris Banes        final Drawable wrapper = DrawableCompat.wrap(drawable);
1074da36b0dfa8436b197314094337fa3102fcca1bcChris Banes        assertNotNull(wrapper.getConstantState());
1084da36b0dfa8436b197314094337fa3102fcca1bcChris Banes    }
1094da36b0dfa8436b197314094337fa3102fcca1bcChris Banes
110134f9096b97a77898c34c4f4751c2fb687b191feChris Banes    @Test
111c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes    public void testWrappedDrawableHasCallbackSet() {
112c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        // First create a Drawable
113c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        final Drawable drawable = new GradientDrawable();
114c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes
115c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        // Now wrap it and set a mock as the wrapper's callback
116c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        final Drawable wrapper = DrawableCompat.wrap(drawable);
117c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        final Drawable.Callback mockCallback = mock(Drawable.Callback.class);
118c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        wrapper.setCallback(mockCallback);
119c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes
120c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        // Now make the wrapped drawable invalidate itself
121c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        drawable.invalidateSelf();
122c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes
123c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        // ...and verify that the wrapper calls to be invalidated
124c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes        verify(mockCallback, times(1)).invalidateDrawable(wrapper);
125c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes    }
126c3b9589f61cbfda8c60344a47f8f87c0ded98554Chris Banes
1275f5ffb9bea7e6db394d6879f37ab1aadb8d2fdebChris Banes    @Test
128be678137d44778590a6220ae0ef13649e83363a9Chris Banes    public void testDoesNotWrapTintAwareDrawable() {
129be678137d44778590a6220ae0ef13649e83363a9Chris Banes        final TestTintAwareDrawable tintAwareDrawable = new TestTintAwareDrawable();
130be678137d44778590a6220ae0ef13649e83363a9Chris Banes        final Drawable wrapped = DrawableCompat.wrap(tintAwareDrawable);
131be678137d44778590a6220ae0ef13649e83363a9Chris Banes        // Assert that the tint aware drawable was not wrapped
132be678137d44778590a6220ae0ef13649e83363a9Chris Banes        assertSame(tintAwareDrawable, wrapped);
133be678137d44778590a6220ae0ef13649e83363a9Chris Banes    }
134be678137d44778590a6220ae0ef13649e83363a9Chris Banes
1355f5ffb9bea7e6db394d6879f37ab1aadb8d2fdebChris Banes    @Test
136be678137d44778590a6220ae0ef13649e83363a9Chris Banes    public void testTintAwareDrawableGetsTintCallsDirectly() {
137be678137d44778590a6220ae0ef13649e83363a9Chris Banes        final TestTintAwareDrawable d = mock(TestTintAwareDrawable.class);
138be678137d44778590a6220ae0ef13649e83363a9Chris Banes
139be678137d44778590a6220ae0ef13649e83363a9Chris Banes        final ColorStateList tint = ColorStateList.valueOf(Color.BLACK);
140be678137d44778590a6220ae0ef13649e83363a9Chris Banes        final PorterDuff.Mode tintMode = PorterDuff.Mode.DST;
141be678137d44778590a6220ae0ef13649e83363a9Chris Banes
142be678137d44778590a6220ae0ef13649e83363a9Chris Banes        // Now set the tint list and mode using DrawableCompat
143be678137d44778590a6220ae0ef13649e83363a9Chris Banes        DrawableCompat.setTintList(d, tint);
144be678137d44778590a6220ae0ef13649e83363a9Chris Banes        DrawableCompat.setTintMode(d, tintMode);
145be678137d44778590a6220ae0ef13649e83363a9Chris Banes
146be678137d44778590a6220ae0ef13649e83363a9Chris Banes        // Verify that the calls were directly on to the TintAwareDrawable
147be678137d44778590a6220ae0ef13649e83363a9Chris Banes        verify(d).setTintList(tint);
148be678137d44778590a6220ae0ef13649e83363a9Chris Banes        verify(d).setTintMode(tintMode);
149be678137d44778590a6220ae0ef13649e83363a9Chris Banes    }
150be678137d44778590a6220ae0ef13649e83363a9Chris Banes
15189d63e9cbc1daf9e04ba6261cfd141e6dd68ec63Chris Banes}