• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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 
18 package com.android.ide.common.layout;
19 import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
20 import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
21 
22 import com.android.ide.common.api.DropFeedback;
23 import com.android.ide.common.api.IClientRulesEngine;
24 import com.android.ide.common.api.IDragElement;
25 import com.android.ide.common.api.INode;
26 import com.android.ide.common.api.IValidator;
27 import com.android.ide.common.api.IViewMetadata;
28 import com.android.ide.common.api.IViewRule;
29 import com.android.ide.common.api.Margins;
30 import com.android.ide.common.api.Point;
31 import com.android.ide.common.api.Rect;
32 import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository;
33 
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Map;
39 
40 import junit.framework.TestCase;
41 
42 /**
43  * Common layout helpers from LayoutRule tests
44  */
45 @SuppressWarnings("javadoc")
46 public class LayoutTestBase extends TestCase {
47     /**
48      * Helper function used by tests to drag a button into a canvas containing
49      * the given children.
50      *
51      * @param rule The rule to test on
52      * @param targetNode The target layout node to drag into
53      * @param dragBounds The (original) bounds of the dragged item
54      * @param dropPoint The drag point we should drag to and drop
55      * @param secondDropPoint An optional second drag point to drag to before
56      *            drawing graphics and dropping (or null if not applicable)
57      * @param insertIndex The expected insert position we end up with after
58      *            dropping at the dropPoint
59      * @param currentIndex If the dragged widget is already in the canvas this
60      *            should be its child index; if not, pass in -1
61      * @param graphicsFragments This is a varargs array of String fragments
62      *            we expect to see in the graphics output on the drag over
63      *            event.
64      * @return The inserted node
65      */
dragInto(IViewRule rule, INode targetNode, Rect dragBounds, Point dropPoint, Point secondDropPoint, int insertIndex, int currentIndex, String... graphicsFragments)66     protected INode dragInto(IViewRule rule, INode targetNode, Rect dragBounds, Point dropPoint,
67             Point secondDropPoint, int insertIndex, int currentIndex,
68             String... graphicsFragments) {
69 
70         String draggedButtonId = (currentIndex == -1) ? "@+id/DraggedButton" : targetNode
71                 .getChildren()[currentIndex].getStringAttr(ANDROID_URI, ATTR_ID);
72 
73         IDragElement[] elements = TestDragElement.create(TestDragElement.create(
74                 "android.widget.Button", dragBounds).id(draggedButtonId));
75 
76         // Enter target
77         DropFeedback feedback = rule.onDropEnter(targetNode, null/*targetView*/, elements);
78         assertNotNull(feedback);
79         assertFalse(feedback.invalidTarget);
80         assertNotNull(feedback.painter);
81 
82         if (currentIndex != -1) {
83             feedback.sameCanvas = true;
84         }
85 
86         // Move near top left corner of the target
87         feedback = rule.onDropMove(targetNode, elements, feedback, dropPoint);
88         assertNotNull(feedback);
89 
90         if (secondDropPoint != null) {
91             feedback = rule.onDropMove(targetNode, elements, feedback, secondDropPoint);
92             assertNotNull(feedback);
93         }
94 
95         if (insertIndex == -1) {
96             assertTrue(feedback.invalidTarget);
97         } else {
98             assertFalse(feedback.invalidTarget);
99         }
100 
101         // Paint feedback and make sure it's what we expect
102         TestGraphics graphics = new TestGraphics();
103         assertNotNull(feedback.painter);
104         feedback.painter.paint(graphics, targetNode, feedback);
105         String drawn = graphics.getDrawn().toString();
106 
107         // Check that each graphics fragment is drawn
108         for (String fragment : graphicsFragments) {
109             if (!drawn.contains(fragment)) {
110                 // Get drawn-output since unit test truncates message in below
111                 // contains-assertion
112                 System.out.println("Could not find: " + fragment);
113                 System.out.println("Full graphics output: " + drawn);
114             }
115             assertTrue(fragment + " not found; full=" + drawn, drawn.contains(fragment));
116         }
117 
118         // Attempt a drop?
119         if (insertIndex == -1) {
120             // No, not expected to succeed (for example, when drop point is over an
121             // invalid region in RelativeLayout) - just return.
122             return null;
123         }
124         int childrenCountBefore = targetNode.getChildren().length;
125         rule.onDropped(targetNode, elements, feedback, dropPoint);
126 
127         if (currentIndex == -1) {
128             // Inserting new from outside
129             assertEquals(childrenCountBefore+1, targetNode.getChildren().length);
130         } else {
131             // Moving from existing; must remove in old position first
132             ((TestNode) targetNode).removeChild(currentIndex);
133 
134             assertEquals(childrenCountBefore, targetNode.getChildren().length);
135         }
136         // Ensure that it's inserted in the right place
137         String actualId = targetNode.getChildren()[insertIndex].getStringAttr(
138                 ANDROID_URI, ATTR_ID);
139         if (!draggedButtonId.equals(actualId)) {
140             // Using assertEquals instead of fail to get nice diff view on test
141             // failure
142             List<String> childrenIds = new ArrayList<String>();
143             for (INode child : targetNode.getChildren()) {
144                 childrenIds.add(child.getStringAttr(ANDROID_URI, ATTR_ID));
145             }
146             int index = childrenIds.indexOf(draggedButtonId);
147             String message = "Button found at index " + index + " instead of " + insertIndex
148                     + " among " + childrenIds;
149             System.out.println(message);
150             assertEquals(message, draggedButtonId, actualId);
151         }
152 
153 
154         return targetNode.getChildren()[insertIndex];
155     }
156 
157     /**
158      * Utility method for asserting that two collections contain exactly the
159      * same elements (regardless of order)
160      * @param expected expected collection
161      * @param actual  actual collection
162      */
assertContainsSame(Collection<String> expected, Collection<String> actual)163     public static void assertContainsSame(Collection<String> expected, Collection<String> actual) {
164         if (expected.size() != actual.size()) {
165             fail("Collection sizes differ; expected " + expected.size() + " but was "
166                     + actual.size());
167         }
168 
169         // Sort prior to comparison to ensure we have the same elements
170         // regardless of order
171         List<String> expectedList = new ArrayList<String>(expected);
172         Collections.sort(expectedList);
173         List<String> actualList = new ArrayList<String>(actual);
174         Collections.sort(actualList);
175         // Instead of just assertEquals(expectedList, actualList);
176         // we iterate one element at a time so we can show the first
177         // -difference-.
178         for (int i = 0; i < expectedList.size(); i++) {
179             String expectedElement = expectedList.get(i);
180             String actualElement = actualList.get(i);
181             if (!expectedElement.equals(actualElement)) {
182                 System.out.println("Expected items: " + expectedList);
183                 System.out.println("Actual items  : " + actualList);
184             }
185             assertEquals("Collections differ; first difference:", expectedElement, actualElement);
186         }
187     }
188 
initialize(IViewRule rule, String fqn)189     protected void initialize(IViewRule rule, String fqn) {
190         rule.onInitialize(fqn, new TestRulesEngine(fqn));
191     }
192 
193     private static class TestRulesEngine implements IClientRulesEngine {
194         private final String mFqn;
195 
TestRulesEngine(String fqn)196         protected TestRulesEngine(String fqn) {
197             mFqn = fqn;
198         }
199 
200         @Override
debugPrintf(String msg, Object... params)201         public void debugPrintf(String msg, Object... params) {
202             fail("Not supported in tests yet");
203         }
204 
205         @Override
displayAlert(String message)206         public void displayAlert(String message) {
207             fail("Not supported in tests yet");
208         }
209 
210         @Override
displayInput(String message, String value, IValidator filter)211         public String displayInput(String message, String value, IValidator filter) {
212             fail("Not supported in tests yet");
213             return null;
214         }
215 
216         @Override
getFqcn()217         public String getFqcn() {
218             return mFqn;
219         }
220 
221         @Override
getMetadata(final String fqcn)222         public IViewMetadata getMetadata(final String fqcn) {
223             return new IViewMetadata() {
224                 @Override
225                 public String getDisplayName() {
226                     // This also works when there is no "."
227                     return fqcn.substring(fqcn.lastIndexOf('.') + 1);
228                 }
229 
230                 @Override
231                 public FillPreference getFillPreference() {
232                     return ViewMetadataRepository.get().getFillPreference(fqcn);
233                 }
234 
235                 @Override
236                 public Margins getInsets() {
237                     return null;
238                 }
239 
240                 @Override
241                 public List<String> getTopAttributes() {
242                     return ViewMetadataRepository.get().getTopAttributes(fqcn);
243                 }
244             };
245         }
246 
247         @Override
getMinApiLevel()248         public int getMinApiLevel() {
249             return 8;
250         }
251 
252         @Override
loadRule(String fqcn)253         public IViewRule loadRule(String fqcn) {
254             fail("Not supported in tests yet");
255             return null;
256         }
257 
258         @Override
displayReferenceInput(String currentValue)259         public String displayReferenceInput(String currentValue) {
260             fail("Not supported in tests yet");
261             return null;
262         }
263 
264         @Override
getResourceValidator()265         public IValidator getResourceValidator() {
266             fail("Not supported in tests yet");
267             return null;
268         }
269 
270         @Override
displayResourceInput(String resourceTypeName, String currentValue)271         public String displayResourceInput(String resourceTypeName, String currentValue) {
272             fail("Not supported in tests yet");
273             return null;
274         }
275 
276         @Override
displayMarginInput(String all, String left, String right, String top, String bottom)277         public String[] displayMarginInput(String all, String left, String right, String top,
278                 String bottom) {
279             fail("Not supported in tests yet");
280             return null;
281         }
282 
283         @Override
displayIncludeSourceInput()284         public String displayIncludeSourceInput() {
285             fail("Not supported in tests yet");
286             return null;
287         }
288 
289         @Override
select(Collection<INode> nodes)290         public void select(Collection<INode> nodes) {
291             fail("Not supported in tests yet");
292         }
293 
294         @Override
displayFragmentSourceInput()295         public String displayFragmentSourceInput() {
296             fail("Not supported in tests yet");
297             return null;
298         }
299 
300         @Override
layout()301         public void layout() {
302             fail("Not supported in tests yet");
303         }
304 
305         @Override
redraw()306         public void redraw() {
307             fail("Not supported in tests yet");
308         }
309 
310         @Override
measureChildren(INode parent, AttributeFilter filter)311         public Map<INode, Rect> measureChildren(INode parent, AttributeFilter filter) {
312             return null;
313         }
314 
315         @Override
pxToDp(int px)316         public int pxToDp(int px) {
317             fail("Not supported in tests yet");
318             return px;
319         }
320 
321         @Override
getUniqueId(String prefix)322         public String getUniqueId(String prefix) {
323             fail("Not supported in tests yet");
324             return null;
325         }
326 
327         @Override
screenToLayout(int pixels)328         public int screenToLayout(int pixels) {
329             fail("Not supported in tests yet");
330             return 0;
331         }
332 
333         @Override
dpToPx(int dp)334         public int dpToPx(int dp) {
335             fail("Not supported in tests yet");
336             return 0;
337         }
338 
339         @Override
getAppNameSpace()340         public String getAppNameSpace() {
341             fail("Not supported in tests yet");
342             return null;
343         }
344     }
345 
346     public void testDummy() {
347         // To avoid JUnit warning that this class contains no tests, even though
348         // this is an abstract class and JUnit shouldn't try
349     }
350 }
351