143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar/*
243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar * Copyright (C) 2016 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
1743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarpackage android.support.v7.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;
2643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport android.test.AndroidTestCase;
2743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport android.test.suitebuilder.annotation.SmallTest;
2843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport android.view.View;
2943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
3043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.hamcrest.CoreMatchers;
3143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.hamcrest.MatcherAssert;
3243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.After;
3343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.Before;
3443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.Test;
3543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.runner.RunWith;
3643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport org.junit.runners.Parameterized;
3743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
3843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport java.util.Arrays;
3943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarimport java.util.List;
4043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
4143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar@RunWith(Parameterized.class)
4243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar@SmallTest
4343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyarpublic class DefaultMeasureSpecTest extends AndroidTestCase {
4443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private final int mWSpec;
4543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private final int mHSpec;
4643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private int mExpectedW;
4743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private int mExpectedH;
4843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private final Rect mPadding;
4943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    RecyclerView mRecyclerView;
5043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
5143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Before
5243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Override
5343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void setUp() throws Exception {
5443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        super.setUp();
5543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        setContext(InstrumentationRegistry.getContext());
5643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView = new RecyclerView(getContext());
5743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mPadding != null) {
5843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            mRecyclerView.setPadding(mPadding.left, mPadding.top, mPadding.right, mPadding.bottom);
5943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
6043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
6143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
6243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @After
6343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Override
6443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void tearDown() throws Exception {
6543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        super.tearDown();
6643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
6743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
6843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Parameterized.Parameters(name = "{0}")
6943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public static List<Object[]> param() {
7043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        List<Object[]> params = Arrays.asList(
7143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(20, EXACTLY), 10,
72abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        20, new Rect(0, 0, 0, 0)},
7343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, AT_MOST), 10,
74abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        0, new Rect(0, 0, 0, 0)},
7543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, AT_MOST), makeMeasureSpec(100, EXACTLY), 0,
76abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        100, new Rect(0, 0, 0, 0)},
7743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, UNSPECIFIED),
78abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        10, 0, new Rect(0, 0, 0, 0)},
7943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, UNSPECIFIED), makeMeasureSpec(100, EXACTLY),
80abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar                        0, 100, new Rect(0, 0, 0, 0)},
8143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(20, EXACTLY), 10,
8243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        20, new Rect(39, 50, 34, 23)},
8343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, AT_MOST), 10,
8443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        50, new Rect(3, 35, 3, 15)},
8543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, AT_MOST), 10,
8643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        100, new Rect(3, 350, 3, 15)},
8743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
8843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, AT_MOST), makeMeasureSpec(100, EXACTLY), 10,
8943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        100, new Rect(15, 500, 5, 30)},
9043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, AT_MOST), makeMeasureSpec(100, EXACTLY), 5,
9143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        100, new Rect(3, 500, 2, 30)},
9243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, EXACTLY), makeMeasureSpec(100, UNSPECIFIED),
9343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        10, 20, new Rect(500, 15, 30, 5)},
9443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                new Object[]{null, makeMeasureSpec(10, UNSPECIFIED), makeMeasureSpec(100, EXACTLY),
9543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                        45, 100, new Rect(15, 400, 30, 5)}
9643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        );
9743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        for (Object[] param : params) {
9843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            param[0] = "width: " + log((Integer) param[1]) + ", height:" + log((Integer) param[2]);
99abce40396e24c3cdbd606e1bf0f277629191bb8dYigit Boyar            param[0] = param[0] + ", padding:" + param[5];
10043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
10143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        return params;
10243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
10343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
10443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public DefaultMeasureSpecTest(@SuppressWarnings("UnusedParameters") String ignored,
10543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            int wSpec, int hSpec, int expectedW, int expectedH, Rect padding) {
10643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mWSpec = wSpec;
10743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mHSpec = hSpec;
10843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mExpectedW = expectedW;
10943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mExpectedH = expectedH;
11043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        this.mPadding = padding;
11143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
11243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
11343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
11443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithSmallerMinWidth() {
11543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumWidth(Math.max(0, mExpectedW - 5));
11643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
11743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
11843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
11943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
12043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithSmallerMinHeight() {
12143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumHeight(Math.max(0, mExpectedH - 5));
12243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
12343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
12443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
12543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
12643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithLargerMinHeight() {
12743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumHeight(mExpectedH + 5);
12843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        int mode = View.MeasureSpec.getMode(mHSpec);
12943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        switch (mode) {
13043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case UNSPECIFIED:
13143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedH += 5;
13243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
13343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case AT_MOST:
13443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedH = Math.min(View.MeasureSpec.getSize(mHSpec), mExpectedH + 5);
13543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
13643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
13743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
13843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
13943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
14043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
14143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void testWithLargerMinWidth() {
14243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.setMinimumWidth(mExpectedW + 5);
14343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        int mode = View.MeasureSpec.getMode(mWSpec);
14443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        switch (mode) {
14543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case UNSPECIFIED:
14643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedW += 5;
14743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
14843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            case AT_MOST:
14943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                mExpectedW = Math.min(View.MeasureSpec.getSize(mWSpec), mExpectedW + 5);
15043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                break;
15143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
15243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        runTest();
15343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
15443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
15543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    @Test
15643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    public void runTest() {
15743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        mRecyclerView.defaultOnMeasure(mWSpec, mHSpec);
15843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        MatcherAssert.assertThat("measured width", mRecyclerView.getMeasuredWidth(),
15943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                CoreMatchers.is(mExpectedW));
16043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        MatcherAssert.assertThat("measured height", mRecyclerView.getMeasuredHeight(),
16143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar                CoreMatchers.is(mExpectedH));
16243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
16343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar
16443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    private static String log(int spec) {
16543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        final int size = View.MeasureSpec.getSize(spec);
16643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        int mode = View.MeasureSpec.getMode(spec);
16743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mode == View.MeasureSpec.AT_MOST) {
16843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            return "at most " + size;
16943de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
17043de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mode == View.MeasureSpec.UNSPECIFIED) {
17143de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            return "unspecified " + size;
17243de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
17343de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        if (mode == View.MeasureSpec.EXACTLY) {
17443de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar            return "exactly " + size;
17543de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        }
17643de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar        return "?? " + size;
17743de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar    }
17843de23e6297fd4287b9c2a26f1aa04d37ba6968dYigit Boyar}
179