1 /* 2 * Copyright 2018 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 17 package androidx.coordinatorlayout.widget; 18 19 import static org.junit.Assert.assertEquals; 20 21 import android.app.Instrumentation; 22 import android.support.test.InstrumentationRegistry; 23 import android.support.test.filters.MediumTest; 24 import android.support.test.rule.ActivityTestRule; 25 import android.view.View; 26 27 import androidx.coordinatorlayout.testutils.CoordinatorLayoutUtils; 28 29 import org.junit.Rule; 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 import org.junit.runners.Parameterized; 33 34 import java.util.ArrayList; 35 import java.util.Arrays; 36 import java.util.Collection; 37 import java.util.List; 38 39 @RunWith(Parameterized.class) 40 @MediumTest 41 public class CoordinatorLayoutSortTest { 42 @Rule 43 public final ActivityTestRule<CoordinatorLayoutActivity> mActivityTestRule; 44 45 private static final int NUMBER_VIEWS_DEPENDENCY_SORT = 4; 46 47 /** 48 * All 27 permutations of a quad-tuple containing unique values in the range 0-3 49 */ 50 @Parameterized.Parameters 51 public static Collection<Object[]> data() { 52 return Arrays.asList(new Object[][] { 53 {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {0, 3, 2, 1}, 54 {1, 0, 2, 3}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 2, 3, 0}, {1, 3, 0, 2}, {1, 3, 2, 0}, 55 {2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {2, 3, 1, 0}, 56 {3, 0, 1, 2}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0} 57 }); 58 } 59 60 private int mFirstAddIndex; 61 private int mSecondAddIndex; 62 private int mThirdAddIndex; 63 private int mFourthAddIndex; 64 65 public CoordinatorLayoutSortTest(int firstIndex, int secondIndex, int thirdIndex, 66 int fourthIndex) { 67 mActivityTestRule = new ActivityTestRule<>(CoordinatorLayoutActivity.class); 68 mFirstAddIndex = firstIndex; 69 mSecondAddIndex = secondIndex; 70 mThirdAddIndex = thirdIndex; 71 mFourthAddIndex = fourthIndex; 72 } 73 74 @Test 75 public void testDependencySortingOrder() throws Throwable { 76 final CoordinatorLayout col = mActivityTestRule.getActivity().mCoordinatorLayout; 77 78 // Let's create some views where each view depends on the previous view. 79 // i.e C depends on B, B depends on A, A doesn't depend on anything. 80 final List<View> views = new ArrayList<>(); 81 for (int i = 0; i < NUMBER_VIEWS_DEPENDENCY_SORT; i++) { 82 // 65 == A in ASCII 83 final String label = Character.toString((char) (65 + i)); 84 final View view = new View(col.getContext()) { 85 @Override 86 public String toString() { 87 return label; 88 } 89 }; 90 91 // Create a Behavior which depends on the previously added view 92 View dependency = i > 0 ? views.get(i - 1) : null; 93 final CoordinatorLayout.Behavior<View> behavior = 94 new CoordinatorLayoutUtils.DependentBehavior(dependency); 95 96 // And set its LayoutParams to use the Behavior 97 CoordinatorLayout.LayoutParams lp = col.generateDefaultLayoutParams(); 98 lp.setBehavior(behavior); 99 view.setLayoutParams(lp); 100 101 views.add(view); 102 } 103 104 // Now the add the views in the given order and assert that they still end up in 105 // the expected order A, B, C, D 106 final List<View> testOrder = new ArrayList<>(); 107 testOrder.add(views.get(mFirstAddIndex)); 108 testOrder.add(views.get(mSecondAddIndex)); 109 testOrder.add(views.get(mThirdAddIndex)); 110 testOrder.add(views.get(mFourthAddIndex)); 111 addViewsAndAssertOrdering(col, views, testOrder); 112 } 113 114 private void addViewsAndAssertOrdering(final CoordinatorLayout col, 115 final List<View> expectedOrder, final List<View> addOrder) throws Throwable { 116 final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 117 118 // Add the Views in the given order 119 mActivityTestRule.runOnUiThread(new Runnable() { 120 @Override 121 public void run() { 122 for (int i = 0; i < addOrder.size(); i++) { 123 col.addView(addOrder.get(i)); 124 } 125 } 126 }); 127 instrumentation.waitForIdleSync(); 128 129 // Now assert that the dependency sorted order is correct 130 assertEquals(expectedOrder, col.getDependencySortedChildren()); 131 132 // Finally remove all of the views 133 mActivityTestRule.runOnUiThread(new Runnable() { 134 @Override 135 public void run() { 136 col.removeAllViews(); 137 } 138 }); 139 } 140 } 141