1a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes/*
2a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * Copyright (C) 2016 The Android Open Source Project
3a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes *
4a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * you may not use this file except in compliance with the License.
6a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * You may obtain a copy of the License at
7a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes *
8a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes *      http://www.apache.org/licenses/LICENSE-2.0
9a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes *
10a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * Unless required by applicable law or agreed to in writing, software
11a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * See the License for the specific language governing permissions and
14a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes * limitations under the License.
15a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes */
16a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
17a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banespackage android.support.design.widget;
18a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
19a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport static org.junit.Assert.assertEquals;
20a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
21a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport android.app.Instrumentation;
223c9fb156e6585049f4e8f7992542aca307f0be13Chris Banesimport android.support.design.testutils.CoordinatorLayoutUtils;
23a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport android.support.test.InstrumentationRegistry;
24a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport android.test.suitebuilder.annotation.MediumTest;
25a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport android.view.View;
26a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
27a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport org.junit.Test;
28a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport org.junit.runner.RunWith;
29a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport org.junit.runners.Parameterized;
30a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
31a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport java.util.ArrayList;
32a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport java.util.Arrays;
33a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport java.util.Collection;
34a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banesimport java.util.List;
35a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
36a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes@RunWith(Parameterized.class)
37a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes@MediumTest
38a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banespublic class CoordinatorLayoutSortTest
39a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        extends BaseInstrumentationTestCase<CoordinatorLayoutActivity> {
40a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
41a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    private static final int NUMBER_VIEWS_DEPENDENCY_SORT = 4;
42a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
43a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    /**
44a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes     * All 27 permutations of a quad-tuple containing unique values in the range 0-3
45a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes     */
46a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    @Parameterized.Parameters
47a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    public static Collection<Object[]> data() {
48a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        return Arrays.asList(new Object[][] {
49a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {0, 3, 2, 1},
50a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                {1, 0, 2, 3}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 2, 3, 0}, {1, 3, 0, 2}, {1, 3, 2, 0},
51a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                {2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {2, 3, 1, 0},
52a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                {3, 0, 1, 2}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0}
53a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        });
54a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    }
55a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
56a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    private int mFirstAddIndex;
57a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    private int mSecondAddIndex;
58a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    private int mThirdAddIndex;
59a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    private int mFourthAddIndex;
60a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
61a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    public CoordinatorLayoutSortTest(int firstIndex, int secondIndex, int thirdIndex,
62a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            int fourthIndex) {
63a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        super(CoordinatorLayoutActivity.class);
64a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        mFirstAddIndex = firstIndex;
65a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        mSecondAddIndex = secondIndex;
66a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        mThirdAddIndex = thirdIndex;
67a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        mFourthAddIndex = fourthIndex;
68a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    }
69a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
70a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    @Test
71a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    public void testDependencySortingOrder() {
72a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        final CoordinatorLayout col = mActivityTestRule.getActivity().mCoordinatorLayout;
73a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
74a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        // Let's create some views where each view depends on the previous view.
75a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        // i.e C depends on B, B depends on A, A doesn't depend on anything.
76a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        final List<View> views = new ArrayList<>();
77a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        for (int i = 0; i < NUMBER_VIEWS_DEPENDENCY_SORT; i++) {
78a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            // 65 == A in ASCII
79a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            final String label = Character.toString((char) (65 + i));
80a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            final View view = new View(col.getContext()) {
81a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                @Override
82a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                public String toString() {
83a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                    return label;
84a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                }
85a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            };
86a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
87a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            // Create a Behavior which depends on the previously added view
88a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            View dependency = i > 0 ? views.get(i - 1) : null;
893c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes            final CoordinatorLayout.Behavior<View> behavior
903c9fb156e6585049f4e8f7992542aca307f0be13Chris Banes                    = new CoordinatorLayoutUtils.DependentBehavior(dependency);
91a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
92a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            // And set its LayoutParams to use the Behavior
93a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            CoordinatorLayout.LayoutParams lp = col.generateDefaultLayoutParams();
94a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            lp.setBehavior(behavior);
95a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            view.setLayoutParams(lp);
96a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
97a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            views.add(view);
98a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        }
99a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
100a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        // Now the add the views in the given order and assert that they still end up in
101a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        // the expected order A, B, C, D
102a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        final List<View> testOrder = new ArrayList<>();
103a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        testOrder.add(views.get(mFirstAddIndex));
104a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        testOrder.add(views.get(mSecondAddIndex));
105a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        testOrder.add(views.get(mThirdAddIndex));
106a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        testOrder.add(views.get(mFourthAddIndex));
107a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        addViewsAndAssertOrdering(col, views, testOrder);
108a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    }
109a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
110a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    private static void addViewsAndAssertOrdering(final CoordinatorLayout col,
111a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            final List<View> expectedOrder, final List<View> addOrder) {
112a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
113a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
114a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        // Add the Views in the given order
115a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        instrumentation.runOnMainSync(new Runnable() {
116a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            @Override
117a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            public void run() {
118a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                for (int i = 0; i < addOrder.size(); i++) {
119a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                    col.addView(addOrder.get(i));
120a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                }
121a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            }
122a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        });
123a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        instrumentation.waitForIdleSync();
124a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
125a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        // Now assert that the dependency sorted order is correct
126a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        assertEquals(expectedOrder, col.getDependencySortedChildren());
127a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes
128a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        // Finally remove all of the views
129a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        instrumentation.runOnMainSync(new Runnable() {
130a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            @Override
131a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            public void run() {
132a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes                col.removeAllViews();
133a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes            }
134a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes        });
135a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes    }
136a2f4dd03315ee950fef6b8211d372f15883a52aaChris Banes}
137