aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java334
1 files changed, 334 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java
new file mode 100644
index 000000000..9565183bc
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringTest.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
+
+import static com.android.SdkConstants.ANDROID_WIDGET_PREFIX;
+import static com.android.SdkConstants.DOT_XML;
+
+import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
+import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
+import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.TextFileChange;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
+import org.w3c.dom.Element;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@SuppressWarnings("restriction")
+public class RefactoringTest extends AdtProjectTest {
+
+ protected boolean autoFormat() {
+ return true;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+
+ // Ensure that the defaults are initialized so for example formatting options are
+ // initialized properly
+ IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
+ AdtPrefs.init(store);
+ AdtPrefs prefs = AdtPrefs.getPrefs();
+ prefs.initializeStoreWithDefaults(store);
+
+ store.setValue(AdtPrefs.PREFS_FORMAT_GUI_XML, autoFormat());
+
+ prefs.loadValues(null);
+
+ super.setUp();
+ }
+
+ protected static Element findElementById(Element root, String id) {
+ if (id.equals(VisualRefactoring.getId(root))) {
+ return root;
+ }
+
+ for (Element child : DomUtilities.getChildren(root)) {
+ Element result = findElementById(child, id);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ protected static List<Element> getElements(Element root, String... ids) {
+ List<Element> selectedElements = new ArrayList<Element>();
+ for (String id : ids) {
+ Element element = findElementById(root, id);
+ assertNotNull(element);
+ selectedElements.add(element);
+ }
+ return selectedElements;
+ }
+
+ protected void checkEdits(String basename, List<Change> changes) throws BadLocationException,
+ IOException {
+ IDocument document = new Document();
+
+ String xml = readTestFile(basename, false);
+ if (xml == null) { // New file
+ xml = ""; //$NON-NLS-1$
+ }
+ document.set(xml);
+
+ for (Change change : changes) {
+ if (change instanceof TextFileChange) {
+ TextFileChange tf = (TextFileChange) change;
+ TextEdit edit = tf.getEdit();
+ IFile file = tf.getFile();
+ String contents = AdtPlugin.readFile(file);
+ assertEquals(contents, xml);
+ if (edit instanceof MultiTextEdit) {
+ MultiTextEdit edits = (MultiTextEdit) edit;
+ edits.apply(document);
+ } else {
+ edit.apply(document);
+ }
+ } else {
+ System.out.println("Ignoring non-textfilechange in refactoring result");
+ }
+ }
+
+ String actual = document.get();
+
+ // Ensure that the document is still valid to make sure the edits don't
+ // mangle it:
+ org.w3c.dom.Document doc = DomUtilities.parseDocument(actual, true);
+ assertNotNull(actual, doc);
+
+ assertEqualsGolden(basename, actual);
+ }
+
+ protected void checkEdits(List<Change> changes,
+ Map<IPath, String> fileToGoldenName) throws BadLocationException, IOException {
+ checkEdits(changes, fileToGoldenName, false);
+ }
+
+ protected void checkEdits(List<Change> changes,
+ Map<IPath, String> fileToGoldenName, boolean createDiffs)
+ throws BadLocationException, IOException {
+ for (Change change : changes) {
+ if (change instanceof TextFileChange) {
+ TextFileChange tf = (TextFileChange) change;
+ IFile file = tf.getFile();
+ assertNotNull(file);
+ IPath path = file.getProjectRelativePath();
+ String goldenName = fileToGoldenName.get(path);
+ assertNotNull("Not found: " + path.toString(), goldenName);
+
+ String xml = readTestFile(goldenName, false);
+ if (xml == null) { // New file
+ xml = ""; //$NON-NLS-1$
+ }
+ IDocument document = new Document();
+ document.set(xml);
+
+ String before = document.get();
+
+ TextEdit edit = tf.getEdit();
+ if (edit instanceof MultiTextEdit) {
+ MultiTextEdit edits = (MultiTextEdit) edit;
+ edits.apply(document);
+ } else {
+ edit.apply(document);
+ }
+
+ String actual = document.get();
+
+ if (createDiffs) {
+ // Use a diff as the golden file instead of the after
+ actual = getDiff(before, actual);
+ if (goldenName.endsWith(DOT_XML)) {
+ goldenName = goldenName.substring(0,
+ goldenName.length() - DOT_XML.length())
+ + ".diff";
+ }
+ }
+
+ assertEqualsGolden(goldenName, actual);
+ } else {
+ System.out.println("Ignoring non-textfilechange in refactoring result");
+ assertNull(change.getAffectedObjects());
+ }
+ }
+ }
+
+ protected UiViewElementNode createModel(UiViewElementNode parent, Element element) {
+ List<Element> children = DomUtilities.getChildren(element);
+ String fqcn = ANDROID_WIDGET_PREFIX + element.getTagName();
+ boolean hasChildren = children.size() > 0;
+ UiViewElementNode node = createNode(parent, fqcn, hasChildren);
+ node.setXmlNode(element);
+ for (Element child : children) {
+ createModel(node, child);
+ }
+
+ return node;
+ }
+
+ /**
+ * Builds up a ViewInfo hierarchy for the given model. This is done by
+ * reading .info dump files which record the exact pixel sizes of each
+ * ViewInfo object. These files are assumed to match up exactly with the
+ * model objects. This is done rather than rendering an actual layout
+ * hierarchy to insulate the test from pixel difference (in say font size)
+ * among platforms, as well as tying the test to particulars about relative
+ * sizes of things which may change with theme adjustments etc.
+ * <p>
+ * Each file can be generated by the dump method in the ViewHierarchy.
+ */
+ protected ViewInfo createInfos(UiElementNode model, String relativePath) throws IOException {
+ String basename = relativePath.substring(0, relativePath.lastIndexOf('.') + 1);
+ String relative = basename + "info"; //$NON-NLS-1$
+ String info = readTestFile(relative, true);
+ // Parse the info file and build up a model from it
+ // Each line contains a new info.
+ // If indented it is a child of the parent.
+ String[] lines = info.split("\n"); //$NON-NLS-1$
+
+ // Iteration order for the info file should match exactly the UI model so
+ // we can just advance the line index sequentially as we traverse
+
+ return create(model, Arrays.asList(lines).iterator());
+ }
+
+ protected ViewInfo create(UiElementNode node, Iterator<String> lineIterator) {
+ // android.widget.LinearLayout [0,36,240,320]
+ Pattern pattern = Pattern.compile("(\\s*)(\\S+) \\[(\\d+),(\\d+),(\\d+),(\\d+)\\].*");
+ assertTrue(lineIterator.hasNext());
+ String description = lineIterator.next();
+ Matcher matcher = pattern.matcher(description);
+ assertTrue(matcher.matches());
+ //String indent = matcher.group(1);
+ //String fqcn = matcher.group(2);
+ String left = matcher.group(3);
+ String top = matcher.group(4);
+ String right = matcher.group(5);
+ String bottom = matcher.group(6);
+
+ ViewInfo view = new ViewInfo(node.getXmlNode().getLocalName(), node,
+ Integer.parseInt(left), Integer.parseInt(top),
+ Integer.parseInt(right), Integer.parseInt(bottom));
+
+ List<UiElementNode> childNodes = node.getUiChildren();
+ if (childNodes.size() > 0) {
+ List<ViewInfo> children = new ArrayList<ViewInfo>();
+ for (UiElementNode child : childNodes) {
+ children.add(create(child, lineIterator));
+ }
+ view.setChildren(children);
+ }
+
+ return view;
+ }
+
+ protected TestContext setupTestContext(IFile file, String relativePath) throws Exception {
+ IStructuredModel structuredModel = null;
+ org.w3c.dom.Document domDocument = null;
+ IStructuredDocument structuredDocument = null;
+ Element element = null;
+
+ try {
+ IModelManager modelManager = StructuredModelManager.getModelManager();
+ structuredModel = modelManager.getModelForRead(file);
+ if (structuredModel instanceof IDOMModel) {
+ IDOMModel domModel = (IDOMModel) structuredModel;
+ domDocument = domModel.getDocument();
+ element = domDocument.getDocumentElement();
+ structuredDocument = structuredModel.getStructuredDocument();
+ }
+ } finally {
+ if (structuredModel != null) {
+ structuredModel.releaseFromRead();
+ }
+ }
+
+ assertNotNull(structuredModel);
+ assertNotNull(domDocument);
+ assertNotNull(element);
+ assertNotNull(structuredDocument);
+ assertTrue(element instanceof IndexedRegion);
+
+ UiViewElementNode model = createModel(null, element);
+ ViewInfo info = createInfos(model, relativePath);
+ CanvasViewInfo rootView = CanvasViewInfo.create(info, true /* layoutlib5 */).getFirst();
+ TestLayoutEditorDelegate layoutEditor =
+ new TestLayoutEditorDelegate(file, structuredDocument, null);
+
+ TestContext testInfo = createTestContext();
+ testInfo.mFile = file;
+ testInfo.mStructuredModel = structuredModel;
+ testInfo.mStructuredDocument = structuredDocument;
+ testInfo.mElement = element;
+ testInfo.mDomDocument = domDocument;
+ testInfo.mUiModel = model;
+ testInfo.mViewInfo = info;
+ testInfo.mRootView = rootView;
+ testInfo.mLayoutEditorDelegate = layoutEditor;
+
+ return testInfo;
+ }
+
+ protected TestContext createTestContext() {
+ return new TestContext();
+ }
+
+ protected static class TestContext {
+ protected IFile mFile;
+ protected IStructuredModel mStructuredModel;
+ protected IStructuredDocument mStructuredDocument;
+ protected org.w3c.dom.Document mDomDocument;
+ protected Element mElement;
+ protected UiViewElementNode mUiModel;
+ protected ViewInfo mViewInfo;
+ protected CanvasViewInfo mRootView;
+ protected TestLayoutEditorDelegate mLayoutEditorDelegate;
+ }
+
+ @Override
+ public void testDummy() {
+ // To avoid JUnit warning that this class contains no tests, even though
+ // this is an abstract class and JUnit shouldn't try
+ }
+}