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