GridLayoutManagerBaseConfigSetTest.java revision 4143554adb9b31b700b6876a251a64419e6111e2
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v7.widget;
18
19import org.junit.Test;
20import org.junit.runner.RunWith;
21import org.junit.runners.Parameterized;
22import android.support.v7.widget.BaseGridLayoutManagerTest.Config;
23import android.util.Log;
24import android.view.View;
25import android.view.ViewGroup;
26
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.BitSet;
30import java.util.List;
31
32import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL;
33import static android.support.v7.widget.LinearLayoutManager.VERTICAL;
34import static org.junit.Assert.assertEquals;
35import static org.junit.Assert.assertNotNull;
36import static org.junit.Assert.assertSame;
37import static org.junit.Assert.assertTrue;
38
39@RunWith(Parameterized.class)
40public class GridLayoutManagerBaseConfigSetTest extends BaseGridLayoutManagerTest {
41    @Parameterized.Parameters(name = "{0}")
42    public static List<Config> params() {
43        return createBaseVariations();
44    }
45
46    private final Config mConfig;
47
48    public GridLayoutManagerBaseConfigSetTest(Config config) {
49        mConfig = config;
50    }
51
52    @Test
53    public void scrollBackAndPreservePositions() throws Throwable {
54        Config config = (Config) mConfig.clone();
55        config.mItemCount = 150;
56        scrollBackAndPreservePositionsTest(config);
57    }
58
59    public void scrollBackAndPreservePositionsTest(final Config config) throws Throwable {
60        final RecyclerView rv = setupBasic(config);
61        for (int i = 1; i < mAdapter.getItemCount(); i += config.mSpanCount + 2) {
62            mAdapter.setFullSpan(i);
63        }
64        waitForFirstLayout(rv);
65        final int[] globalPositions = new int[mAdapter.getItemCount()];
66        Arrays.fill(globalPositions, Integer.MIN_VALUE);
67        final int scrollStep = (mGlm.mOrientationHelper.getTotalSpace() / 20)
68                * (config.mReverseLayout ? -1 : 1);
69        final String logPrefix = config.toString();
70        final int[] globalPos = new int[1];
71        runTestOnUiThread(new Runnable() {
72            @Override
73            public void run() {
74                assertSame("test sanity", mRecyclerView, rv);
75                int globalScrollPosition = 0;
76                int visited = 0;
77                while (visited < mAdapter.getItemCount()) {
78                    for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
79                        View child = mRecyclerView.getChildAt(i);
80                        final int pos = mRecyclerView.getChildLayoutPosition(child);
81                        if (globalPositions[pos] != Integer.MIN_VALUE) {
82                            continue;
83                        }
84                        visited++;
85                        GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
86                                child.getLayoutParams();
87                        if (config.mReverseLayout) {
88                            globalPositions[pos] = globalScrollPosition +
89                                    mGlm.mOrientationHelper.getDecoratedEnd(child);
90                        } else {
91                            globalPositions[pos] = globalScrollPosition +
92                                    mGlm.mOrientationHelper.getDecoratedStart(child);
93                        }
94                        assertEquals(logPrefix + " span index should match",
95                                mGlm.getSpanSizeLookup().getSpanIndex(pos, mGlm.getSpanCount()),
96                                lp.getSpanIndex());
97                    }
98                    int scrolled = mGlm.scrollBy(scrollStep,
99                            mRecyclerView.mRecycler, mRecyclerView.mState);
100                    globalScrollPosition += scrolled;
101                    if (scrolled == 0) {
102                        assertEquals(
103                                logPrefix + " If scroll is complete, all views should be visited",
104                                visited, mAdapter.getItemCount());
105                    }
106                }
107                if (DEBUG) {
108                    Log.d(TAG, "done recording positions " + Arrays.toString(globalPositions));
109                }
110                globalPos[0] = globalScrollPosition;
111            }
112        });
113        checkForMainThreadException();
114        // test sanity, ensure scroll happened
115        runTestOnUiThread(new Runnable() {
116            @Override
117            public void run() {
118                final int childCount = mGlm.getChildCount();
119                final BitSet expectedPositions = new BitSet();
120                for (int i = 0; i < childCount; i ++) {
121                    expectedPositions.set(mAdapter.getItemCount() - i - 1);
122                }
123                for (int i = 0; i <childCount; i ++) {
124                    final View view = mGlm.getChildAt(i);
125                    int position = mGlm.getPosition(view);
126                    assertTrue("child position should be in last page", expectedPositions.get(position));
127                }
128            }
129        });
130        getInstrumentation().waitForIdleSync();
131        runTestOnUiThread(new Runnable() {
132            @Override
133            public void run() {
134                int globalScrollPosition = globalPos[0];
135                // now scroll back and make sure global positions match
136                BitSet shouldTest = new BitSet(mAdapter.getItemCount());
137                shouldTest.set(0, mAdapter.getItemCount() - 1, true);
138                String assertPrefix = config
139                        + " global pos must match when scrolling in reverse for position ";
140                int scrollAmount = Integer.MAX_VALUE;
141                while (!shouldTest.isEmpty() && scrollAmount != 0) {
142                    for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
143                        View child = mRecyclerView.getChildAt(i);
144                        int pos = mRecyclerView.getChildLayoutPosition(child);
145                        if (!shouldTest.get(pos)) {
146                            continue;
147                        }
148                        GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)
149                                child.getLayoutParams();
150                        shouldTest.clear(pos);
151                        int globalPos;
152                        if (config.mReverseLayout) {
153                            globalPos = globalScrollPosition +
154                                    mGlm.mOrientationHelper.getDecoratedEnd(child);
155                        } else {
156                            globalPos = globalScrollPosition +
157                                    mGlm.mOrientationHelper.getDecoratedStart(child);
158                        }
159                        assertEquals(assertPrefix + pos,
160                                globalPositions[pos], globalPos);
161                        assertEquals("span index should match",
162                                mGlm.getSpanSizeLookup().getSpanIndex(pos, mGlm.getSpanCount()),
163                                lp.getSpanIndex());
164                    }
165                    scrollAmount = mGlm.scrollBy(-scrollStep,
166                            mRecyclerView.mRecycler, mRecyclerView.mState);
167                    globalScrollPosition += scrollAmount;
168                }
169                assertTrue("all views should be seen", shouldTest.isEmpty());
170            }
171        });
172        checkForMainThreadException();
173    }
174}
175