• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 package com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
17 
18 import static com.android.AndroidConstants.FD_RES_LAYOUT;
19 import static com.android.AndroidConstants.FD_RES_VALUES;
20 import static com.android.sdklib.SdkConstants.FD_RES;
21 
22 import com.android.ide.eclipse.adt.AdtPlugin;
23 import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
24 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
25 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
26 import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
27 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
28 import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
29 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
30 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
31 import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreator;
32 import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState;
33 import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
34 import com.android.ide.eclipse.tests.SdkTestCase;
35 import com.android.sdklib.IAndroidTarget;
36 import com.android.sdklib.SdkConstants;
37 
38 import org.eclipse.core.resources.IContainer;
39 import org.eclipse.core.resources.IFile;
40 import org.eclipse.core.resources.IFolder;
41 import org.eclipse.core.resources.IProject;
42 import org.eclipse.core.resources.ResourcesPlugin;
43 import org.eclipse.core.runtime.NullProgressMonitor;
44 import org.eclipse.core.runtime.Path;
45 import org.eclipse.jface.operation.IRunnableContext;
46 import org.eclipse.jface.operation.IRunnableWithProgress;
47 import org.eclipse.jface.text.source.ISourceViewer;
48 import org.eclipse.swt.graphics.Point;
49 import org.eclipse.wst.sse.core.StructuredModelManager;
50 import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
51 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
52 import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
53 
54 import java.io.BufferedReader;
55 import java.io.ByteArrayInputStream;
56 import java.io.File;
57 import java.io.InputStream;
58 import java.io.InputStreamReader;
59 import java.lang.reflect.InvocationTargetException;
60 import java.util.Calendar;
61 import java.util.HashMap;
62 import java.util.Map;
63 
64 @SuppressWarnings({"restriction", "javadoc"})
65 public class AdtProjectTest extends SdkTestCase {
66     private static final int TARGET_API_LEVEL = 12;
67     public static final String TEST_PROJECT_PACKAGE = "com.android.eclipse.tests"; //$NON-NLS-1$
68 
69     /** Update golden files if different from the actual results */
70     private static final boolean UPDATE_DIFFERENT_FILES = false;
71     /** Create golden files if missing */
72     private static final boolean UPDATE_MISSING_FILES = true;
73     private static final String TEST_DATA_REL_PATH =
74         "eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/"
75         + "internal/editors/layout/refactoring/testdata";
76     private static final String PROJECTNAME_PREFIX = "testproject-";
77     private static final long TESTS_START_TIME = System.currentTimeMillis();
78     private static File sTempDir = null;
79 
80     /**
81      * We don't stash the project used by each test case as a field such that test cases
82      * can share a single project instance (which is typically much faster).
83      * However, see {@link #getProjectName()} for exceptions to this sharing scheme.
84      */
85     private static Map<String, IProject> sProjectMap = new HashMap<String, IProject>();
86 
87     @Override
setUp()88     protected void setUp() throws Exception {
89         super.setUp();
90 
91         // Prevent preview icon computation during plugin test to make test faster
92         if (AdtPlugin.getDefault() == null) {
93             fail("This test must be run as an Eclipse plugin test, not a plain JUnit test!");
94         }
95         AdtPrefs.getPrefs().setPaletteModes("ICON_TEXT"); //$NON-NLS-1$
96 
97         getProject();
98     }
99 
100     /** Set to true if the subclass test case should use a per-instance project rather
101      * than a shared project. This is needed by projects which modify the project in such
102      * a way that it affects what other tests see (for example, the quickfix resource creation
103      * tests will add in new resources, which the code completion tests will then list as
104      * possible matches if the code completion test is run after the quickfix test.)
105      * @return true to create a per-instance project instead of the default shared project
106      */
testCaseNeedsUniqueProject()107     protected boolean testCaseNeedsUniqueProject() {
108         return false;
109     }
110 
testNeedsUniqueProject()111     protected boolean testNeedsUniqueProject() {
112         return false;
113     }
114 
115     @Override
validateSdk(IAndroidTarget target)116     protected boolean validateSdk(IAndroidTarget target) {
117         // Not quite working yet. When enabled will make tests run faster.
118         //if (target.getVersion().getApiLevel() < TARGET_API_LEVEL) {
119         //    return false;
120         //}
121 
122         return true;
123     }
124 
125     /** Returns a name to use for the project used in this test. Subclasses do not need to
126      * override this if they can share a project with others - which is the case if they do
127      * not modify the project in a way that does not affect other tests. For example
128      * the resource quickfix test will create new resources which affect what shows up
129      * in the code completion results, so the quickfix tests will override this method
130      * to produce a unique project for its own tests.
131      */
getProjectName()132     private String getProjectName() {
133         if (testNeedsUniqueProject()) {
134             return PROJECTNAME_PREFIX + getClass().getSimpleName() + "-" + getName();
135         } else if (testCaseNeedsUniqueProject()) {
136             return PROJECTNAME_PREFIX + getClass().getSimpleName();
137         } else {
138             return PROJECTNAME_PREFIX + TESTS_START_TIME;
139         }
140     }
141 
getProject()142     protected IProject getProject() {
143         String projectName = getProjectName();
144         IProject project = sProjectMap.get(projectName);
145         if (project == null) {
146             project = createProject(projectName);
147             assertNotNull(project);
148             sProjectMap.put(projectName, project);
149         }
150 
151         return project;
152     }
153 
getTestDataFile(IProject project, String name)154     protected IFile getTestDataFile(IProject project, String name) throws Exception {
155         return getTestDataFile(project, name, name);
156     }
157 
getLayoutFile(IProject project, String name)158     protected IFile getLayoutFile(IProject project, String name) throws Exception {
159         return getTestDataFile(project, name, FD_RES + "/" + FD_RES_LAYOUT + "/" + name);
160     }
161 
getValueFile(IProject project, String name)162     protected IFile getValueFile(IProject project, String name) throws Exception {
163         return getTestDataFile(project, name, FD_RES + "/" + FD_RES_VALUES + "/" + name);
164     }
165 
getTestDataFile(IProject project, String sourceName, String destPath)166     protected IFile getTestDataFile(IProject project, String sourceName,
167             String destPath) throws Exception {
168         return getTestDataFile(project, sourceName, destPath, false);
169     }
170 
getTestDataFile(IProject project, String sourceName, String destPath, boolean overwrite)171     protected IFile getTestDataFile(IProject project, String sourceName,
172             String destPath, boolean overwrite) throws Exception {
173         String[] split = destPath.split("/"); //$NON-NLS-1$
174         IContainer parent;
175         String name;
176         if (split.length == 1) {
177             parent = project;
178             name = destPath;
179         } else {
180             IFolder folder = project.getFolder(split[0]);
181             NullProgressMonitor monitor = new NullProgressMonitor();
182             if (!folder.exists()) {
183                 folder.create(true /* force */, true /* local */, monitor);
184             }
185             for (int i = 1, n = split.length; i < n -1; i++) {
186                 IFolder subFolder = folder.getFolder(split[i]);
187                 if (!subFolder.exists()) {
188                     subFolder.create(true /* force */, true /* local */, monitor);
189                 }
190                 folder = subFolder;
191             }
192             name = split[split.length - 1];
193             parent = folder;
194         }
195         IFile file = parent.getFile(new Path(name));
196         if (overwrite && file.exists()) {
197             String currentContents = AdtPlugin.readFile(file);
198             String newContents = readTestFile(sourceName, true);
199             if (currentContents == null || !currentContents.equals(newContents)) {
200                 file.delete(true, new NullProgressMonitor());
201             } else {
202                 return file;
203             }
204         }
205         if (!file.exists()) {
206             String xml = readTestFile(sourceName, true);
207             InputStream bstream = new ByteArrayInputStream(xml.getBytes("UTF-8")); //$NON-NLS-1$
208             NullProgressMonitor monitor = new NullProgressMonitor();
209             file.create(bstream, false /* force */, monitor);
210         }
211 
212         return file;
213     }
214 
createProject(String name)215     protected IProject createProject(String name) {
216         IAndroidTarget target = null;
217 
218         IAndroidTarget[] targets = getSdk().getTargets();
219         for (IAndroidTarget t : targets) {
220             if (t.getVersion().getApiLevel() >= TARGET_API_LEVEL) {
221                 target = t;
222                 break;
223             }
224         }
225         assertNotNull(target);
226 
227 
228         IRunnableContext context = new IRunnableContext() {
229             @Override
230             public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
231                     throws InvocationTargetException, InterruptedException {
232                 runnable.run(new NullProgressMonitor());
233             }
234         };
235         NewProjectWizardState state = new NewProjectWizardState(Mode.ANY);
236         state.projectName = name;
237         state.target = target;
238         state.packageName = TEST_PROJECT_PACKAGE;
239         state.activityName = name;
240         state.applicationName = name;
241         state.createActivity = false;
242         state.useDefaultLocation = true;
243 
244         NewProjectCreator creator = new NewProjectCreator(state, context);
245         creator.createAndroidProjects();
246         return validateProjectExists(name);
247     }
248 
createTestProject()249     public void createTestProject() {
250         IAndroidTarget target = null;
251 
252         IAndroidTarget[] targets = getSdk().getTargets();
253         for (IAndroidTarget t : targets) {
254             if (t.getVersion().getApiLevel() >= TARGET_API_LEVEL) {
255                 target = t;
256                 break;
257             }
258         }
259         assertNotNull(target);
260     }
261 
validateProjectExists(String name)262     private static IProject validateProjectExists(String name) {
263         IProject iproject = getProject(name);
264         assertTrue(String.format("%s project not created", name), iproject.exists());
265         assertTrue(String.format("%s project not opened", name), iproject.isOpen());
266         return iproject;
267     }
268 
getProject(String name)269     private static IProject getProject(String name) {
270         IProject iproject = ResourcesPlugin.getWorkspace().getRoot()
271                 .getProject(name);
272         return iproject;
273     }
274 
getCaretOffset(IFile file, String caretLocation)275     protected int getCaretOffset(IFile file, String caretLocation) {
276         assertTrue(caretLocation, caretLocation.contains("^"));
277 
278         String fileContent = AdtPlugin.readFile(file);
279         return getCaretOffset(fileContent, caretLocation);
280     }
281 
getCaretOffset(String fileContent, String caretLocation)282     protected int getCaretOffset(String fileContent, String caretLocation) {
283         assertTrue(caretLocation, caretLocation.contains("^")); //$NON-NLS-1$
284 
285         int caretDelta = caretLocation.indexOf("^"); //$NON-NLS-1$
286         assertTrue(caretLocation, caretDelta != -1);
287 
288         // String around caret/range without the range and caret marker characters
289         String caretContext;
290         if (caretLocation.contains("[^")) { //$NON-NLS-1$
291             caretDelta--;
292             assertTrue(caretLocation, caretLocation.startsWith("[^", caretDelta)); //$NON-NLS-1$
293             int caretRangeEnd = caretLocation.indexOf(']', caretDelta + 2);
294             assertTrue(caretLocation, caretRangeEnd != -1);
295             caretContext = caretLocation.substring(0, caretDelta)
296                     + caretLocation.substring(caretDelta + 2, caretRangeEnd)
297                     + caretLocation.substring(caretRangeEnd + 1);
298         } else {
299             caretContext = caretLocation.substring(0, caretDelta)
300                     + caretLocation.substring(caretDelta + 1); // +1: skip "^"
301         }
302 
303         int caretContextIndex = fileContent.indexOf(caretContext);
304         assertTrue("Caret content " + caretContext + " not found in file",
305                 caretContextIndex != -1);
306         return caretContextIndex + caretDelta;
307     }
308 
309     /**
310      * If the given caret location string contains a selection range, select that range in
311      * the given viewer
312      *
313      * @param viewer the viewer to contain the selection
314      * @param caretLocation the location string
315      */
updateCaret(ISourceViewer viewer, String caretLocation)316     protected int updateCaret(ISourceViewer viewer, String caretLocation) {
317         assertTrue(caretLocation, caretLocation.contains("^")); //$NON-NLS-1$
318 
319         int caretDelta = caretLocation.indexOf("^"); //$NON-NLS-1$
320         assertTrue(caretLocation, caretDelta != -1);
321         String text = viewer.getTextWidget().getText();
322 
323         int length = 0;
324 
325         // String around caret/range without the range and caret marker characters
326         String caretContext;
327 
328         if (caretLocation.contains("[^")) { //$NON-NLS-1$
329             caretDelta--;
330             assertTrue(caretLocation, caretLocation.startsWith("[^", caretDelta)); //$NON-NLS-1$
331 
332             int caretRangeEnd = caretLocation.indexOf(']', caretDelta + 2);
333             assertTrue(caretLocation, caretRangeEnd != -1);
334             length = caretRangeEnd - caretDelta - 2;
335             assertTrue(length > 0);
336             caretContext = caretLocation.substring(0, caretDelta)
337                     + caretLocation.substring(caretDelta + 2, caretRangeEnd)
338                     + caretLocation.substring(caretRangeEnd + 1);
339         } else {
340             caretContext = caretLocation.substring(0, caretDelta)
341                     + caretLocation.substring(caretDelta + 1); // +1: skip "^"
342         }
343 
344         int caretContextIndex = text.indexOf(caretContext);
345 
346         assertTrue("Caret content " + caretContext + " not found in file",
347                 caretContextIndex != -1);
348 
349         int offset = caretContextIndex + caretDelta;
350         viewer.setSelectedRange(offset, length);
351 
352         return offset;
353     }
354 
addSelection(String newFileContents, Point selectedRange)355     protected String addSelection(String newFileContents, Point selectedRange) {
356         int selectionBegin = selectedRange.x;
357         int selectionEnd = selectionBegin + selectedRange.y;
358         return addSelection(newFileContents, selectionBegin, selectionEnd);
359     }
360 
addSelection(String newFileContents, int selectionBegin, int selectionEnd)361     protected String addSelection(String newFileContents, int selectionBegin, int selectionEnd) {
362         // Insert selection markers -- [ ] for the selection range, ^ for the caret
363         String newFileWithCaret;
364         if (selectionBegin < selectionEnd) {
365             newFileWithCaret = newFileContents.substring(0, selectionBegin) + "[^"
366                     + newFileContents.substring(selectionBegin, selectionEnd) + "]"
367                     + newFileContents.substring(selectionEnd);
368         } else {
369             // Selected range
370             newFileWithCaret = newFileContents.substring(0, selectionBegin) + "^"
371                     + newFileContents.substring(selectionBegin);
372         }
373 
374         return newFileWithCaret;
375     }
376 
getCaretContext(String file, int offset)377     protected String getCaretContext(String file, int offset) {
378         int windowSize = 20;
379         int begin = Math.max(0, offset - windowSize / 2);
380         int end = Math.min(file.length(), offset + windowSize / 2);
381 
382         return "..." + file.substring(begin, offset) + "^" + file.substring(offset, end) + "...";
383     }
384 
385     /**
386      * Very primitive line differ, intended for files where there are very minor changes
387      * (such as code completion apply-tests)
388      */
getDiff(String before, String after)389     protected String getDiff(String before, String after) {
390         // Do line by line analysis
391         String[] beforeLines = before.split("\n");
392         String[] afterLines = after.split("\n");
393 
394         int firstDelta = 0;
395         for (; firstDelta < Math.min(beforeLines.length, afterLines.length); firstDelta++) {
396             if (!beforeLines[firstDelta].equals(afterLines[firstDelta])) {
397                 break;
398             }
399         }
400 
401         if (firstDelta == beforeLines.length && firstDelta == afterLines.length) {
402             return "";
403         }
404 
405         // Counts from the end of both arrays
406         int lastDelta = 0;
407         for (; lastDelta < Math.min(beforeLines.length, afterLines.length); lastDelta++) {
408             if (!beforeLines[beforeLines.length - 1 - lastDelta].equals(
409                     afterLines[afterLines.length - 1 - lastDelta])) {
410                 break;
411             }
412         }
413 
414 
415         boolean showBeforeWindow = firstDelta >= beforeLines.length - lastDelta;
416         boolean showAfterWindow = firstDelta >= afterLines.length - lastDelta;
417 
418         StringBuilder sb = new StringBuilder();
419         if (showAfterWindow && firstDelta > 0) {
420             sb.append("  ");
421             sb.append(afterLines[firstDelta - 1]);
422             sb.append('\n');
423         }
424         for (int i = firstDelta; i < beforeLines.length - lastDelta; i++) {
425             sb.append("<");
426             if (beforeLines[i].length() > 0) {
427                 sb.append(" ");
428             }
429             sb.append(beforeLines[i]);
430             sb.append('\n');
431         }
432         if (showAfterWindow && lastDelta < afterLines.length - 1) {
433             sb.append("  ");
434             sb.append(afterLines[afterLines.length - (lastDelta -1)]);
435             sb.append('\n');
436         }
437 
438         sb.append("---\n");
439 
440         if (showBeforeWindow && firstDelta > 0) {
441             sb.append("  ");
442             sb.append(beforeLines[firstDelta - 1]);
443             sb.append('\n');
444         }
445         for (int i = firstDelta; i < afterLines.length - lastDelta; i++) {
446             sb.append(">");
447             if (afterLines[i].length() > 0) {
448                 sb.append(" ");
449             }
450             sb.append(afterLines[i]);
451             sb.append('\n');
452         }
453         if (showBeforeWindow && lastDelta < beforeLines.length - 1) {
454             sb.append("  ");
455             sb.append(beforeLines[beforeLines.length - (lastDelta -1)]);
456             sb.append('\n');
457         }
458 
459         return sb.toString();
460     }
461 
removeSessionData(String data)462     protected String removeSessionData(String data) {
463         if (getProject() != null) {
464             data = data.replace(getProject().getName(), "PROJECTNAME");
465         }
466 
467         return data;
468     }
469 
createDesc(String name, String fqn, boolean hasChildren)470     public static ViewElementDescriptor createDesc(String name, String fqn, boolean hasChildren) {
471         if (hasChildren) {
472             return new ViewElementDescriptor(name, name, fqn, "", "", new AttributeDescriptor[0],
473                     new AttributeDescriptor[0], new ElementDescriptor[1], false);
474         } else {
475             return new ViewElementDescriptor(name, fqn);
476         }
477     }
478 
createNode(UiViewElementNode parent, String fqn, boolean hasChildren)479     public static UiViewElementNode createNode(UiViewElementNode parent, String fqn,
480             boolean hasChildren) {
481         String name = fqn.substring(fqn.lastIndexOf('.') + 1);
482         ViewElementDescriptor descriptor = createDesc(name, fqn, hasChildren);
483         if (parent == null) {
484             // All node hierarchies should be wrapped inside a document node at the root
485             parent = new UiViewElementNode(createDesc("doc", "doc", true));
486         }
487         return (UiViewElementNode) parent.appendNewUiChild(descriptor);
488     }
489 
createNode(String fqn, boolean hasChildren)490     public static UiViewElementNode createNode(String fqn, boolean hasChildren) {
491         return createNode(null, fqn, hasChildren);
492     }
493 
readTestFile(String relativePath, boolean expectExists)494     protected String readTestFile(String relativePath, boolean expectExists) {
495         String path = "testdata" + File.separator + relativePath; //$NON-NLS-1$
496         InputStream stream =
497             AdtProjectTest.class.getResourceAsStream(path);
498         if (!expectExists && stream == null) {
499             return null;
500         }
501 
502         assertNotNull(relativePath + " does not exist", stream);
503 
504         BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
505         String xml = AdtPlugin.readFile(reader);
506         assertNotNull(xml);
507         assertTrue(xml.length() > 0);
508 
509         // Remove any references to the project name such that we are isolated from
510         // that in golden file.
511         // Appears in strings.xml etc.
512         xml = removeSessionData(xml);
513 
514         return xml;
515     }
516 
assertEqualsGolden(String basename, String actual)517     protected void assertEqualsGolden(String basename, String actual) {
518         assertEqualsGolden(basename, actual, basename.substring(basename.lastIndexOf('.') + 1));
519     }
520 
assertEqualsGolden(String basename, String actual, String newExtension)521     protected void assertEqualsGolden(String basename, String actual, String newExtension) {
522         String testName = getName();
523         if (testName.startsWith("test")) {
524             testName = testName.substring(4);
525             if (Character.isUpperCase(testName.charAt(0))) {
526                 testName = Character.toLowerCase(testName.charAt(0)) + testName.substring(1);
527             }
528         }
529         String expectedName;
530         String extension = basename.substring(basename.lastIndexOf('.') + 1);
531         if (newExtension == null) {
532             newExtension = extension;
533         }
534         expectedName = basename.substring(0, basename.indexOf('.'))
535                 + "-expected-" + testName + '.' + newExtension;
536         String expected = readTestFile(expectedName, false);
537         if (expected == null) {
538             File expectedPath = new File(
539                     UPDATE_MISSING_FILES ? getTargetDir() : getTempDir(), expectedName);
540             AdtPlugin.writeFile(expectedPath, actual);
541             System.out.println("Expected - written to " + expectedPath + ":\n");
542             System.out.println(actual);
543             fail("Did not find golden file (" + expectedName + "): Wrote contents as "
544                     + expectedPath);
545         } else {
546             if (!expected.replaceAll("\r\n", "\n").equals(actual.replaceAll("\r\n", "\n"))) {
547                 File expectedPath = new File(getTempDir(), expectedName);
548                 File actualPath = new File(getTempDir(),
549                         expectedName.replace("expected", "actual"));
550                 AdtPlugin.writeFile(expectedPath, expected);
551                 AdtPlugin.writeFile(actualPath, actual);
552                 // Also update data dir with the current value
553                 if (UPDATE_DIFFERENT_FILES) {
554                     AdtPlugin.writeFile( new File(getTargetDir(), expectedName), actual);
555                 }
556                 System.out.println("The files differ: diff " + expectedPath + " "
557                         + actualPath);
558                 assertEquals("The files differ - see " + expectedPath + " versus " + actualPath,
559                         expected, actual);
560             }
561         }
562     }
563 
564     /** Get the location to write missing golden files to */
getTargetDir()565     protected File getTargetDir() {
566         // Set $ADT_SDK_SOURCE_PATH to point to your git "sdk" directory; if done, then
567         // if you run a unit test which refers to a golden file which does not exist, it
568         // will be created directly into the test data directory and you can rerun the
569         // test
570         // and it should pass (after you verify that the golden file contains the correct
571         // result of course).
572         String sdk = System.getenv("ADT_SDK_SOURCE_PATH");
573         if (sdk != null) {
574             File sdkPath = new File(sdk);
575             if (sdkPath.exists()) {
576                 File testData = new File(sdkPath, TEST_DATA_REL_PATH.replace('/',
577                         File.separatorChar));
578                 if (testData.exists()) {
579                     return testData;
580                 }
581             }
582         }
583         return getTempDir();
584     }
585 
getTempDir()586     protected File getTempDir() {
587         if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
588             return new File("/tmp"); //$NON-NLS-1$
589         }
590 
591         if (sTempDir == null) {
592             // On Windows, we don't want to pollute the temp folder (which is generally
593             // already incredibly busy). So let's create a temp folder for the results.
594 
595             File base = new File(System.getProperty("java.io.tmpdir"));     //$NON-NLS-1$
596 
597             Calendar c = Calendar.getInstance();
598             String name = String.format("adtTests_%1$tF_%1$tT", c).replace(':', '-'); //$NON-NLS-1$
599             File tmpDir = new File(base, name);
600             if (!tmpDir.exists() && tmpDir.mkdir()) {
601                 sTempDir = tmpDir;
602             } else {
603                 sTempDir = base;
604             }
605         }
606 
607         return sTempDir;
608     }
609 
610     /** Special editor context set on the model to be rendered */
611     protected static class TestLayoutEditorDelegate extends LayoutEditorDelegate {
612 
TestLayoutEditorDelegate( IFile file, IStructuredDocument structuredDocument, UiDocumentNode uiRootNode)613         public TestLayoutEditorDelegate(
614                 IFile file,
615                 IStructuredDocument structuredDocument,
616                 UiDocumentNode uiRootNode) {
617             super(new TestAndroidXmlCommonEditor(file, structuredDocument, uiRootNode));
618         }
619 
620         static class TestAndroidXmlCommonEditor extends CommonXmlEditor {
621 
622             private final IFile mFile;
623             private final IStructuredDocument mStructuredDocument;
624             private UiDocumentNode mUiRootNode;
625 
TestAndroidXmlCommonEditor( IFile file, IStructuredDocument structuredDocument, UiDocumentNode uiRootNode)626             TestAndroidXmlCommonEditor(
627                     IFile file,
628                     IStructuredDocument structuredDocument,
629                     UiDocumentNode uiRootNode) {
630                 mFile = file;
631                 mStructuredDocument = structuredDocument;
632                 mUiRootNode = uiRootNode;
633             }
634 
635             @Override
getInputFile()636             public IFile getInputFile() {
637                 return mFile;
638             }
639 
640             @Override
getProject()641             public IProject getProject() {
642                 return mFile.getProject();
643             }
644 
645             @Override
getStructuredDocument()646             public IStructuredDocument getStructuredDocument() {
647                 return mStructuredDocument;
648             }
649 
650             @Override
getUiRootNode()651             public UiDocumentNode getUiRootNode() {
652                 return mUiRootNode;
653             }
654 
655             @Override
editorDirtyStateChanged()656             public void editorDirtyStateChanged() {
657             }
658 
659             @Override
getModelForRead()660             public IStructuredModel getModelForRead() {
661                 IModelManager mm = StructuredModelManager.getModelManager();
662                 if (mm != null) {
663                     try {
664                         return mm.getModelForRead(mFile);
665                     } catch (Exception e) {
666                         fail(e.toString());
667                     }
668                 }
669 
670                 return null;
671             }
672         }
673     }
674 
testDummy()675     public void testDummy() {
676         // This class contains shared test functionality for testcase subclasses,
677         // but without an actual test in the class JUnit complains (even if we make
678         // it abstract)
679     }
680 }
681