/*******************************************************************************
 *  Copyright (c) 2000, 2017 IBM Corporation and others.
 *  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:
 *     IBM Corporation - initial API and implementation
 *     Alexander Kurtakov <akurtako@redhat.com> - Bug 459343
 *******************************************************************************/
package org.eclipse.core.tests.internal.builders;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.tests.harness.TestBarrier;
import org.eclipse.core.tests.harness.TestJob;

/**
 * This class tests public API related to building and to build specifications.
 * Specifically, the following methods are tested:
 *
 * IWorkspace#build IProject#build IProjectDescription#getBuildSpec
 * IProjectDescription#setBuildSpec
 */
public class BuilderTest extends AbstractBuilderTest {
	public static Test suite() {
		return new TestSuite(BuilderTest.class);
		//		TestSuite suite = new TestSuite();
		//		suite.addTest(new BuilderTest("testInterruptAutobuild"));
		//		return suite;
	}

	public BuilderTest() {
		super(null);
	}

	/**
	 * BuilderTest constructor comment.
	 *
	 * @param name
	 *                  java.lang.String
	 */
	public BuilderTest(String name) {
		super(name);
	}

	/**
	 * Tears down the fixture, for example, close a network connection. This
	 * method is called after a test is executed.
	 */
	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		getWorkspace().getRoot().delete(true, null);
		TestBuilder builder = SortBuilder.getInstance();
		if (builder != null) {
			builder.reset();
		}
		builder = DeltaVerifierBuilder.getInstance();
		if (builder != null) {
			builder.reset();
		}
	}

	/**
	 * Make sure this test runs first, before any other test
	 * has a chance to mess with the build order.
	 */
	public void testAardvarkBuildOrder() {
		IWorkspace workspace = getWorkspace();
		//builder order should initially be null
		assertEquals("1.0", null, workspace.getDescription().getBuildOrder());
	}

	/**
	 * Tests the lifecycle of a builder.
	 *
	 * @see SortBuilder
	 */
	public void testAutoBuildPR() {
		//REF: 1FUQUJ4
		// Create some resource handles
		IWorkspace workspace = getWorkspace();
		IProject project1 = workspace.getRoot().getProject("PROJECT" + 1);
		IFolder folder = project1.getFolder("FOLDER");
		IFolder sub = folder.getFolder("sub");
		IFile fileA = folder.getFile("A");
		IFile fileB = sub.getFile("B");
		// Create some resources
		try {
			// Turn auto-building on
			setAutoBuilding(true);
			project1.create(getMonitor());
			project1.open(getMonitor());
			// Set build spec
			IProjectDescription desc = project1.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			command.getArguments().put(TestBuilder.BUILD_ID, "Project1Build1");
			desc.setBuildSpec(new ICommand[] {command});
			project1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		// Create folders and files
		try {
			folder.create(true, true, getMonitor());
			fileA.create(getRandomContents(), true, getMonitor());
			sub.create(true, true, getMonitor());
			fileB.create(getRandomContents(), true, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
	}

	/**
	 * Tests installing and running a builder that always fails during
	 * instantation.
	 */
	public void testBrokenBuilder() {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		try {
			setAutoBuilding(false);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build spec for the project
		try {
			IProjectDescription desc = project.getDescription();
			ICommand command1 = desc.newCommand();
			command1.setBuilderName(BrokenBuilder.BUILDER_NAME);
			ICommand command2 = desc.newCommand();
			command2.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command1, command2});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		//do an incremental build -- build should fail, but second builder
		// should run
		try {
			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			fail("3.0");
		} catch (CoreException e) {
			//expected
		}
		TestBuilder verifier = SortBuilder.getInstance();
		verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
		verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
		verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
		verifier.assertLifecycleEvents("3.1");
		//build again -- it should succeed this time
		try {
			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("4.0", e);
		}
	}

	public void testBuildClean() {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build spec for the project
		try {
			IProjectDescription desc = project.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, DeltaVerifierBuilder.BUILDER_NAME, "Project2Build2")});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		//start with a clean build
		try {
			getWorkspace().build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("3.1", e);
		}
		DeltaVerifierBuilder verifier = DeltaVerifierBuilder.getInstance();
		assertTrue("3.2", verifier.wasCleanBuild());
		// Now do an incremental build - since delta was null it should appear as a clean build
		try {
			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("3.3", e);
		}
		assertTrue("3.4", verifier.wasFullBuild());
		// next time it will appear as an incremental build
		try {
			project.touch(getMonitor());
			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("3.5", e);
		}
		assertTrue("3.6", verifier.wasIncrementalBuild());
		//do another clean
		try {
			getWorkspace().build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("3.7", e);
		}
		assertTrue("3.8", verifier.wasCleanBuild());
		//doing a full build should still look like a full build
		try {
			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("3.9", e);
		}
		assertTrue("3.10", verifier.wasFullBuild());
	}

	/**
	 * Tests the lifecycle of a builder.
	 *
	 * @see SortBuilder
	 */
	public void testBuildCommands() {
		// Create some resource handles
		IWorkspace workspace = getWorkspace();
		IProject project1 = workspace.getRoot().getProject("PROJECT" + 1);
		IProject project2 = workspace.getRoot().getProject("PROJECT" + 2);
		IFile file1 = project1.getFile("FILE1");
		IFile file2 = project2.getFile("FILE2");
		//set the build order
		try {
			IWorkspaceDescription workspaceDesc = workspace.getDescription();
			workspaceDesc.setBuildOrder(new String[] {project1.getName(), project2.getName()});
			workspace.setDescription(workspaceDesc);
		} catch (CoreException e) {
			fail("0.0", e);
		}
		TestBuilder verifier = null;
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create some resources
			project1.create(getMonitor());
			project1.open(getMonitor());
			project2.create(getMonitor());
			project2.open(getMonitor());
			file1.create(getRandomContents(), true, getMonitor());
			file2.create(getRandomContents(), true, getMonitor());
			// Do an initial build to get the builder instance
			IProjectDescription desc = project1.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Project1Build1")});
			project1.setDescription(desc, getMonitor());
			project1.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier = SortBuilder.getInstance();
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Project1Build1");
			verifier.assertLifecycleEvents("1.0");
		} catch (CoreException e) {
			fail("1.99", e);
		}
		// Build spec with no commands
		try {
			IProjectDescription desc = project1.getDescription();
			desc.setBuildSpec(new ICommand[] {});
			project1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}
		// Build the project -- should do nothing
		try {
			verifier.reset();
			dirty(file1);
			project1.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.assertLifecycleEvents("3.1");
		} catch (CoreException e) {
			fail("3.99", e);
		}
		// Build command with no arguments -- will use default build ID
		try {
			IProjectDescription desc = project1.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command});
			project1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("4.99", e);
		}
		// Build the project
		// Note that since the arguments have changed, the identity of the build
		// command is different so a new builder will be instantiated
		try {
			dirty(file1);
			project1.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
			verifier.assertLifecycleEvents("5.2");
		} catch (CoreException e) {
			fail("5.99", e);
		}
		// Create and set a build specs for project one
		try {
			IProjectDescription desc = project1.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Project1Build1")});
			project1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("6.99", e);
		}
		// Create and set a build spec for project two
		try {
			IProjectDescription desc = project2.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, SortBuilder.BUILDER_NAME, "Project2Build1"), createCommand(desc, DeltaVerifierBuilder.BUILDER_NAME, "Project2Build2")});
			project2.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("7.99", e);
		}
		// Build
		try {
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Project1Build1");
			//second builder is touched for the first time
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Project2Build1");
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Project2Build2");
			dirty(file1);
			dirty(file2);
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.assertLifecycleEvents("8.0");
			verifier.addExpectedLifecycleEvent("Project1Build1");
			dirty(file1);
			project1.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			verifier.assertLifecycleEvents("8.2");
			dirty(file2);
			project2.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Project2Build1");
			verifier.addExpectedLifecycleEvent("Project2Build2");
			verifier.assertLifecycleEvents("8.3");
		} catch (CoreException e) {
			fail("8.99", e);
		}
		// Change order of build commands
		try {
			IProjectDescription desc = project2.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, DeltaVerifierBuilder.BUILDER_NAME, "Project2Build2"), createCommand(desc, SortBuilder.BUILDER_NAME, "Project2Build1")});
			project2.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("10.99", e);
		}
		// Build
		try {
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Project1Build1");
			verifier.addExpectedLifecycleEvent("Project2Build2");
			verifier.addExpectedLifecycleEvent("Project2Build1");
			verifier.assertLifecycleEvents("11.0");
			dirty(file1);
			dirty(file2);
			project1.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Project1Build1");
			verifier.assertLifecycleEvents("11.2");
			dirty(file1);
			dirty(file2);
			project2.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Project2Build2");
			verifier.addExpectedLifecycleEvent("Project2Build1");
			verifier.assertLifecycleEvents("11.3 ");
		} catch (CoreException e) {
			fail("11.99", e);
		}
	}

	/**
	 * Tests that a pre_build listener is not called if there have been no changes
	 * since the last build of any kind occurred.  See https://bugs.eclipse.org/bugs/show_bug.cgi?id=154880.
	 */
	public void testPreBuildEvent() {
		IWorkspace workspace = getWorkspace();
		// Create some resource handles
		final boolean[] notified = new boolean[] {false};
		IProject proj1 = workspace.getRoot().getProject("PROJECT" + 1);
		final IResourceChangeListener listener = event -> notified[0] = true;
		workspace.addResourceChangeListener(listener, IResourceChangeEvent.PRE_BUILD);
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create some resources
			proj1.create(getMonitor());
			proj1.open(getMonitor());
			// Create and set a build spec for project one
			IProjectDescription desc = proj1.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build0")});
			proj1.setDescription(desc, getMonitor());
			proj1.build(IncrementalProjectBuilder.FULL_BUILD, SortBuilder.BUILDER_NAME, new HashMap<String, String>(), null);
			notified[0] = false;
			//now turn on autobuild and see if the listener is notified again
			setAutoBuilding(true);
			waitForBuild();
			assertTrue("1.0", !notified[0]);
		} catch (CoreException e) {
			fail("2.99", e);
		} finally {
			workspace.removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the lifecycle of a builder.
	 *
	 * @see SortBuilder
	 */
	public void testBuildOrder() {
		IWorkspace workspace = getWorkspace();
		// Create some resource handles
		IProject proj1 = workspace.getRoot().getProject("PROJECT" + 1);
		IProject proj2 = workspace.getRoot().getProject("PROJECT" + 2);
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create some resources
			proj1.create(getMonitor());
			proj1.open(getMonitor());
			proj2.create(getMonitor());
			proj2.open(getMonitor());
			//set the build order
			setBuildOrder(proj1, proj2);
		} catch (CoreException e) {
			fail("1.99", e);
		}
		// Create and set a build specs for project one
		try {
			IProjectDescription desc = proj1.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build0")});
			proj1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}
		// Create and set a build spec for project two
		try {
			IProjectDescription desc = proj2.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build1"), createCommand(desc, "Build2")});
			proj2.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("3.99", e);
		}
		// Set up a plug-in lifecycle verifier for testing purposes
		TestBuilder verifier = null;
		// Build the workspace
		try {
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier = SortBuilder.getInstance();
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Build2");
			verifier.assertLifecycleEvents("4.0 ");
		} catch (CoreException e) {
			fail("4.99", e);
		}
		//build in reverse order
		try {
			setBuildOrder(proj2, proj1);
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent("Build2");
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.assertLifecycleEvents("5.0");
		} catch (CoreException e) {
			fail("5.99");
		}
		//only specify build order for project1
		try {
			setBuildOrder(proj1);
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent("Build2");
			verifier.assertLifecycleEvents("6.0");
		} catch (CoreException e) {
			fail("6.99");
		}
		//only specify build order for project2
		try {
			setBuildOrder(proj2, proj1);
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent("Build2");
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.assertLifecycleEvents("7.0");
		} catch (CoreException e) {
			fail("7.99");
		}
	}

	/**
	 * Tests that changing the dynamic build order will induce an autobuild on a project.
	 * This is a regression test for bug 60653.
	 */
	public void testChangeDynamicBuildOrder() {
		IWorkspace workspace = getWorkspace();
		// Create some resource handles
		final IProject proj1 = workspace.getRoot().getProject("PROJECT" + 1);
		final IProject proj2 = workspace.getRoot().getProject("PROJECT" + 2);
		try {
			// Turn auto-building on and make sure there is no explicit build order
			setAutoBuilding(true);
			IWorkspaceDescription wsDescription = getWorkspace().getDescription();
			wsDescription.setBuildOrder(null);
			getWorkspace().setDescription(wsDescription);
			// Create and set a build spec for project two
			getWorkspace().run((IWorkspaceRunnable) monitor -> {
				proj2.create(getMonitor());
				proj2.open(getMonitor());
				IProjectDescription desc = proj2.getDescription();
				desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build1")});
				proj2.setDescription(desc, getMonitor());
			}, getMonitor());
			waitForBuild();
		} catch (CoreException e) {
			fail("1.99", e);
		}
		// Set up a plug-in lifecycle verifier for testing purposes
		TestBuilder verifier = SortBuilder.getInstance();
		verifier.reset();
		//create project two and establish a build order by adding a dynamic
		//reference from proj2->proj1 in the same operation
		try {
			getWorkspace().run((IWorkspaceRunnable) monitor -> {
				// Create and set a build specs for project one
				proj1.create(getMonitor());
				proj1.open(getMonitor());
				IProjectDescription desc = proj1.getDescription();
				desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build0")});
				proj1.setDescription(desc, getMonitor());

				//add the dynamic reference to project two
				IProjectDescription description = proj2.getDescription();
				description.setDynamicReferences(new IProject[] {proj1});
				proj2.setDescription(description, IResource.NONE, null);
			}, getMonitor());
		} catch (CoreException e1) {
			fail("2.99", e1);
		}
		waitForBuild();
		//ensure the build happened in the correct order, and that both projects were built
		verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
		verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
		verifier.addExpectedLifecycleEvent("Build0");
		verifier.addExpectedLifecycleEvent("Build1");
		verifier.assertLifecycleEvents("3.0");
	}

	/**
	 * Tests that changing the dynamic build order during a pre-build notification causes projects
	 * to be built in the correct order.
	 * This is a regression test for bug 330194.
	 */
	public void testChangeDynamicBuildOrderDuringPreBuild() throws Exception {
		IWorkspace workspace = getWorkspace();
		// Create some resource handles
		final IProject proj1 = workspace.getRoot().getProject("bug_330194_referencer");
		final IProject proj2 = workspace.getRoot().getProject("bug_330194_referencee");
		// Disable workspace auto-build
		setAutoBuilding(false);

		ensureExistsInWorkspace(proj1, false);
		ensureExistsInWorkspace(proj2, false);

		IProjectDescription desc = proj1.getDescription();
		desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build0")});
		proj1.setDescription(desc, getMonitor());

		desc = proj2.getDescription();
		desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build1")});
		proj2.setDescription(desc, getMonitor());

		// Ensure the builder is instantiated
		workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());

		// Add pre-build listener that swap around the dependencies
		IResourceChangeListener buildListener = event -> {
			try {
				IProjectDescription desc1 = proj1.getDescription();
				IProjectDescription desc2 = proj2.getDescription();
				// Swap around the references
				if (desc1.getDynamicReferences().length == 0) {
					desc1.setDynamicReferences(new IProject[] {proj2});
					desc2.setDynamicReferences(new IProject[0]);
				} else {
					desc1.setDynamicReferences(new IProject[0]);
					desc2.setDynamicReferences(new IProject[] {proj1});
				}
				proj1.setDescription(desc1, getMonitor());
				proj2.setDescription(desc2, getMonitor());
			} catch (CoreException e) {
				fail();
			}
		};
		try {
			getWorkspace().addResourceChangeListener(buildListener, IResourceChangeEvent.PRE_BUILD);
			// Set up a plug-in lifecycle verifier for testing purposes
			TestBuilder verifier = SortBuilder.getInstance();
			verifier.reset();

			// FULL_BUILD 1
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.assertLifecycleEvents("1.0");
			verifier.reset();

			// FULL_BUILD 2
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.assertLifecycleEvents("2.0");
			verifier.reset();

			// AUTO_BUILD
			setAutoBuilding(true);
			proj1.touch(getMonitor());
			waitForBuild();
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.assertLifecycleEvents("3.0");
			verifier.reset();

			// AUTO_BUILD 2
			proj1.touch(getMonitor());
			waitForBuild();
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.assertLifecycleEvents("4.0");
			verifier.reset();

		} finally {
			getWorkspace().removeResourceChangeListener(buildListener);
		}
	}

	/**
	 * Ensure that build order is preserved when project is closed/opened.
	 */
	public void testCloseOpenProject() {
		IWorkspace workspace = getWorkspace();
		IProject project = workspace.getRoot().getProject("PROJECT" + 1);
		try {
			// Create some resources
			project.create(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		// Create and set a build spec
		try {
			IProjectDescription desc = project.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build1"), createCommand(desc, "Build2")});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}
		try {
			project.close(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("3.99", e);
		}
		//ensure the build spec hasn't changed
		try {
			IProjectDescription desc = project.getDescription();
			ICommand[] commands = desc.getBuildSpec();
			assertEquals("4.0", 2, commands.length);
			assertEquals("4.1", commands[0].getBuilderName(), SortBuilder.BUILDER_NAME);
			assertEquals("4.2", commands[1].getBuilderName(), SortBuilder.BUILDER_NAME);
			Map<String, String> args = commands[0].getArguments();
			assertEquals("4.3", "Build1", args.get(TestBuilder.BUILD_ID));
			args = commands[1].getArguments();
			assertEquals("4.4", "Build2", args.get(TestBuilder.BUILD_ID));
		} catch (CoreException e) {
			fail("4.99", e);
		}
	}

	/**
	 * Tests that when a project is copied, the copied project has a full build
	 * but the source project does not.
	 */
	public void testCopyProject() {
		IWorkspace workspace = getWorkspace();
		// Create some resource handles
		IProject proj1 = workspace.getRoot().getProject("testCopyProject" + 1);
		IProject proj2 = workspace.getRoot().getProject("testCopyProject" + 2);
		try {
			// Turn auto-building on
			setAutoBuilding(true);
			// Create some resources
			proj1.create(getMonitor());
			proj1.open(getMonitor());
			ensureDoesNotExistInWorkspace(proj2);
		} catch (CoreException e) {
			fail("1.99", e);
		}
		// Create and set a build spec for project one
		try {
			IProjectDescription desc = proj1.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build0")});
			proj1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}
		waitForBuild();
		SortBuilder.getInstance().reset();
		try {
			IProjectDescription desc = proj1.getDescription();
			desc.setName(proj2.getName());
			proj1.copy(desc, IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("3.99", e);
		}
		waitForBuild();
		SortBuilder builder = SortBuilder.getInstance();
		assertEquals("4.0", proj2, builder.getProject());

		//builder 2 should have done a full build
		builder.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
		builder.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
		builder.addExpectedLifecycleEvent("Build0");
		builder.assertLifecycleEvents("4.4");
		assertTrue("4.5", builder.wasFullBuild());

	}

	/**
	 * Tests an implicit workspace build order created by setting dynamic
	 * project references.
	 */
	public void testDynamicBuildOrder() {
		IWorkspace workspace = getWorkspace();
		// Create some resource handles
		IProject proj1 = workspace.getRoot().getProject("PROJECT" + 1);
		IProject proj2 = workspace.getRoot().getProject("PROJECT" + 2);
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create some resources
			proj1.create(getMonitor());
			proj1.open(getMonitor());
			proj2.create(getMonitor());
			proj2.open(getMonitor());
			//establish a build order by adding a dynamic reference from
			// proj2->proj1
			IProjectDescription description = proj2.getDescription();
			description.setDynamicReferences(new IProject[] {proj1});
			proj2.setDescription(description, IResource.NONE, null);
			IWorkspaceDescription wsDescription = getWorkspace().getDescription();
			wsDescription.setBuildOrder(null);
			getWorkspace().setDescription(wsDescription);
		} catch (CoreException e) {
			fail("1.99", e);
		}
		// Create and set a build specs for project one
		try {
			IProjectDescription desc = proj1.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build0")});
			proj1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.99", e);
		}
		// Create and set a build spec for project two
		try {
			IProjectDescription desc = proj2.getDescription();
			desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build1"), createCommand(desc, "Build2")});
			proj2.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("3.99", e);
		}
		// Set up a plug-in lifecycle verifier for testing purposes
		TestBuilder verifier = null;
		// Build the workspace
		try {
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier = SortBuilder.getInstance();
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent("Build2");
			verifier.assertLifecycleEvents("4.0 ");
		} catch (CoreException e) {
			fail("4.99", e);
		}
		//build in reverse order
		try {
			//reverse the order by adding a dynamic reference from proj1->proj2
			IProjectDescription description = proj2.getDescription();
			description.setDynamicReferences(new IProject[0]);
			proj2.setDescription(description, IResource.NONE, null);
			description = proj1.getDescription();
			description.setDynamicReferences(new IProject[] {proj2});
			proj1.setDescription(description, IResource.NONE, null);
			workspace.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent("Build1");
			verifier.addExpectedLifecycleEvent("Build2");
			verifier.addExpectedLifecycleEvent("Build0");
			verifier.assertLifecycleEvents("5.0");
		} catch (CoreException e) {
			fail("5.99");
		}
	}

	/**
	 * Tests that enabling autobuild causes a build to occur.
	 */
	public void testEnableAutobuild() {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build spec for the project
		try {
			IProjectDescription desc = project.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		// Set up a plug-in lifecycle verifier for testing purposes
		TestBuilder verifier = null;
		//Cause a build by enabling autobuild
		try {
			setAutoBuilding(true);
			waitForBuild();
			verifier = SortBuilder.getInstance();
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
			verifier.assertLifecycleEvents("3.1");
		} catch (CoreException e) {
			fail("3.2", e);
		}
	}

	/**
	 * Tests installing and running a builder that always fails in its build method
	 */
	public void testExceptionBuilder() {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		try {
			setAutoBuilding(false);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build spec for the project
		try {
			IProjectDescription desc = project.getDescription();
			ICommand command1 = desc.newCommand();
			command1.setBuilderName(ExceptionBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command1});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		final boolean[] listenerCalled = new boolean[] {false};
		IResourceChangeListener listener = event -> listenerCalled[0] = true;
		getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.POST_BUILD);
		//do an incremental build -- build should fail, but POST_BUILD should still occur
		try {
			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			fail("3.0");
		} catch (CoreException e) {
			//see discussion in bug 273147 about build exception severity
			assertEquals("3.1", IStatus.ERROR, e.getStatus().getSeverity());
			//expected
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
		assertTrue("1.0", listenerCalled[0]);
	}

	/**
	 * Tests the method IncrementProjectBuilder.forgetLastBuiltState
	 */
	public void testForgetLastBuiltState() {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build spec for the project
		try {
			IProjectDescription desc = project.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		// Set up a plug-in lifecycle verifier for testing purposes
		SortBuilder verifier = null;
		//do an initial build
		try {
			project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, SortBuilder.BUILDER_NAME, null, getMonitor());
			verifier = SortBuilder.getInstance();
		} catch (CoreException e) {
			fail("3.2", e);
		}
		//forget last built state
		verifier.forgetLastBuiltState();
		// Now do another incremental build. Delta should be null
		try {
			project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, SortBuilder.BUILDER_NAME, null, getMonitor());
			assertTrue("4.0", verifier.wasDeltaNull());
		} catch (CoreException e) {
			fail("4.99", e);
		}
		// Do another incremental build, requesting a null build state. Delta
		// should not be null
		verifier.requestForgetLastBuildState();
		try {
			project.touch(getMonitor());
			project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, SortBuilder.BUILDER_NAME, null, getMonitor());
			assertTrue("5.0", !verifier.wasDeltaNull());
		} catch (CoreException e) {
			fail("5.99", e);
		}
		//try a snapshot when a builder has a null tree
		try {
			getWorkspace().save(false, getMonitor());
		} catch (CoreException e) {
			fail("6.99");
		}
		// Do another incremental build. Delta should be null
		try {
			project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, SortBuilder.BUILDER_NAME, null, getMonitor());
			assertTrue("7.0", verifier.wasDeltaNull());
		} catch (CoreException e) {
			fail("7.99", e);
		}
		// Delete the project
		try {
			project.delete(false, getMonitor());
		} catch (CoreException e) {
			fail("99.99", e);
		}
	}

	/**
	 * Tests that a client invoking a manual incremental build before autobuild has had
	 * a chance to run will block until the build completes. See bug 275879.
	 */
	public void testIncrementalBuildBeforeAutobuild() {
		// Create some resource handles
		final IProject project = getWorkspace().getRoot().getProject("PROJECT");
		final IFile input = project.getFolder(SortBuilder.DEFAULT_UNSORTED_FOLDER).getFile("File.txt");
		final IFile output = project.getFolder(SortBuilder.DEFAULT_SORTED_FOLDER).getFile("File.txt");
		try {
			setAutoBuilding(true);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
			IProjectDescription desc = project.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command});
			project.setDescription(desc, getMonitor());
			ensureExistsInWorkspace(input, getRandomContents());
		} catch (CoreException e) {
			fail("0.99", e);
		}
		waitForBuild();
		assertTrue("1.0", output.exists());

		//change the file and then immediately perform build
		final ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			getWorkspace().run((IWorkspaceRunnable) monitor -> {
				input.setContents(new ByteArrayInputStream(new byte[] {5, 4, 3, 2, 1}), IResource.NONE, getMonitor());
				project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
				transferStreams(output.getContents(), out, null, null);
			}, getMonitor());
		} catch (CoreException e) {
			fail("1.99", e);
		}
		byte[] result = out.toByteArray();
		byte[] expected = new byte[] {1, 2, 3, 4, 5};
		assertEquals("2.0", expected.length, result.length);
		for (int i = 0; i < expected.length; i++) {
			assertEquals("2.1." + i, expected[i], result[i]);
		}
	}

	/**
	 * Tests that autobuild is interrupted by a background scheduled job, but eventually completes.
	 */
	public void testInterruptAutobuild() {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		final IFile file = project.getFile("File.txt");
		try {
			setAutoBuilding(true);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
			IProjectDescription desc = project.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command});
			project.setDescription(desc, getMonitor());
			file.create(getRandomContents(), IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		waitForBuild();

		// Set up a plug-in lifecycle verifier for testing purposes
		TestBuilder verifier = SortBuilder.getInstance();
		verifier.reset();

		final TestJob blockedJob = new TestJob("Interrupt build", 3, 1000);
		blockedJob.setRule(getWorkspace().getRoot());
		//use a barrier to ensure the blocking job starts
		final TestBarrier barrier = new TestBarrier();
		barrier.setStatus(TestBarrier.STATUS_WAIT_FOR_START);
		//install a listener that will cause autobuild to be interrupted
		IResourceChangeListener listener = event -> {
			blockedJob.schedule();
			//wait for autobuild to become blocking
			while (!Job.getJobManager().currentJob().isBlocking()) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					//ignore
				}
			}
			//allow the test main method to continue
			barrier.setStatus(TestBarrier.STATUS_RUNNING);
		};
		try {
			getWorkspace().addResourceChangeListener(listener, IResourceChangeEvent.PRE_BUILD);
			// Now change a file. The build should not complete until the job triggered by the listener completes
			file.setContents(getRandomContents(), IResource.NONE, getMonitor());
			//wait for job to be scheduled
			barrier.waitForStatus(TestBarrier.STATUS_RUNNING);
			//wait for test job to complete
			try {
				blockedJob.join();
			} catch (InterruptedException e) {
				fail("1.99", e);
			}
			//autobuild should now run after the blocking job is finished
			waitForBuild();
			verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
			verifier.assertLifecycleEvents("2.0");
		} catch (CoreException e) {
			fail("2.99", e);
		} finally {
			getWorkspace().removeResourceChangeListener(listener);
		}
	}

	/**
	 * Tests the lifecycle of a builder.
	 */
	public void testLifecycleEvents() {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build spec for the project
		try {
			IProjectDescription desc = project.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		// Set up a plug-in lifecycle verifier for testing purposes
		TestBuilder verifier = null;
		//try to do an incremental build when there has never
		//been a batch build
		try {
			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			verifier = SortBuilder.getInstance();
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
			verifier.assertLifecycleEvents("3.1");
		} catch (CoreException e) {
			fail("3.2", e);
		}
		// Now do another incremental build. Since we just did one, nothing
		// should happen in this one.
		try {
			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			verifier.assertLifecycleEvents("3.4");
		} catch (CoreException e) {
			fail("3.5", e);
		}
		// Now do a batch build
		try {
			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
			verifier.assertLifecycleEvents("3.6");
		} catch (CoreException e) {
			fail("3.8", e);
		}
		// Close the project
		try {
			project.close(getMonitor());
		} catch (CoreException e) {
			fail("4.1", e);
		}
		// Open the project, build it, and delete it
		try {
			project.open(getMonitor());
			getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
			project.delete(false, getMonitor());
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
			verifier.assertLifecycleEvents("5.0");
		} catch (CoreException e) {
			fail("5.1", e);
		}
	}

	/**
	 * Tests the lifecycle of a builder.
	 *
	 * @see SortBuilder
	 */
	public void testMoveProject() {
		// Create some resource handles
		IWorkspace workspace = getWorkspace();
		IProject proj1 = workspace.getRoot().getProject("PROJECT" + 1);
		IProject proj2 = workspace.getRoot().getProject("Destination");
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create some resources
			proj1.create(getMonitor());
			proj1.open(getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build specs for project one
		try {
			IProjectDescription desc = proj1.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			command.getArguments().put(TestBuilder.BUILD_ID, "Build0");
			desc.setBuildSpec(new ICommand[] {command});
			proj1.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		// build project1
		try {
			proj1.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("3.0", e);
		}
		// move proj1 to proj2
		try {
			proj1.move(proj2.getFullPath(), false, getMonitor());
		} catch (CoreException e) {
			fail("4.0", e);
		}
		// build proj2
		try {
			proj2.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
		} catch (CoreException e) {
			fail("5.0", e);
		}
	}

	/**
	 * Tests that turning autobuild on will invoke a build in the next
	 * operation.
	 */
	public void testTurnOnAutobuild() throws CoreException {
		// Create some resource handles
		IProject project = getWorkspace().getRoot().getProject("PROJECT");
		final IFile file = project.getFile("File.txt");
		try {
			// Turn auto-building off
			setAutoBuilding(false);
			// Create and open a project
			project.create(getMonitor());
			project.open(getMonitor());
			file.create(getRandomContents(), IResource.NONE, getMonitor());
		} catch (CoreException e) {
			fail("1.0", e);
		}
		// Create and set a build spec for the project
		try {
			IProjectDescription desc = project.getDescription();
			ICommand command = desc.newCommand();
			command.setBuilderName(SortBuilder.BUILDER_NAME);
			desc.setBuildSpec(new ICommand[] {command});
			project.setDescription(desc, getMonitor());
		} catch (CoreException e) {
			fail("2.0", e);
		}
		// Set up a plug-in lifecycle verifier for testing purposes
		TestBuilder verifier = null;
		//try to do an incremental build when there has never
		//been a batch build
		try {
			getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
			verifier = SortBuilder.getInstance();
			verifier.addExpectedLifecycleEvent(TestBuilder.SET_INITIALIZATION_DATA);
			verifier.addExpectedLifecycleEvent(TestBuilder.STARTUP_ON_INITIALIZE);
			verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
			verifier.assertLifecycleEvents("3.1");
		} catch (CoreException e) {
			fail("3.2", e);
		}
		// Now make a change and then turn autobuild on. Turning it on should
		// cause a build.
		IWorkspaceRunnable r = monitor -> {
			file.setContents(getRandomContents(), IResource.NONE, getMonitor());
			IWorkspaceDescription desc = getWorkspace().getDescription();
			desc.setAutoBuilding(true);
			getWorkspace().setDescription(desc);
		};
		waitForBuild();
		getWorkspace().run(r, getMonitor());
		waitForBuild();
		verifier.addExpectedLifecycleEvent(TestBuilder.DEFAULT_BUILD_ID);
		verifier.assertLifecycleEvents("4.0");
	}
}
