143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar *
443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * you may not use this file except in compliance with the License.
643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * You may obtain a copy of the License at
743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar *
843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar *
1043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * Unless required by applicable law or agreed to in writing, software
1143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
1243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * See the License for the specific language governing permissions and
1443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * limitations under the License.
1543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar */
1643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.recyclerview.widget;
1843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
1943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport static android.view.View.MeasureSpec.AT_MOST;
2043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport static android.view.View.MeasureSpec.EXACTLY;
2143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport static android.view.View.MeasureSpec.UNSPECIFIED;
2243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport static android.view.View.MeasureSpec.makeMeasureSpec;
2343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
2443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport android.graphics.Rect;
2543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport android.support.test.InstrumentationRegistry;
26754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.SmallTest;
2743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport android.view.View;
2843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
2943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.hamcrest.CoreMatchers;
3043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.hamcrest.MatcherAssert;
3143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.Before;
3243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.Test;
3343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.runner.RunWith;
3443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.runners.Parameterized;
3543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
3643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport java.util.Arrays;
3743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport java.util.List;
3843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
3943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar@RunWith(Parameterized.class)
4043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar@SmallTest
413f8f2df1dc73b4936b8f77ec4acdae7bb4950539Aurimas Liutikaspublic class DefaultMeasureSpecTest {
4243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private final int mWSpec;
4343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private final int mHSpec;
4443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private int mExpectedW;
4543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private int mExpectedH;
4643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private final Rect mPadding;
4743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    RecyclerView mRecyclerView;
4843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
4943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Before
5043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void setUp() throws Exception {
513f8f2df1dc73b4936b8f77ec4acdae7bb4950539Aurimas Liutikas        mRecyclerView = new RecyclerView(InstrumentationRegistry.getContext());
5243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mPadding != null) {
5343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right, mPadding.bottom);
5443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
5543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
5643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
5743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Parameterized.Parameters(name = "{0}")
5843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public static List<Object[]> param() {
5943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        List<Object[]> params = Arrays.asList(
6043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(20, EXACTLY), 10,
61abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        20, new Rect(0, 0, 0, 0)},
6243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, AT_MOST), 10,
63abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        0, new Rect(0, 0, 0, 0)},
6443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, AT_MOST), makeMeasureSpec(100, EXACTLY), 0,
65abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        100, new Rect(0, 0, 0, 0)},
6643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, UNSPECIFIED),
67abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        10, 0, new Rect(0, 0, 0, 0)},
6843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, UNSPECIFIED), makeMeasureSpec(100, EXACTLY),
69abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        0, 100, new Rect(0, 0, 0, 0)},
7043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(20, EXACTLY), 10,
7143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        20, new Rect(39, 50, 34, 23)},
7243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, AT_MOST), 10,
7343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        50, new Rect(3, 35, 3, 15)},
7443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, AT_MOST), 10,
7543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        100, new Rect(3, 350, 3, 15)},
7643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
7743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, AT_MOST), makeMeasureSpec(100, EXACTLY), 10,
7843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        100, new Rect(15, 500, 5, 30)},
7943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, AT_MOST), makeMeasureSpec(100, EXACTLY), 5,
8043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        100, new Rect(3, 500, 2, 30)},
8143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, UNSPECIFIED),
8243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        10, 20, new Rect(500, 15, 30, 5)},
8343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, UNSPECIFIED), makeMeasureSpec(100, EXACTLY),
8443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        45, 100, new Rect(15, 400, 30, 5)}
8543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        );
8643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        for (Object[] param : params) {
8743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            param[0] = "width: " + log((Integer) param[1]) + ", height:" + log((Integer) param[2]);
88abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar            param[0] = param[0] + ", padding:" + param[5];
8943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
9043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        return params;
9143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
9243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
9343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public DefaultMeasureSpecTest(@SuppressWarnings("UnusedParameters") String ignored,
9443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            int wSpec, int hSpec, int expectedW, int expectedH, Rect padding) {
9543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mWSpec = wSpec;
9643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mHSpec = hSpec;
9743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mExpectedW = expectedW;
9843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mExpectedH = expectedH;
9943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        this.mPadding = padding;
10043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
10143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
10243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
10343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithSmallerMinWidth() {
10443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumWidth(Math.max(0, mExpectedW - 5));
10543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
10643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
10743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
10843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
10943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithSmallerMinHeight() {
11043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumHeight(Math.max(0, mExpectedH - 5));
11143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
11243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
11343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
11443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
11543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithLargerMinHeight() {
11643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumHeight(mExpectedH + 5);
11743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        int mode = View.MeasureSpec.getMode(mHSpec);
11843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        switch (mode) {
11943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case UNSPECIFIED:
12043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedH += 5;
12143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
12243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case AT_MOST:
12343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedH = Math.min(View.MeasureSpec.getSize(mHSpec), mExpectedH + 5);
12443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
12543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
12643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
12743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
12843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
12943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
13043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithLargerMinWidth() {
13143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumWidth(mExpectedW + 5);
13243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        int mode = View.MeasureSpec.getMode(mWSpec);
13343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        switch (mode) {
13443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case UNSPECIFIED:
13543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedW += 5;
13643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
13743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case AT_MOST:
13843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedW = Math.min(View.MeasureSpec.getSize(mWSpec), mExpectedW + 5);
13943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
14043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
14143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
14243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
14343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
14443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
14543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void runTest() {
14643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.defaultOnMeasure(mWSpec, mHSpec);
14743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        MatcherAssert.assertThat("measured width", mRecyclerView.getMeasuredWidth(),
14843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                CoreMatchers.is(mExpectedW));
14943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        MatcherAssert.assertThat("measured height", mRecyclerView.getMeasuredHeight(),
15043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                CoreMatchers.is(mExpectedH));
15143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
15243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
15343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private static String log(int spec) {
15443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        final int size = View.MeasureSpec.getSize(spec);
15543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        int mode = View.MeasureSpec.getMode(spec);
15643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mode == View.MeasureSpec.AT_MOST) {
15743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            return "at most " + size;
15843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
15943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mode == View.MeasureSpec.UNSPECIFIED) {
16043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            return "unspecified " + size;
16143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
16243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mode == View.MeasureSpec.EXACTLY) {
16343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            return "exactly " + size;
16443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
16543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        return "?? " + size;
16643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
16743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar}
168