Fix Eclipse sample tests.

This commit is contained in:
Brett Chabot
2009-10-02 17:34:05 -07:00
parent 480332f6c5
commit 071276efbd
6 changed files with 320 additions and 131 deletions

View File

@@ -21,28 +21,31 @@ import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Path;
import java.io.File;
/** /**
* Stub class for project creation page Returns canned responses for creating a * Stub class for project creation page.
* sample project * <p/>
* Returns canned responses for creating a sample project.
*/ */
public class StubSampleProjectCreationPage extends NewProjectCreationPage { public class StubProjectCreationPage extends NewProjectCreationPage {
private String mSampleProjectName; private final String mProjectName;
private String mOsSdkLocation; private final String mLocation;
private final IAndroidTarget mTarget;
public StubSampleProjectCreationPage(String sampleProjectName, String osSdkLocation) { public StubProjectCreationPage(String projectName, String projectLocation, IAndroidTarget target) {
super(); super();
this.mSampleProjectName = sampleProjectName; this.mProjectName = projectName;
this.mOsSdkLocation = osSdkLocation; this.mLocation = projectLocation;
this.mTarget = target;
// don't set test project info
setTestInfo(null);
} }
@Override @Override
public IMainInfo getMainInfo() { public IMainInfo getMainInfo() {
return new IMainInfo() { return new IMainInfo() {
public String getProjectName() { public String getProjectName() {
return mSampleProjectName; return mProjectName;
} }
public String getPackageName() { public String getPackageName() {
@@ -50,11 +53,11 @@ public class StubSampleProjectCreationPage extends NewProjectCreationPage {
} }
public String getActivityName() { public String getActivityName() {
return mSampleProjectName; return mProjectName;
} }
public String getApplicationName() { public String getApplicationName() {
return mSampleProjectName; return mProjectName;
} }
public boolean isNewProject() { public boolean isNewProject() {
@@ -66,9 +69,7 @@ public class StubSampleProjectCreationPage extends NewProjectCreationPage {
} }
public IPath getLocationPath() { public IPath getLocationPath() {
return new Path(mOsSdkLocation + File.separator + return new Path(mLocation);
"samples" + File.separator +
mSampleProjectName);
} }
public String getMinSdkVersion() { public String getMinSdkVersion() {
@@ -76,7 +77,7 @@ public class StubSampleProjectCreationPage extends NewProjectCreationPage {
} }
public IAndroidTarget getSdkTarget() { public IAndroidTarget getSdkTarget() {
return null; return mTarget;
} }
public boolean isCreateActivity() { public boolean isCreateActivity() {

View File

@@ -17,6 +17,8 @@ package com.android.ide.eclipse.adt.wizards.newproject;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreationPage; import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreationPage;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizard; import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizard;
import com.android.ide.eclipse.adt.internal.wizards.newproject.NewTestProjectCreationPage;
import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.operation.IRunnableWithProgress;
@@ -27,24 +29,27 @@ import org.eclipse.swt.widgets.Shell;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
/** /**
* Stub class for project creation wizard Created so project creation logic can * Stub class for project creation wizard.
* be run without UI creation/manipulation Returns canned responses for creating * <p/>
* a sample project * Created so project creation logic can be run without UI creation/manipulation.
*/ */
public class StubSampleProjectWizard extends NewProjectWizard { public class StubProjectWizard extends NewProjectWizard {
private final String mSampleProjectName; private final String mProjectName;
private final String mOsSdkLocation; private final String mProjectLocation;
private final IAndroidTarget mTarget;
/** /**
* Constructor * Constructor
* *
* @param sampleProjectName * @param projectName
* @param osSdkLocation * @param projectLocation
* @parama target
*/ */
public StubSampleProjectWizard(String sampleProjectName, String osSdkLocation) { public StubProjectWizard(String projectName, String projectLocation, IAndroidTarget target) {
this.mSampleProjectName = sampleProjectName; this.mProjectName = projectName;
this.mOsSdkLocation = osSdkLocation; this.mProjectLocation = projectLocation;
this.mTarget = target;
} }
/** /**
@@ -52,7 +57,15 @@ public class StubSampleProjectWizard extends NewProjectWizard {
*/ */
@Override @Override
protected NewProjectCreationPage createMainPage() { protected NewProjectCreationPage createMainPage() {
return new StubSampleProjectCreationPage(mSampleProjectName, mOsSdkLocation); return new StubProjectCreationPage(mProjectName, mProjectLocation, mTarget);
}
/**
* Override parent to return null page
*/
@Override
protected NewTestProjectCreationPage createTestPage() {
return null;
} }
/** /**

View File

@@ -15,40 +15,70 @@
*/ */
package com.android.ide.eclipse.tests; package com.android.ide.eclipse.tests;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetParser;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
* Generic superclass for Eclipse Android functional test cases, that provides * Generic superclass for Eclipse Android functional test cases, that provides common facilities.
* common facilities
*/ */
public class FuncTestCase extends TestCase { public class FuncTestCase extends TestCase {
private String mOsSdkLocation; private String mOsSdkLocation;
protected Sdk mSdk;
/** /**
* Constructor * Initializes test SDK
* * <p/>
* @throws IllegalArgumentException if environment variable "sdk_home" is * Fails test if environment variable "sdk_home" is not set.
* not set
*/ */
protected FuncTestCase() { @Override
protected void setUp() throws Exception {
super.setUp();
mOsSdkLocation = System.getProperty("sdk_home"); mOsSdkLocation = System.getProperty("sdk_home");
if (mOsSdkLocation == null) { if (mOsSdkLocation == null) {
mOsSdkLocation = System.getenv("sdk_home"); mOsSdkLocation = System.getenv("sdk_home");
} }
if (mOsSdkLocation == null || mOsSdkLocation.length() < 1) { if (mOsSdkLocation == null || mOsSdkLocation.length() < 1) {
throw new IllegalArgumentException( fail("Environment variable sdk_home is not set");
"Environment variable sdk_home is not set");
} }
loadSdk(mOsSdkLocation);
} }
/** /**
* Returns the absolute file system path of the Android SDK location to use * Returns the absolute file system path of the Android SDK location to use for this test.
* for this test
*/ */
protected String getOsSdkLocation() { protected String getOsSdkLocation() {
return mOsSdkLocation; return mOsSdkLocation;
} }
/**
* Returns the {@link Sdk} under test.
*/
protected Sdk getSdk() {
return mSdk;
}
/**
* Loads the {@link Sdk}.
*/
private void loadSdk(String sdkLocation) {
mSdk = Sdk.loadSdk(sdkLocation);
int n = mSdk.getTargets().length;
if (n > 0) {
for (IAndroidTarget target : mSdk.getTargets()) {
IStatus status = new AndroidTargetParser(target).run(new NullProgressMonitor());
if (status.getCode() != IStatus.OK) {
fail("Failed to parse targets data");
}
}
}
}
} }

View File

@@ -37,9 +37,7 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreen
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetParser;
import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.LoadStatus;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge;
import com.android.ide.eclipse.tests.FuncTestCase; import com.android.ide.eclipse.tests.FuncTestCase;
import com.android.layoutlib.api.ILayoutResult; import com.android.layoutlib.api.ILayoutResult;
@@ -49,8 +47,6 @@ import com.android.layoutlib.api.IXmlPullParser;
import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants; import com.android.sdklib.SdkConstants;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.kxml2.io.KXmlParser; import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
@@ -120,30 +116,10 @@ public class ApiDemosRenderingTest extends FuncTestCase {
} }
private Sdk mSdk;
public void testApiDemos() throws IOException, XmlPullParserException { public void testApiDemos() throws IOException, XmlPullParserException {
loadSdk();
findApiDemos(); findApiDemos();
} }
/**
* Loads the {@link Sdk}.
*/
private void loadSdk() {
mSdk = Sdk.loadSdk(this.getOsSdkLocation());
int n = mSdk.getTargets().length;
if (n > 0) {
for (IAndroidTarget target : mSdk.getTargets()) {
IStatus status = new AndroidTargetParser(target).run(new NullProgressMonitor());
if (status.getCode() != IStatus.OK) {
fail("Failed to parse targets data");
}
}
}
}
private void findApiDemos() throws IOException, XmlPullParserException { private void findApiDemos() throws IOException, XmlPullParserException {
IAndroidTarget[] targets = mSdk.getTargets(); IAndroidTarget[] targets = mSdk.getTargets();

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2009 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.tests.functests.sampleProjects;
import com.android.ide.eclipse.adt.internal.project.AndroidManifestParser;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.xml.AndroidManifest;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* Helper class for modifying an AndroidManifest.
* <p/>
* TODO: consider merging this with AndroidManifestParser.
*/
class AndroidManifestWriter {
private static final Logger sLogger = Logger.getLogger(AndroidManifestWriter.class.getName());
private final Document mDoc;
private final String mOsManifestFilePath;
private AndroidManifestWriter(Document doc, String osManifestFilePath) {
mDoc = doc;
mOsManifestFilePath = osManifestFilePath;
}
/**
* Sets the minimum SDK version for this manifest
* @param minSdkVersion - the minimim sdk version to use
* @returns <code>true</code> on success, false otherwise
*/
public boolean setMinSdkVersion(String minSdkVersion) {
Element usesSdkElement = null;
NodeList nodeList = mDoc.getElementsByTagName(AndroidManifest.NODE_USES_SDK);
if (nodeList.getLength() > 0) {
usesSdkElement = (Element) nodeList.item(0);
} else {
usesSdkElement = mDoc.createElement(AndroidManifest.NODE_USES_SDK);
mDoc.getDocumentElement().appendChild(usesSdkElement);
}
Attr minSdkAttr = mDoc.createAttributeNS(SdkConstants.NS_RESOURCES,
AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION);
String prefix = mDoc.lookupPrefix(SdkConstants.NS_RESOURCES);
minSdkAttr.setPrefix(prefix);
minSdkAttr.setValue(minSdkVersion);
usesSdkElement.setAttributeNodeNS(minSdkAttr);
return saveXmlToFile();
}
private boolean saveXmlToFile() {
try {
// Prepare the DOM document for writing
Source source = new DOMSource(mDoc);
// Prepare the output file
File file = new File(mOsManifestFilePath);
Result result = new StreamResult(file);
// Write the DOM document to the file
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(source, result);
} catch (TransformerConfigurationException e) {
sLogger.log(Level.SEVERE, "Failed to write xml file", e);
return false;
} catch (TransformerException e) {
sLogger.log(Level.SEVERE, "Failed to write xml file", e);
return false;
}
return true;
}
/**
* Parses the manifest file, and collects data.
*
* @param osManifestFilePath The OS path of the manifest file to parse.
* @return an {@link AndroidManifestParser} or null if parsing failed
*/
public static AndroidManifestWriter parse(String osManifestFilePath) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
docFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(osManifestFilePath);
return new AndroidManifestWriter(doc, osManifestFilePath);
} catch (ParserConfigurationException e) {
sLogger.log(Level.SEVERE, "Error parsing file", e);
return null;
} catch (SAXException e) {
sLogger.log(Level.SEVERE, "Error parsing file", e);
return null;
} catch (IOException e) {
sLogger.log(Level.SEVERE, "Error parsing file", e);
return null;
}
}
}

View File

@@ -15,9 +15,11 @@
*/ */
package com.android.ide.eclipse.tests.functests.sampleProjects; package com.android.ide.eclipse.tests.functests.sampleProjects;
import com.android.ide.eclipse.adt.AndroidConstants;
import com.android.ide.eclipse.adt.internal.project.ProjectHelper; import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
import com.android.ide.eclipse.adt.wizards.newproject.StubSampleProjectWizard; import com.android.ide.eclipse.adt.wizards.newproject.StubProjectWizard;
import com.android.ide.eclipse.tests.FuncTestCase; import com.android.ide.eclipse.tests.FuncTestCase;
import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeEvent;
@@ -26,15 +28,17 @@ import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Display;
import java.io.File;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* Test case that verifies all SDK sample projects can be imported, built in * Test case that verifies all SDK sample projects can be imported, and built in
* Eclipse * Eclipse.
* * <p/>
* TODO: add support for deploying apps onto emulator and verifying successful * TODO: add support for deploying apps onto emulator and verifying successful
* execution there * execution there
* *
@@ -43,57 +47,93 @@ public class SampleProjectTest extends FuncTestCase {
private static final Logger sLogger = Logger.getLogger(SampleProjectTest.class.getName()); private static final Logger sLogger = Logger.getLogger(SampleProjectTest.class.getName());
/**
* Finds all samples projects in set SDK and verify they can be built in Eclipse.
* <p/>
* TODO: add install and run on emulator test
* @throws CoreException
*/
public void testSamples() throws CoreException {
// TODO: For reporting purposes, it would be better if a separate test success or failure
// could be reported for each sample
IAndroidTarget[] targets = mSdk.getTargets();
for (IAndroidTarget target : targets) {
doTestSamplesForTarget(target);
}
}
private void doTestSamplesForTarget(IAndroidTarget target) throws CoreException {
String path = target.getPath(IAndroidTarget.SAMPLES);
File samples = new File(path);
if (samples.isDirectory()) {
File[] files = samples.listFiles();
for (File file : files) {
if (file.isDirectory()) {
doTestSampleProject(file.getName(), file.getAbsolutePath(), target);
}
}
}
}
/** /**
* Tests the sample project with the given name * Tests the sample project with the given name
* *
* @param target - SDK target of project
* @param name - name of sample project to test * @param name - name of sample project to test
* @param path - absolute file system path
* @throws CoreException
*/ */
protected void doTestSampleProject(String name) { private void doTestSampleProject(String name, String path, IAndroidTarget target)
throws CoreException {
IProject iproject = null;
try { try {
sLogger.log(Level.INFO, String.format("Testing sample %s for target %s", name,
target.getName()));
StubSampleProjectWizard newProjCreator = new StubSampleProjectWizard( prepareProject(path, target);
name, getOsSdkLocation());
final StubProjectWizard newProjCreator = new StubProjectWizard(
name, path, target);
newProjCreator.init(null, null); newProjCreator.init(null, null);
newProjCreator.performFinish(); // need to run finish on ui thread since it invokes a perspective switch
Display.getDefault().syncExec(new Runnable() {
IProject iproject = validateProjectExists(name); public void run() {
newProjCreator.performFinish();
}
});
iproject = validateProjectExists(name);
validateNoProblems(iproject); validateNoProblems(iproject);
} }
catch (CoreException e) { catch (CoreException e) {
fail("Unexpected exception when creating sample project: " + e.toString()); sLogger.log(Level.SEVERE,
String.format("Unexpected exception when creating sample project %s " +
"for target %s", name, target.getName()));
throw e;
} finally {
if (iproject != null) {
iproject.delete(false, true, new NullProgressMonitor());
}
} }
} }
public void testApiDemos() { private void prepareProject(String path, IAndroidTarget target) {
doTestSampleProject("ApiDemos"); if (target.getVersion().isPreview()) {
} // need to explicitly set preview's version in manifest for project to compile
final String manifestPath = path + File.separatorChar +
public void testHelloActivity() { AndroidConstants.FN_ANDROID_MANIFEST;
doTestSampleProject("HelloActivity"); AndroidManifestWriter manifestWriter =
} AndroidManifestWriter.parse(manifestPath);
assertNotNull(String.format("could not read manifest %s", manifestPath),
public void testLunarLander() { manifestWriter);
doTestSampleProject("LunarLander"); assertTrue(manifestWriter.setMinSdkVersion(target.getVersion().getApiString()));
} }
public void testNotePad() {
doTestSampleProject("NotePad");
}
public void testSkeletonApp() {
doTestSampleProject("SkeletonApp");
}
public void testSnake() {
doTestSampleProject("Snake");
} }
private IProject validateProjectExists(String name) { private IProject validateProjectExists(String name) {
IProject iproject = getIProject(name); IProject iproject = getIProject(name);
assertTrue(iproject.exists()); assertTrue(String.format("%s project not created", name), iproject.exists());
assertTrue(iproject.isOpen()); assertTrue(String.format("%s project not opened", name), iproject.isOpen());
return iproject; return iproject;
} }
@@ -105,10 +145,10 @@ public class SampleProjectTest extends FuncTestCase {
private void validateNoProblems(IProject iproject) throws CoreException { private void validateNoProblems(IProject iproject) throws CoreException {
waitForBuild(iproject); waitForBuild(iproject);
assertFalse(ProjectHelper.hasError(iproject, true)); assertFalse(String.format("%s project has compile errors", iproject.getName()),
ProjectHelper.hasError(iproject, true));
} }
/** /**
* Waits for build to complete. * Waits for build to complete.
* *
@@ -143,7 +183,7 @@ public class SampleProjectTest extends FuncTestCase {
Thread.sleep(50); Thread.sleep(50);
} }
catch (InterruptedException e) { catch (InterruptedException e) {
// ignore
} }
if (Display.getCurrent() != null) { if (Display.getCurrent() != null) {
Display.getCurrent().readAndDispatch(); Display.getCurrent().readAndDispatch();
@@ -151,8 +191,7 @@ public class SampleProjectTest extends FuncTestCase {
} }
sLogger.log(Level.SEVERE, "expected build event never happened?"); sLogger.log(Level.SEVERE, "expected build event never happened?");
fail("expected build event never happened for " + iproject.getName()); fail(String.format("Expected build event never happened for %s", iproject.getName()));
} }
/** /**
@@ -184,6 +223,5 @@ public class SampleProjectTest extends FuncTestCase {
public synchronized boolean isProjectBuilt() { public synchronized boolean isProjectBuilt() {
return mIsBuilt; return mIsBuilt;
} }
} }
} }