org.eclipse.amp.amf.testing.ide.TestRunSet.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.amp.amf.testing.ide.TestRunSet.java

Source

/**
 * <copyright>
 *
 * Copyright (c) 2009 Metascape, LLC.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *   Metascape - Initial API and Implementation
 *
 * </copyright>
 *
 */
package org.eclipse.amp.amf.testing.ide;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.time.DateFormatUtils;
import org.eclipse.amp.amf.abase.IInterpreterProvider;
import org.eclipse.amp.amf.parameters.AParFactory;
import org.eclipse.amp.amf.testing.ATestInterpreter;
import org.eclipse.amp.amf.testing.aTest.Model;
import org.eclipse.amp.amf.testing.aTest.TestMember;
import org.eclipse.amp.amf.testing.ares.ResultType;
import org.eclipse.amp.amf.testing.ares.RunSet;
import org.eclipse.amp.amf.testing.ares.impl.AresFactoryImpl;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLParserPool;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl;

public class TestRunSet {

    // TODO allow maximum threads to be preferences
    private static final int MAX_THREADS = 8;

    String name;

    private Resource aResResource;

    private RunSet runSet;

    public final static IPath RESULTS_FOLDER = new Path("test-results");

    int testRunCount;
    int testInFlightCount;
    int testCompleteCount;
    int testSuccessCount;

    List<IResource> uniqueTests;

    private List lookupTable = new ArrayList();

    private IProgressMonitor monitor;

    private MultiStatus status;

    private IInterpreterProvider aParPool;

    /**
     * The total number of tests waiting including multiple runs per resource
     */
    private List<Resource> testsWaiting;

    IProject project;

    int runsPerTest;

    private XMLParserPool parserPool = new XMLParserPoolImpl();

    private Map nameToFeatureMap = new HashMap();

    private ResourceSet resourceSet;

    private final IResource firstResource;

    public TestRunSet(IProject project, IResource res, List<IResource> testResources, int runsPerTest) {
        super();
        this.firstResource = res;
        this.uniqueTests = testResources;
        // use first test location for project
        this.project = project;
        this.runsPerTest = runsPerTest;

        name = getName();
    }

    private String getName() {
        String name = "";
        if (firstResource instanceof IFolder) {
            name += ((IFolder) firstResource).getName();
        } else if (uniqueTests.size() < 3) {
            for (IResource res : uniqueTests) {
                name += res.getProjectRelativePath().removeFileExtension().lastSegment() + "_";
            }
        } else {
            for (IResource res : uniqueTests) {
                name += res.getName().substring(0, Math.max(5, res.getName().length() - 1)) + "_";
            }
        }
        name += DateFormatUtils.format(System.currentTimeMillis(), "MM-dd-yy_HH-mm-S");
        return name;
    }

    protected void initialize() {
        monitor.subTask("Creating Test Resource");
        resourceSet = new ResourceSetImpl();

        resourceSet.getLoadOptions().put(XMLResource.OPTION_DEFER_ATTACHMENT, Boolean.TRUE);
        resourceSet.getLoadOptions().put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, Boolean.TRUE);
        resourceSet.getLoadOptions().put(XMLResource.OPTION_USE_DEPRECATED_METHODS, Boolean.TRUE);
        resourceSet.getLoadOptions().put(XMLResource.OPTION_USE_PARSER_POOL, parserPool);
        resourceSet.getLoadOptions().put(XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP, nameToFeatureMap);

        aParPool = AParFactory.createPooled(resourceSet);

        monitor.subTask("Creating Results");

        IResource firstResource = uniqueTests.get(0);
        // Get rid of test folder
        IPath projectPath = RESULTS_FOLDER
                .append(firstResource.getProjectRelativePath().removeFirstSegments(1).removeLastSegments(1))
                .append(name + ".ares");

        URI fileURI = URI.createPlatformResourceURI(project.getName() + "/" + projectPath, true);
        aResResource = resourceSet.createResource(fileURI);

        runSet = AresFactoryImpl.eINSTANCE.createRunSet();

        if (runSet != null) {
            aResResource.getContents().add(runSet);
        } else {
            throw new RuntimeException("Couldn't create resource.");
        }
        if (monitor.isCanceled()) {
            return;
        }
        saveResults();
    }

    private synchronized void saveResults() {
        Map<Object, Object> saveOptions = new HashMap<Object, Object>();
        saveOptions.put(XMLResource.OPTION_CONFIGURATION_CACHE, Boolean.TRUE);
        saveOptions.put(XMLResource.OPTION_USE_CACHED_LOOKUP_TABLE, lookupTable);
        monitor.subTask("Saving Results");
        try {
            aResResource.save(saveOptions);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void runTests(final IProgressMonitor monitor, final MultiStatus status) {
        this.monitor = monitor;
        this.status = status;
        monitor.beginTask("Executing Escape Tests: " + name, uniqueTests.size());

        initialize();
        monitor.subTask("Preparing Tests");
        testsWaiting = Collections.synchronizedList(new ArrayList<Resource>());
        for (IResource resource : uniqueTests) {

            IPath modelPath = ((IFile) resource).getFullPath();
            URI aTestURI = URI.createPlatformResourceURI(modelPath.toString(), true);
            Resource atestResource = resourceSet.getResource(aTestURI, true);
            Model testmodel = (Model) atestResource.getContents().get(0);
            if (testmodel.getContains().size() == 0) {
                for (int i = 0; i < runsPerTest; i++) {
                    testsWaiting.add(atestResource);
                }
            } else {
                for (TestMember member : testmodel.getContains()) {
                    Resource emfResource = resourceSet
                            .getResource(URI.createURI(ATestInterpreter.convertURI(member)), true);
                    for (int i = 0; i < runsPerTest; i++) {
                        testsWaiting.add(emfResource);
                    }
                }
            }
        }
        // Release the unique tests so that the underlying resources can be gc'd when individual tests are removed.
        uniqueTests = null;
        testRunCount = testsWaiting.size();
        testCompleteCount = 0;
        testSuccessCount = 0;

        fillThreads();
        while (testCompleteCount < testRunCount && !monitor.isCanceled()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
        if (!monitor.isCanceled()) {
            if (testSuccessCount == testRunCount) {
                runSet.setResult(ResultType.SUCCESS);
            } else {
                runSet.setResult(ResultType.FAILURE);
            }
            saveResults();
        }
        monitor.done();
    }

    private synchronized void fillThreads() {
        monitor.subTask("(Filling Threads)");
        while (testsWaiting.size() > 0 && testInFlightCount < MAX_THREADS && !monitor.isCanceled()) {
            final Resource nextATest = testsWaiting.remove(0);
            testInFlightCount++;
            // We don't want to block on load interpreter
            new Thread() {
                public void run() {
                    TestRun nextRun = new TestRun(TestRunSet.this, runSet, project, nextATest, aParPool);
                    nextRun.runTest(monitor, status, false);
                };
            }.start();
            updateMonitor();
        }
    }

    public void run() {
        Job escapeRun = new Job("Run " + name) {
            protected IStatus run(IProgressMonitor monitor) {
                final MultiStatus status = new MultiStatus("org.eclipse.amp.amf.testing.ide", Status.OK,
                        "Executing Tests", null);
                runTests(monitor, status);
                return status;
            }
        };
        escapeRun.setPriority(Job.LONG);
        escapeRun.schedule();
    }

    /**
     * @param thread
     */
    public void testComplete(TestRun run, Throwable failureCondition) {
        synchronized (this) {
            if (run.getRun() != null && run.getRun().getResult() == ResultType.SUCCESS) {
                testSuccessCount++;
            }
            testCompleteCount++;
            testInFlightCount--;
            if (failureCondition == null) {
                runSet.getRuns().add(run.getRun());
            }
            fillThreads();
        }
        saveResults();
        updateMonitor();
        monitor.worked(1);
    }

    private void updateMonitor() {
        // Don't block on ui monitor update
        monitor.subTask("Completed " + testCompleteCount + " of " + testRunCount + " ("
                + (testCompleteCount - testSuccessCount) + " failures)");
    }

    public RunSet getRunSet() {
        return runSet;
    }

    public XMLParserPool getParserPool() {
        return parserPool;
    }

    public Map getNameToFeatureMap() {
        return nameToFeatureMap;
    }

    public ResourceSet getResourceSet() {
        return resourceSet;
    }
}