aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/AndroidManifestWriter.java131
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java263
2 files changed, 394 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/AndroidManifestWriter.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/AndroidManifestWriter.java
new file mode 100644
index 000000000..141e7e000
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/AndroidManifestWriter.java
@@ -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.SdkConstants;
+import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
+import com.android.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 AndroidManifestHelper} 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;
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
new file mode 100644
index 000000000..3fb705dfb
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2008 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.SdkConstants;
+import com.android.ide.eclipse.adt.AdtUtils;
+import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreator;
+import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState;
+import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
+import com.android.ide.eclipse.tests.SdkLoadingTestCase;
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.widgets.Display;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Test case that verifies all SDK sample projects can be imported, and built in
+ * Eclipse.
+ * <p/>
+ * TODO: add support for deploying apps onto emulator and verifying successful
+ * execution there
+ *
+ */
+public class SampleProjectTest extends SdkLoadingTestCase {
+
+ 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 = getSdk().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
+ *
+ * @param target - SDK target of project
+ * @param name - name of sample project to test
+ * @param path - absolute file system path
+ * @throws CoreException
+ */
+ private void doTestSampleProject(String name, String path, IAndroidTarget target)
+ throws CoreException {
+ IProject iproject = null;
+ try {
+ sLogger.log(Level.INFO, String.format("Testing sample %s for target %s", name,
+ target.getName()));
+
+ prepareProject(path, target);
+
+ IRunnableContext context = new IRunnableContext() {
+ @Override
+ public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
+ throws InvocationTargetException, InterruptedException {
+ runnable.run(new NullProgressMonitor());
+ }
+ };
+ NewProjectWizardState state = new NewProjectWizardState(Mode.SAMPLE);
+ state.projectName = name;
+ state.target = target;
+ state.packageName = "com.android.samples";
+ state.activityName = name;
+ state.applicationName = name;
+ state.chosenSample = new File(path);
+ state.useDefaultLocation = false;
+ state.createActivity = false;
+
+ NewProjectCreator creator = new NewProjectCreator(state, context);
+ creator.createAndroidProjects();
+ iproject = validateProjectExists(name);
+ validateNoProblems(iproject);
+ }
+ catch (CoreException e) {
+ 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());
+ }
+ }
+ }
+
+ private void prepareProject(String path, IAndroidTarget target) {
+ if (target.getVersion().isPreview()) {
+ // need to explicitly set preview's version in manifest for project to compile
+ final String manifestPath = path + File.separatorChar +
+ SdkConstants.FN_ANDROID_MANIFEST_XML;
+ AndroidManifestWriter manifestWriter =
+ AndroidManifestWriter.parse(manifestPath);
+ assertNotNull(String.format("could not read manifest %s", manifestPath),
+ manifestWriter);
+ assertTrue(manifestWriter.setMinSdkVersion(target.getVersion().getApiString()));
+ }
+ }
+
+ private IProject validateProjectExists(String name) {
+ IProject iproject = getIProject(name);
+ assertTrue(String.format("%s project not created", name), iproject.exists());
+ assertTrue(String.format("%s project not opened", name), iproject.isOpen());
+ return iproject;
+ }
+
+ private IProject getIProject(String name) {
+ IProject iproject = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(name);
+ return iproject;
+ }
+
+ private void validateNoProblems(IProject iproject) throws CoreException {
+ waitForBuild(iproject);
+
+ boolean hasErrors = false;
+ StringBuilder failureBuilder = new StringBuilder(String.format("%s project has errors:",
+ iproject.getName()));
+ IMarker[] markers = iproject.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
+ if (markers != null && markers.length > 0) {
+ // the project has marker(s). even though they are "problem" we
+ // don't know their severity. so we loop on them and figure if they
+ // are warnings or errors
+ for (IMarker m : markers) {
+ int s = m.getAttribute(IMarker.SEVERITY, -1);
+ if (s == IMarker.SEVERITY_ERROR) {
+ hasErrors = true;
+ failureBuilder.append("\n");
+ failureBuilder.append(m.getAttribute(IMarker.MESSAGE, ""));
+ }
+ }
+ }
+ failureBuilder.append("Project location: " + AdtUtils.getAbsolutePath(iproject));
+ assertFalse(failureBuilder.toString(), hasErrors);
+ }
+
+ /**
+ * Waits for build to complete.
+ *
+ * @param iproject
+ */
+ private void waitForBuild(final IProject iproject) {
+
+ final BuiltProjectDeltaVisitor deltaVisitor = new BuiltProjectDeltaVisitor(iproject);
+ IResourceChangeListener newBuildListener = new IResourceChangeListener() {
+
+ @Override
+ public void resourceChanged(IResourceChangeEvent event) {
+ try {
+ event.getDelta().accept(deltaVisitor);
+ }
+ catch (CoreException e) {
+ fail();
+ }
+ }
+
+ };
+ iproject.getWorkspace().addResourceChangeListener(newBuildListener,
+ IResourceChangeEvent.POST_BUILD);
+
+ // poll build listener to determine when build is done
+ // loop max of 1200 times * 50 ms = 60 seconds
+ final int maxWait = 1200;
+ for (int i=0; i < maxWait; i++) {
+ if (deltaVisitor.isProjectBuilt()) {
+ return;
+ }
+ try {
+ Thread.sleep(50);
+ }
+ catch (InterruptedException e) {
+ // ignore
+ }
+ if (Display.getCurrent() != null) {
+ Display.getCurrent().readAndDispatch();
+ }
+ }
+
+ sLogger.log(Level.SEVERE, "expected build event never happened?");
+ fail(String.format("Expected build event never happened for %s", iproject.getName()));
+ }
+
+ /**
+ * Scans a given IResourceDelta looking for a "build event" change for given IProject
+ *
+ */
+ private class BuiltProjectDeltaVisitor implements IResourceDeltaVisitor {
+
+ private IProject mIProject;
+ private boolean mIsBuilt;
+
+ public BuiltProjectDeltaVisitor(IProject iproject) {
+ mIProject = iproject;
+ mIsBuilt = false;
+ }
+
+ @Override
+ public boolean visit(IResourceDelta delta) {
+ if (mIProject.equals(delta.getResource())) {
+ setBuilt(true);
+ return false;
+ }
+ return true;
+ }
+
+ private synchronized void setBuilt(boolean b) {
+ mIsBuilt = b;
+ }
+
+ public synchronized boolean isProjectBuilt() {
+ return mIsBuilt;
+ }
+ }
+}