diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/sampleProjects/SampleProjectTest.java | 263 |
1 files changed, 263 insertions, 0 deletions
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; + } + } +} |