14143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
34143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *
44143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
54143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * you may not use this file except in compliance with the License.
64143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * You may obtain a copy of the License at
74143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *
84143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
94143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar *
104143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * Unless required by applicable law or agreed to in writing, software
114143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
124143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * See the License for the specific language governing permissions and
144143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * limitations under the License.
154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar */
16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.recyclerview.widget;
174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
186b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyarimport static org.hamcrest.CoreMatchers.is;
196b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyarimport static org.hamcrest.MatcherAssert.assertThat;
206b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyarimport static org.junit.Assert.assertEquals;
216b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyarimport static org.junit.Assert.assertNull;
226b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyarimport static org.junit.Assert.assertTrue;
236b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar
2429f43aa1bb825a46fd7cf161a0cd1d5353aaf821Yigit Boyarimport android.app.Activity;
254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.graphics.Color;
264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.graphics.Rect;
274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.util.Log;
284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.view.Gravity;
294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.view.View;
304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.view.ViewGroup;
314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport android.widget.TextView;
324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
33c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.annotation.NonNull;
34c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.annotation.Nullable;
35c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.collection.LongSparseArray;
36c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas
37f3844451301cb14ca885e125cb27f108a834c386Yigit Boyarimport org.hamcrest.CoreMatchers;
38959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport java.util.ArrayList;
404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport java.util.Collections;
414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarimport java.util.List;
424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
434143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar/**
444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * Class to test any generic wrap content behavior.
454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * It does so by running the same view scenario twice. Once with match parent setup to record all
464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * dimensions and once with wrap_content setup. Then compares all child locations & ids +
474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar * RecyclerView size.
484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar */
494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarabstract public class BaseWrapContentTest extends BaseRecyclerViewInstrumentationTest {
504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static final boolean DEBUG = false;
524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static final String TAG = "WrapContentTest";
534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    RecyclerView.LayoutManager mLayoutManager;
544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    TestAdapter mTestAdapter;
564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    LoggingItemAnimator mLoggingItemAnimator;
584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    boolean mIsWrapContent;
604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    protected final WrapContentConfig mWrapContentConfig;
624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    public BaseWrapContentTest(WrapContentConfig config) {
644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        mWrapContentConfig = config;
654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    abstract RecyclerView.LayoutManager createLayoutManager();
684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
69f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar    void unspecifiedWithHintTest(boolean horizontal) throws Throwable {
70f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        final int itemHeight = 20;
71f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        final int itemWidth = 15;
72f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        RecyclerView.LayoutManager layoutManager = createLayoutManager();
73f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        WrappedRecyclerView rv = createRecyclerView(getActivity());
74f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        TestAdapter testAdapter = new TestAdapter(20) {
75f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            @Override
768a11e6829c522aa1efcc903afa4c01d337082eabChris Craik            public void onBindViewHolder(@NonNull TestViewHolder holder,
77f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar                    int position) {
78f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar                super.onBindViewHolder(holder, position);
79f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar                holder.itemView.setLayoutParams(new ViewGroup.LayoutParams(itemWidth, itemHeight));
80f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            }
81f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        };
82f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        rv.setLayoutManager(layoutManager);
83f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        rv.setAdapter(testAdapter);
84f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        TestedFrameLayout.FullControlLayoutParams lp =
85f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar                new TestedFrameLayout.FullControlLayoutParams(0, 0);
86f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        if (horizontal) {
87f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            lp.wSpec = View.MeasureSpec.makeMeasureSpec(25, View.MeasureSpec.UNSPECIFIED);
88f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            lp.hSpec = View.MeasureSpec.makeMeasureSpec(50, View.MeasureSpec.AT_MOST);
89f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        } else {
90f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            lp.hSpec = View.MeasureSpec.makeMeasureSpec(25, View.MeasureSpec.UNSPECIFIED);
91f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            lp.wSpec = View.MeasureSpec.makeMeasureSpec(50, View.MeasureSpec.AT_MOST);
92f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        }
93f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        rv.setLayoutParams(lp);
94f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        setRecyclerView(rv);
95f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        rv.waitUntilLayout();
96f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar
97f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        // we don't assert against the given size hint because LM will still ask for more if it
98f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        // lays out more children. This is the correct behavior because the spec is not AT_MOST,
99f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        // it is UNSPECIFIED.
100f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        if (horizontal) {
101f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            int expectedWidth = rv.getPaddingLeft() + rv.getPaddingRight() + itemWidth;
102f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            while (expectedWidth < 25) {
103f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar                expectedWidth += itemWidth;
104f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            }
105f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            assertThat(rv.getWidth(), CoreMatchers.is(expectedWidth));
106f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        } else {
107f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            int expectedHeight = rv.getPaddingTop() + rv.getPaddingBottom() + itemHeight;
108f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            while (expectedHeight < 25) {
109f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar                expectedHeight += itemHeight;
110f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            }
111f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar            assertThat(rv.getHeight(), CoreMatchers.is(expectedHeight));
112f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar        }
113f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar    }
114f3844451301cb14ca885e125cb27f108a834c386Yigit Boyar
1154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    protected void testScenerio(Scenario scenario) throws Throwable {
116ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas        TestedFrameLayout.FullControlLayoutParams
117ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                matchParent = new TestedFrameLayout.FullControlLayoutParams(
1184143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                ViewGroup.LayoutParams.MATCH_PARENT,
1194143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                ViewGroup.LayoutParams.MATCH_PARENT);
120ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas        TestedFrameLayout.FullControlLayoutParams
121ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                wrapContent = new TestedFrameLayout.FullControlLayoutParams(
1224143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                ViewGroup.LayoutParams.WRAP_CONTENT,
1234143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                ViewGroup.LayoutParams.WRAP_CONTENT);
1244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        if (mWrapContentConfig.isUnlimitedHeight()) {
1254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            wrapContent.hSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
1264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        if (mWrapContentConfig.isUnlimitedWidth()) {
1284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            wrapContent.wSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
1294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        mIsWrapContent = false;
1324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        List<Snapshot> s1 = runScenario(scenario, matchParent, null);
1334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        mIsWrapContent = true;
1344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1354143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        List<Snapshot> s2 = runScenario(scenario, wrapContent, s1);
1364143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        assertEquals("test sanity", s1.size(), s2.size());
1374143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1384143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        for (int i = 0; i < s1.size(); i++) {
1394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Snapshot step1 = s1.get(i);
1404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Snapshot step2 = s2.get(i);
1414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            step1.assertSame(step2, i);
1424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1434143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
1444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
1454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    public List<Snapshot> runScenario(Scenario scenario, ViewGroup.LayoutParams lp,
1464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            @Nullable List<Snapshot> compareWith)
1474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            throws Throwable {
1484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        removeRecyclerView();
1494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Item.idCounter.set(0);
1504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        List<Snapshot> result = new ArrayList<>();
1514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        RecyclerView.LayoutManager layoutManager = scenario.createLayoutManager();
1524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        WrappedRecyclerView recyclerView = new WrappedRecyclerView(getActivity());
1534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setBackgroundColor(Color.rgb(0, 0, 255));
1544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setLayoutManager(layoutManager);
1554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setLayoutParams(lp);
1564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        mLayoutManager = layoutManager;
1574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        mTestAdapter = new TestAdapter(scenario.getSeedAdapterSize());
1584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setAdapter(mTestAdapter);
1594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        mLoggingItemAnimator = new LoggingItemAnimator();
1604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setItemAnimator(mLoggingItemAnimator);
1614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        setRecyclerView(recyclerView);
1624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.waitUntilLayout();
1634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        int stepIndex = 0;
1644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        for (Step step : scenario.mStepList) {
1654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mLoggingItemAnimator.reset();
1664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            step.onRun();
1674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            recyclerView.waitUntilLayout();
1684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            recyclerView.waitUntilAnimations();
1694143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Snapshot snapshot = takeSnapshot();
1704143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (mIsWrapContent) {
1714143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                snapshot.assertRvSize();
1724143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
1734143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            result.add(snapshot);
1744143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (compareWith != null) {
1754143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                compareWith.get(stepIndex).assertSame(snapshot, stepIndex);
1764143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
1774143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            stepIndex++;
1784143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1794143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.waitUntilLayout();
1804143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.waitUntilAnimations();
1814143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Snapshot snapshot = takeSnapshot();
1824143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        if (mIsWrapContent) {
1834143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            snapshot.assertRvSize();
1844143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1854143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        result.add(snapshot);
1864143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        if (compareWith != null) {
1874143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            compareWith.get(stepIndex).assertSame(snapshot, stepIndex);
1884143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
1894143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        return result;
1904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
1914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
19229f43aa1bb825a46fd7cf161a0cd1d5353aaf821Yigit Boyar    protected WrappedRecyclerView createRecyclerView(Activity activity) {
19329f43aa1bb825a46fd7cf161a0cd1d5353aaf821Yigit Boyar        return new WrappedRecyclerView(getActivity());
19429f43aa1bb825a46fd7cf161a0cd1d5353aaf821Yigit Boyar    }
19529f43aa1bb825a46fd7cf161a0cd1d5353aaf821Yigit Boyar
1964143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    void layoutAndCheck(TestedFrameLayout.FullControlLayoutParams lp,
1974143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            BaseWrapContentWithAspectRatioTest.WrapContentAdapter adapter, Rect[] expected,
1984143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            int width, int height) throws Throwable {
19929f43aa1bb825a46fd7cf161a0cd1d5353aaf821Yigit Boyar        WrappedRecyclerView recyclerView = createRecyclerView(getActivity());
2004143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setBackgroundColor(Color.rgb(0, 0, 255));
2014143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setLayoutManager(createLayoutManager());
2024143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setAdapter(adapter);
2034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.setLayoutParams(lp);
2046b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        Rect padding = mWrapContentConfig.padding;
205de8a5de43b647f9b61f4859a22a0ce59155f442aYigit Boyar        recyclerView.setPadding(padding.left, padding.top, padding.right, padding.bottom);
2064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        setRecyclerView(recyclerView);
2074143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        recyclerView.waitUntilLayout();
2084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Snapshot snapshot = takeSnapshot();
2094143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        int index = 0;
2106b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        Rect tmp = new Rect();
2114143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        for (BaseWrapContentWithAspectRatioTest.MeasureBehavior behavior : adapter.behaviors) {
2126b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar            tmp.set(expected[index]);
2136b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar            tmp.offset(padding.left, padding.top);
2144143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertThat("behavior " + index, snapshot.mChildCoordinates.get(behavior.getId()),
2156b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar                    is(tmp));
2164143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            index ++;
2174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2184143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Rect boundingBox = new Rect(0, 0, 0, 0);
2194143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        for (Rect rect : expected) {
2204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            boundingBox.union(rect);
2214143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2226b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        assertThat(recyclerView.getWidth(), is(width + padding.left + padding.right));
2236b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        assertThat(recyclerView.getHeight(), is(height + padding.top + padding.bottom));
2244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
2254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    abstract protected int getVerticalGravity(RecyclerView.LayoutManager layoutManager);
2284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    abstract protected int getHorizontalGravity(RecyclerView.LayoutManager layoutManager);
2304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    protected Snapshot takeSnapshot() throws Throwable {
2324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Snapshot snapshot = new Snapshot(mRecyclerView, mLoggingItemAnimator,
2334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                getHorizontalGravity(mLayoutManager), getVerticalGravity(mLayoutManager));
2344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        return snapshot;
2354143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
2364143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2374143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    abstract class Scenario {
2384143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        ArrayList<Step> mStepList = new ArrayList<>();
2404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public Scenario(Step... steps) {
2424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Collections.addAll(mStepList, steps);
2434143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public int getSeedAdapterSize() {
2464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return 10;
2474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public RecyclerView.LayoutManager createLayoutManager() {
2504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return BaseWrapContentTest.this.createLayoutManager();
2514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
2524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
2534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    abstract static class Step {
2554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        abstract void onRun() throws Throwable;
2574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
2584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    class Snapshot {
2604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Rect mRawChildrenBox = new Rect();
2624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Rect mRvSize = new Rect();
2644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Rect mRvPadding = new Rect();
2664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        Rect mRvParentSize = new Rect();
2684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2694143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        LongSparseArray<Rect> mChildCoordinates = new LongSparseArray<>();
2704143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2714143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        LongSparseArray<String> mAppear = new LongSparseArray<>();
2724143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2734143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        LongSparseArray<String> mDisappear = new LongSparseArray<>();
2744143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2754143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        LongSparseArray<String> mPersistent = new LongSparseArray<>();
2764143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2774143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        LongSparseArray<String> mChanged = new LongSparseArray<>();
2784143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2794143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        int mVerticalGravity;
2804143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2814143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        int mHorizontalGravity;
2824143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2834143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        int mOffsetX, mOffsetY;// how much we should offset children
2844143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
2854143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public Snapshot(RecyclerView recyclerView, LoggingItemAnimator loggingItemAnimator,
2864143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                int horizontalGravity, int verticalGravity)
2874143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                throws Throwable {
2884143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mRvSize = getViewBounds(recyclerView);
2894143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mRvParentSize = getViewBounds((View) recyclerView.getParent());
2904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mRvPadding = new Rect(recyclerView.getPaddingLeft(), recyclerView.getPaddingTop(),
2914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
2924143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mVerticalGravity = verticalGravity;
2934143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mHorizontalGravity = horizontalGravity;
2944143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (mVerticalGravity == Gravity.TOP) {
2954143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                mOffsetY = 0;
2964143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            } else {
2974143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                mOffsetY = mRvParentSize.bottom - mRvSize.bottom;
2984143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
2994143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3004143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (mHorizontalGravity == Gravity.LEFT) {
3014143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                mOffsetX = 0;
3024143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            } else {
3034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                mOffsetX = mRvParentSize.right - mRvSize.right;
3044143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3054143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            collectChildCoordinates(recyclerView);
3064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (loggingItemAnimator != null) {
3074143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                collectInto(mAppear, loggingItemAnimator.mAnimateAppearanceList);
3084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                collectInto(mDisappear, loggingItemAnimator.mAnimateDisappearanceList);
3094143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                collectInto(mPersistent, loggingItemAnimator.mAnimatePersistenceList);
3104143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                collectInto(mChanged, loggingItemAnimator.mAnimateChangeList);
3114143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3124143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3134143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3144143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public boolean doesChildrenFitVertically() {
3154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return mRawChildrenBox.top >= mRvPadding.top
3164143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    && mRawChildrenBox.bottom <= mRvSize.bottom - mRvPadding.bottom;
3174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3184143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3194143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public boolean doesChildrenFitHorizontally() {
3204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return mRawChildrenBox.left >= mRvPadding.left
3214143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    && mRawChildrenBox.right <= mRvSize.right - mRvPadding.right;
3224143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3234143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void assertSame(Snapshot other, int step) {
3254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (mWrapContentConfig.isUnlimitedHeight() &&
3264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    (!doesChildrenFitVertically() || !other.doesChildrenFitVertically())) {
3274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                if (DEBUG) {
3284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    Log.d(TAG, "cannot assert coordinates because it does not fit vertically");
3294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                }
3304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return;
3314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (mWrapContentConfig.isUnlimitedWidth() &&
3334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    (!doesChildrenFitHorizontally() || !other.doesChildrenFitHorizontally())) {
3344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                if (DEBUG) {
3354143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    Log.d(TAG, "cannot assert coordinates because it does not fit horizontally");
3364143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                }
3374143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return;
3384143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertMap("child coordinates. step:" + step, mChildCoordinates,
3404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    other.mChildCoordinates);
3414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (mWrapContentConfig.isUnlimitedHeight() || mWrapContentConfig.isUnlimitedWidth()) {
3424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return;//cannot assert animatinos in unlimited size
3434143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertMap("appearing step:" + step, mAppear, other.mAppear);
3454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertMap("disappearing step:" + step, mDisappear, other.mDisappear);
3464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertMap("persistent step:" + step, mPersistent, other.mPersistent);
3474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertMap("changed step:" + step, mChanged, other.mChanged);
3484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private void assertMap(String prefix, LongSparseArray<?> map1, LongSparseArray<?> map2) {
3514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            StringBuilder logBuilder = new StringBuilder();
3524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logBuilder.append(prefix).append("\n");
3534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logBuilder.append("map1").append("\n");
3544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logInto(map1, logBuilder);
3554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logBuilder.append("map2").append("\n");
3564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logInto(map2, logBuilder);
3574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            final String log = logBuilder.toString();
3584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertEquals(log + " same size", map1.size(), map2.size());
3594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            for (int i = 0; i < map1.size(); i++) {
3604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                assertAtIndex(log, map1, map2, i);
3614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private void assertAtIndex(String prefix, LongSparseArray<?> map1, LongSparseArray<?> map2,
3654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                int index) {
3664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            long key1 = map1.keyAt(index);
3674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            long key2 = map2.keyAt(index);
3684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertEquals(prefix + "key mismatch at index " + index, key1, key2);
3694143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Object value1 = map1.valueAt(index);
3704143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Object value2 = map2.valueAt(index);
3714143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            assertEquals(prefix + " value mismatch at index " + index, value1, value2);
3724143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3734143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3744143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private void logInto(LongSparseArray<?> map, StringBuilder sb) {
3754143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            for (int i = 0; i < map.size(); i++) {
3764143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                long key = map.keyAt(i);
3774143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                Object value = map.valueAt(i);
3784143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                sb.append(key).append(" : ").append(value).append("\n");
3794143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
3804143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3814143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3824143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
3834143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public String toString() {
3844143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            StringBuilder sb = new StringBuilder("Snapshot{\n");
3854143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            sb.append("child coordinates:\n");
3864143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logInto(mChildCoordinates, sb);
3874143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            sb.append("appear animations:\n");
3884143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logInto(mAppear, sb);
3894143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            sb.append("disappear animations:\n");
3904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logInto(mDisappear, sb);
3914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            sb.append("change animations:\n");
3924143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logInto(mChanged, sb);
3934143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            sb.append("persistent animations:\n");
3944143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            logInto(mPersistent, sb);
3954143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            sb.append("}");
3964143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return sb.toString();
3974143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
3984143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
3994143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
4004143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public int hashCode() {
4014143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            int result = mChildCoordinates.hashCode();
4024143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            result = 31 * result + mAppear.hashCode();
4034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            result = 31 * result + mDisappear.hashCode();
4044143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            result = 31 * result + mPersistent.hashCode();
4054143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            result = 31 * result + mChanged.hashCode();
4064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return result;
4074143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4094143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private void collectInto(
4104143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                LongSparseArray<String> target,
4114143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                List<? extends BaseRecyclerViewAnimationsTest.AnimateLogBase> list) {
4124143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            for (BaseRecyclerViewAnimationsTest.AnimateLogBase base : list) {
4134143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                long id = getItemId(base.viewHolder);
4144143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                assertNull(target.get(id));
4154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                target.put(id, log(base));
4164143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
4174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4184143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4194143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private String log(BaseRecyclerViewAnimationsTest.AnimateLogBase base) {
4204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return base.getClass().getSimpleName() +
4214143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    ((TextView) base.viewHolder.itemView).getText() + ": " +
4224143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    "[pre:" + log(base.postInfo) +
4234143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    ", post:" + log(base.postInfo) + "]";
4244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private String log(BaseRecyclerViewAnimationsTest.LoggingInfo postInfo) {
4274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (postInfo == null) {
4284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return "?";
4294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
4304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return "PI[flags: " + postInfo.changeFlags
4314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    + ",l:" + (postInfo.left + mOffsetX)
4324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    + ",t:" + (postInfo.top + mOffsetY)
4334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    + ",r:" + (postInfo.right + mOffsetX)
4344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    + ",b:" + (postInfo.bottom + mOffsetY) + "]";
4354143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4364143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4374143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        void collectChildCoordinates(RecyclerView recyclerView) throws Throwable {
4384143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            mRawChildrenBox = new Rect(0, 0, 0, 0);
4394143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            final int childCount = recyclerView.getChildCount();
4404143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            for (int i = 0; i < childCount; i++) {
4414143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                View child = recyclerView.getChildAt(i);
4424143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                Rect childBounds = getChildBounds(recyclerView, child, true);
4434143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                mRawChildrenBox.union(getChildBounds(recyclerView, child, false));
4444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                RecyclerView.ViewHolder childViewHolder = recyclerView.getChildViewHolder(child);
4454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                mChildCoordinates.put(getItemId(childViewHolder), childBounds);
4464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
4474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private Rect getViewBounds(View view) {
4504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
4514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private Rect getChildBounds(RecyclerView recyclerView, View child, boolean offset) {
4544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
4554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams();
4564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            Rect rect = new Rect(layoutManager.getDecoratedLeft(child) - lp.leftMargin,
4574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    layoutManager.getDecoratedTop(child) - lp.topMargin,
4584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    layoutManager.getDecoratedRight(child) + lp.rightMargin,
4594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    layoutManager.getDecoratedBottom(child) + lp.bottomMargin);
4604143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (offset) {
4614143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                rect.offset(mOffsetX, mOffsetY);
4624143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
4634143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return rect;
4644143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4654143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4664143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        private long getItemId(RecyclerView.ViewHolder vh) {
4674143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (vh instanceof TestViewHolder) {
4684143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return ((TestViewHolder) vh).mBoundItem.mId;
4694143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            } else if (vh instanceof BaseWrapContentWithAspectRatioTest.WrapContentViewHolder) {
4704143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                BaseWrapContentWithAspectRatioTest.WrapContentViewHolder casted =
4714143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                        (BaseWrapContentWithAspectRatioTest.WrapContentViewHolder) vh;
4724143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                return casted.mView.mBehavior.getId();
4734143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            } else {
4744143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                throw new IllegalArgumentException("i don't support any VH");
4754143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
4764143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4774143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4784143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public void assertRvSize() {
4794143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (shouldWrapContentHorizontally()) {
4804143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                int expectedW = mRawChildrenBox.width() + mRvPadding.left + mRvPadding.right;
4814143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                assertTrue(mRvSize.width() + " <= " + expectedW, mRvSize.width() <= expectedW);
4824143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
4834143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (shouldWrapContentVertically()) {
4844143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                int expectedH = mRawChildrenBox.height() + mRvPadding.top + mRvPadding.bottom;
4854143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                assertTrue(mRvSize.height() + "<=" + expectedH, mRvSize.height() <= expectedH);
4864143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
4874143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
4884143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
4894143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4904143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    protected boolean shouldWrapContentHorizontally() {
4914143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        return true;
4924143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
4934143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4944143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    protected boolean shouldWrapContentVertically() {
4954143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        return true;
4964143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
4974143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
4984143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    static class WrapContentConfig {
4994143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5006b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        public boolean unlimitedWidth;
5016b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        public boolean unlimitedHeight;
5026b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        public Rect padding = new Rect(0, 0, 0, 0);
5034143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5044143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public WrapContentConfig(boolean unlimitedWidth, boolean unlimitedHeight) {
5054143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.unlimitedWidth = unlimitedWidth;
5064143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.unlimitedHeight = unlimitedHeight;
5074143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
5084143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5096b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        public WrapContentConfig(boolean unlimitedWidth, boolean unlimitedHeight, Rect padding) {
5106b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar            this.unlimitedWidth = unlimitedWidth;
5116b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar            this.unlimitedHeight = unlimitedHeight;
5126b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar            this.padding.set(padding);
5136b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar        }
5146b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar
5154143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public boolean isUnlimitedWidth() {
5164143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return unlimitedWidth;
5174143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
5184143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5194143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public WrapContentConfig setUnlimitedWidth(boolean unlimitedWidth) {
5204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.unlimitedWidth = unlimitedWidth;
5214143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return this;
5224143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
5234143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5244143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public boolean isUnlimitedHeight() {
5254143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return unlimitedHeight;
5264143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
5274143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5284143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public WrapContentConfig setUnlimitedHeight(boolean unlimitedHeight) {
5294143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            this.unlimitedHeight = unlimitedHeight;
5304143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return this;
5314143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
5324143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5334143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        @Override
5344143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public String toString() {
535142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas            StringBuilder sb = new StringBuilder(32);
536142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas            sb.append("Rect("); sb.append(padding.left); sb.append(",");
537142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas            sb.append(padding.top); sb.append("-"); sb.append(padding.right);
538142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas            sb.append(","); sb.append(padding.bottom); sb.append(")");
5396b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar            return "WrapContentConfig{"
5406b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar                    + "unlimitedWidth=" + unlimitedWidth
541e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas                    + ",unlimitedHeight=" + unlimitedHeight
542142ca4048bd0de39ddbc0e8981914bdff103ead3Aurimas Liutikas                    + ",padding=" + sb.toString()
5436b6a29eea7f6a212447b3cc7b45a081b609ca4b1Yigit Boyar                    + '}';
5444143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
5454143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar
5464143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        public TestedFrameLayout.FullControlLayoutParams toLayoutParams(int wDim, int hDim) {
5474143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            TestedFrameLayout.FullControlLayoutParams
5484143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    lp = new TestedFrameLayout.FullControlLayoutParams(
5494143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                    wDim, hDim);
5504143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (unlimitedWidth) {
5514143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                lp.wSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
5524143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
5534143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            if (unlimitedHeight) {
5544143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar                lp.hSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
5554143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            }
5564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar            return lp;
5574143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar        }
5584143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar    }
5594143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar}
560