1 /* 2 * Copyright (C) 2017 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 android.widget; 18 19 import static org.junit.Assert.assertEquals; 20 21 import static java.util.function.Function.identity; 22 23 import android.graphics.PointF; 24 import android.graphics.RectF; 25 26 import androidx.test.filters.LargeTest; 27 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.JUnit4; 31 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 36 @LargeTest 37 @RunWith(JUnit4.class) 38 public final class SelectionActionModeHelperTest { 39 40 /* 41 * The test rectangle set is composed of three 1x1 rectangles as illustrated below. 42 * 43 * (0, 0) ____________ (100001, 0) 44 * |█ █| 45 * |_█________| 46 * (0, 2) (100001, 2) 47 */ 48 private final List<RectF> mRectFList = Arrays.asList( 49 new RectF(0, 0, 1, 1), 50 new RectF(100000, 0, 100001, 1), 51 new RectF(1, 1, 2, 2)); 52 53 @Test testMovePointInsideNearestRectangle_pointIsInsideRectangle()54 public void testMovePointInsideNearestRectangle_pointIsInsideRectangle() { 55 testMovePointInsideNearestRectangle( 56 0.1f /* pointX */, 57 0.1f /* pointY */, 58 0.1f /* expectedPointX */, 59 0.5f /* expectedPointY */); 60 } 61 62 @Test testMovePointInsideNearestRectangle_pointIsAboveRectangle()63 public void testMovePointInsideNearestRectangle_pointIsAboveRectangle() { 64 testMovePointInsideNearestRectangle( 65 0.1f /* pointX */, 66 -1.0f /* pointY */, 67 0.1f /* expectedPointX */, 68 0.5f /* expectedPointY */); 69 } 70 71 @Test testMovePointInsideNearestRectangle_pointIsLeftOfRectangle()72 public void testMovePointInsideNearestRectangle_pointIsLeftOfRectangle() { 73 testMovePointInsideNearestRectangle( 74 -1.0f /* pointX */, 75 0.4f /* pointY */, 76 0.0f /* expectedPointX */, 77 0.5f /* expectedPointY */); 78 } 79 80 @Test testMovePointInsideNearestRectangle_pointIsRightOfRectangle()81 public void testMovePointInsideNearestRectangle_pointIsRightOfRectangle() { 82 testMovePointInsideNearestRectangle( 83 1.1f /* pointX */, 84 0.0f /* pointY */, 85 1.0f /* expectedPointX */, 86 0.5f /* expectedPointY */); 87 } 88 89 @Test testMovePointInsideNearestRectangle_pointIsBelowRectangle()90 public void testMovePointInsideNearestRectangle_pointIsBelowRectangle() { 91 testMovePointInsideNearestRectangle( 92 0.1f /* pointX */, 93 1.1f /* pointY */, 94 0.1f /* expectedPointX */, 95 0.5f /* expectedPointY */); 96 } 97 98 @Test testMovePointInsideNearestRectangle_pointIsToRightOfTheRightmostRectangle()99 public void testMovePointInsideNearestRectangle_pointIsToRightOfTheRightmostRectangle() { 100 testMovePointInsideNearestRectangle( 101 200000.0f /* pointX */, 102 0.1f /* pointY */, 103 100001.0f /* expectedPointX */, 104 0.5f /* expectedPointY */); 105 } 106 testMovePointInsideNearestRectangle(final float pointX, final float pointY, final float expectedPointX, final float expectedPointY)107 private void testMovePointInsideNearestRectangle(final float pointX, final float pointY, 108 final float expectedPointX, 109 final float expectedPointY) { 110 final PointF point = new PointF(pointX, pointY); 111 final PointF adjustedPoint = 112 SelectionActionModeHelper.movePointInsideNearestRectangle(point, 113 mRectFList, identity()); 114 115 assertEquals(expectedPointX, adjustedPoint.x, 0.0f); 116 assertEquals(expectedPointY, adjustedPoint.y, 0.0f); 117 } 118 119 @Test testMergeRectangleIntoList_addThreeDisjointRectangles()120 public void testMergeRectangleIntoList_addThreeDisjointRectangles() { 121 testExpandRectangleList( 122 new RectF[] { 123 new RectF(0, 0, 1, 1), 124 new RectF(10, 10, 11, 11), 125 new RectF(20, 20, 21, 21) 126 }, 127 new RectF[] { 128 new RectF(0, 0, 1, 1), 129 new RectF(10, 10, 11, 11), 130 new RectF(20, 20, 21, 21) 131 } 132 ); 133 } 134 135 @Test testMergeRectangleIntoList_addAnEmptyRectangle()136 public void testMergeRectangleIntoList_addAnEmptyRectangle() { 137 testExpandRectangleList( 138 new RectF[] { 139 new RectF(0, 0, 0, 0) 140 }, 141 new RectF[] { 142 } 143 ); 144 } 145 146 @Test testMergeRectangleIntoList_addAContainedRectangle()147 public void testMergeRectangleIntoList_addAContainedRectangle() { 148 testExpandRectangleList( 149 new RectF[] { 150 new RectF(0, 0, 10, 10), 151 new RectF(9, 0, 10, 10) 152 }, 153 new RectF[] { 154 new RectF(0, 0, 10, 10) 155 } 156 ); 157 } 158 159 @Test testMergeRectangleIntoList_addARectangleThatContainsExistingRectangles()160 public void testMergeRectangleIntoList_addARectangleThatContainsExistingRectangles() { 161 testExpandRectangleList( 162 new RectF[] { 163 new RectF(0, 0, 1, 1), 164 new RectF(1, 0, 2, 1), 165 new RectF(0, 0, 2, 1) 166 }, 167 new RectF[] { 168 new RectF(0, 0, 2, 1) 169 } 170 ); 171 } 172 173 @Test testMergeRectangleIntoList_addRectangleThatIntersectsAndHasTheSameHeightOnRight()174 public void testMergeRectangleIntoList_addRectangleThatIntersectsAndHasTheSameHeightOnRight() { 175 testExpandRectangleList( 176 new RectF[] { 177 new RectF(0, 0, 1, 1), 178 new RectF(0.5f, 0, 1.5f, 1) 179 }, 180 new RectF[] { 181 new RectF(0, 0, 1.5f, 1) 182 } 183 ); 184 } 185 186 @Test testMergeRectangleIntoList_addRectangleThatIntersectsAndHasTheSameHeightOnLeft()187 public void testMergeRectangleIntoList_addRectangleThatIntersectsAndHasTheSameHeightOnLeft() { 188 testExpandRectangleList( 189 new RectF[] { 190 new RectF(0.5f, 0, 1.5f, 1), 191 new RectF(0, 0, 1, 1) 192 }, 193 new RectF[] { 194 new RectF(0, 0, 1.5f, 1) 195 } 196 ); 197 } 198 199 @Test testMergeRectangleIntoList_addRectangleThatExpandsToTheRight()200 public void testMergeRectangleIntoList_addRectangleThatExpandsToTheRight() { 201 testExpandRectangleList( 202 new RectF[] { 203 new RectF(0, 0, 1, 1), 204 new RectF(1, 0, 1.5f, 1) 205 }, 206 new RectF[] { 207 new RectF(0, 0, 1.5f, 1) 208 } 209 ); 210 } 211 212 @Test testMergeRectangleIntoList_addRectangleThatExpandsToTheLeft()213 public void testMergeRectangleIntoList_addRectangleThatExpandsToTheLeft() { 214 testExpandRectangleList( 215 new RectF[] { 216 new RectF(1, 0, 1.5f, 1), 217 new RectF(0, 0, 1, 1) 218 }, 219 new RectF[] { 220 new RectF(0, 0, 1.5f, 1) 221 } 222 ); 223 } 224 225 226 @Test testMergeRectangleIntoList_addRectangleMadeObsoleteByMultipleExistingRectangles()227 public void testMergeRectangleIntoList_addRectangleMadeObsoleteByMultipleExistingRectangles() { 228 testExpandRectangleList( 229 new RectF[] { 230 new RectF(0, 0, 1, 1), 231 new RectF(0.5f, 0, 1.5f, 1), 232 new RectF(0.25f, 0, 1.25f, 1) 233 }, 234 new RectF[] { 235 new RectF(0, 0, 1.5f, 1) 236 } 237 ); 238 } 239 240 @Test testMergeRectangleIntoList_threeRectanglesThatTouchEachOther()241 public void testMergeRectangleIntoList_threeRectanglesThatTouchEachOther() { 242 testExpandRectangleList( 243 new RectF[] { 244 new RectF(0, 0, 1, 1), 245 new RectF(1, 0, 2, 1), 246 new RectF(2, 0, 3, 1) 247 }, 248 new RectF[] { 249 new RectF(0, 0, 3, 1) 250 } 251 ); 252 } 253 254 testExpandRectangleList(final RectF[] inputRectangles, final RectF[] outputRectangles)255 private void testExpandRectangleList(final RectF[] inputRectangles, 256 final RectF[] outputRectangles) { 257 final List<RectF> expectedOutput = Arrays.asList(outputRectangles); 258 259 final List<RectF> result = new ArrayList<>(); 260 final int size = inputRectangles.length; 261 for (int index = 0; index < size; ++index) { 262 SelectionActionModeHelper.mergeRectangleIntoList(result, inputRectangles[index], 263 identity(), identity()); 264 } 265 266 assertEquals(expectedOutput, result); 267 } 268 269 270 } 271