/*******************************************************************************
 * Copyright (c) 2011, 2013 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
 *******************************************************************************/
package org.eclipse.ant.tests.ui.externaltools;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.ant.internal.launching.AntLaunchingUtil;
import org.eclipse.ant.launching.IAntLaunchConstants;
import org.eclipse.ant.tests.ui.testplugin.AbstractAntUITest;
import org.eclipse.core.externaltools.internal.IExternalToolConstants;
import org.eclipse.core.externaltools.internal.model.BuilderCoreUtils;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;

/**
 * Tests for {@link BuilderCoreUtils}
 * 
 * @since 3.5.100 org.eclipse.ant.tests.ui
 */
public class BuilderCoreUtilsTests extends AbstractExternalToolTest {

	/**
	 * Constructor
	 */
	public BuilderCoreUtilsTests() {
		super("BuilderCoreUtils Tests"); //$NON-NLS-1$
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ant.tests.ui.testplugin.AbstractAntUITest#setUp()
	 */
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		// create the external tool builder dir
		BuilderCoreUtils.getBuilderFolder(getProject(), true);
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configFromBuildCommandArgs(org.eclipse.core.resources.IProject, java.util.Map, String[])} method. <br>
	 * <br>
	 * Tests the argument map missing the {@link BuilderCoreUtils#LAUNCH_CONFIG_HANDLE} attribute and all other config arguments
	 * 
	 * @throws Exception
	 */
	public void testConfigFromBuildCommandArgs1() throws Exception {
		ILaunchConfiguration config = BuilderCoreUtils.configFromBuildCommandArgs(getProject(), new HashMap<String, String>(), new String[] { BuilderCoreUtils.VERSION_1_0 });
		assertNull("There should be no configuration returned without the config handle and arguments", config); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configFromBuildCommandArgs(org.eclipse.core.resources.IProject, java.util.Map, String[])} method. <br>
	 * <br>
	 * Tests the argument map missing the {@link BuilderCoreUtils#LAUNCH_CONFIG_HANDLE} attribute only
	 * 
	 * @throws Exception
	 */
	public void testConfigFromBuildCommandArgs2() throws Exception {
		Map<String, String> args = get20AntArgumentMap();
		ILaunchConfiguration config = BuilderCoreUtils.configFromBuildCommandArgs(getProject(), args, new String[] { BuilderCoreUtils.VERSION_2_1 });
		assertNotNull("There should be a migrated configuration returned", config); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configFromBuildCommandArgs(org.eclipse.core.resources.IProject, java.util.Map, String[])} method. <br>
	 * <br>
	 * Tests the argument map with an invalid {@link BuilderCoreUtils#LAUNCH_CONFIG_HANDLE} attribute
	 * 
	 * @throws Exception
	 */
	public void testConfigFromBuildCommandArgs3() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(BuilderCoreUtils.LAUNCH_CONFIG_HANDLE, "foo"); //$NON-NLS-1$
		ILaunchConfiguration config = BuilderCoreUtils.configFromBuildCommandArgs(getProject(), args, new String[] { BuilderCoreUtils.VERSION_2_1 });
		assertNull("There should be no configuration returned", config); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configFromBuildCommandArgs(org.eclipse.core.resources.IProject, java.util.Map, String[])} method. <br>
	 * <br>
	 * Tests the argument map with a valid {@link BuilderCoreUtils#LAUNCH_CONFIG_HANDLE} attribute with no project prefix, but does include the
	 * .externalToolBuilders dir name - causes a lookup in the launch manager which fails because of the extra path prefix
	 * 
	 * @throws Exception
	 */
	public void testConfigFromBuildCommandArgs4() throws Exception {
		createExternalToolBuilder(getProject(), "testConfigFromBuildCommandArgs4", null); //$NON-NLS-1$
		Map<String, String> args = new HashMap<String, String>();
		args.put(BuilderCoreUtils.LAUNCH_CONFIG_HANDLE, "/.externalToolBuilders/testConfigFromBuildCommandArgs4.launch"); //$NON-NLS-1$
		ILaunchConfiguration config = BuilderCoreUtils.configFromBuildCommandArgs(getProject(), args, new String[] { BuilderCoreUtils.VERSION_2_1 });
		assertNull("There should be no configuration returned", config); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configFromBuildCommandArgs(org.eclipse.core.resources.IProject, java.util.Map, String[])} method. <br>
	 * <br>
	 * Tests the argument map with a valid {@link BuilderCoreUtils#LAUNCH_CONFIG_HANDLE} attribute with no project prefix - causes a lookup in the
	 * launch manager returns the config
	 * 
	 * @throws Exception
	 */
	public void testConfigFromBuildCommandArgs5() throws Exception {
		createExternalToolBuilder(getProject(), "testConfigFromBuildCommandArgs5", null); //$NON-NLS-1$
		Map<String, String> args = new HashMap<String, String>();
		args.put(BuilderCoreUtils.LAUNCH_CONFIG_HANDLE, "testConfigFromBuildCommandArgs5.launch"); //$NON-NLS-1$
		ILaunchConfiguration config = BuilderCoreUtils.configFromBuildCommandArgs(getProject(), args, new String[] { BuilderCoreUtils.VERSION_2_1 });
		assertNotNull("There should be a configuration returned", config); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configFromBuildCommandArgs(org.eclipse.core.resources.IProject, java.util.Map, String[])} method. <br>
	 * <br>
	 * Tests the argument map with a valid {@link BuilderCoreUtils#LAUNCH_CONFIG_HANDLE} attribute with the project prefix but not including the
	 * .externalToolBuilder path segment
	 * 
	 * @throws Exception
	 */
	public void testConfigFromBuildCommandArgs6() throws Exception {
		createExternalToolBuilder(getProject(), "testConfigFromBuildCommandArgs6", null); //$NON-NLS-1$
		Map<String, String> args = new HashMap<String, String>();
		args.put(BuilderCoreUtils.LAUNCH_CONFIG_HANDLE, "<project>/testConfigFromBuildCommandArgs6.launch"); //$NON-NLS-1$
		ILaunchConfiguration config = BuilderCoreUtils.configFromBuildCommandArgs(getProject(), args, new String[] { BuilderCoreUtils.VERSION_2_1 });
		assertNull("There should be no configuration returned", config); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configFromBuildCommandArgs(org.eclipse.core.resources.IProject, java.util.Map, String[])} method. <br>
	 * <br>
	 * Tests the argument map with a valid {@link BuilderCoreUtils#LAUNCH_CONFIG_HANDLE} attribute with the project prefix and a valid config path
	 * 
	 * @throws Exception
	 */
	public void testConfigFromBuildCommandArgs7() throws Exception {
		createExternalToolBuilder(getProject(), "testConfigFromBuildCommandArgs7", null); //$NON-NLS-1$
		Map<String, String> args = new HashMap<String, String>();
		args.put(BuilderCoreUtils.LAUNCH_CONFIG_HANDLE, "<project>/.externalToolBuilders/testConfigFromBuildCommandArgs7.launch"); //$NON-NLS-1$
		ILaunchConfiguration config = BuilderCoreUtils.configFromBuildCommandArgs(getProject(), args, new String[] { BuilderCoreUtils.VERSION_2_1 });
		assertNotNull("There should be a configuration returned", config); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for a full build of the default target after a clean
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers1() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_AFTER_CLEAN_TARGETS, null);
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_FULL);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers1", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building FULL builds", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - null given for target names", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for a full build of a specific targets 'def' and 'clean'
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers2() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_AFTER_CLEAN_TARGETS, "def,clean"); //$NON-NLS-1$
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_FULL);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers2", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building FULL builds", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - only available during a build", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for an incremental AND full build with default targets <br>
	 * <br>
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=114563
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers3() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_MANUAL_TARGETS, null);
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_INCREMENTAL);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers3", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building INCREMENTAL builds", command.isBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD)); //$NON-NLS-1$
		assertTrue("the command must be building FULL builds", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - null given for target names", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for an incremental AND full build with the targets 'def' and 'inc' <br>
	 * <br>
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=114563
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers4() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_MANUAL_TARGETS, "def,inc"); //$NON-NLS-1$
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_INCREMENTAL);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers4", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building INCREMENTAL builds", command.isBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD)); //$NON-NLS-1$
		assertTrue("the command must be building FULL builds", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - only available during a build", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for an auto build
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers5() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_AUTO_TARGETS, null);
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_AUTO);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers5", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building AUTO builds", command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - null given for target names", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for an auto build with the targets 'def' and 'auto'
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers6() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_AUTO_TARGETS, "def,auto"); //$NON-NLS-1$
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_AUTO);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers6", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building AUTO builds", command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - only available during a build", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for a clean build
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers7() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_CLEAN_TARGETS, null);
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_CLEAN);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers7", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.CLEAN_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - null given for target names", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for a clean build with the targets 'def' and 'clean'
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers8() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_CLEAN_TARGETS, "def,clean"); //$NON-NLS-1$
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_CLEAN);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers6", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.CLEAN_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - only available during a build", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for a full + incremental build with the targets 'def' and 'inc' specified for after clean targets and
	 * manual targets respectively
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers9() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_AFTER_CLEAN_TARGETS, "def"); //$NON-NLS-1$
		args.put(IAntLaunchConstants.ATTR_ANT_MANUAL_TARGETS, "inc"); //$NON-NLS-1$
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, IExternalToolConstants.BUILD_TYPE_CLEAN
				+ "," + IExternalToolConstants.BUILD_TYPE_INCREMENTAL); //$NON-NLS-1$
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers9", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - only available during a build", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#configureTriggers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)} method <br>
	 * <br>
	 * Tests that the triggers are configured for a full + incremental build with the targets 'def' and 'inc' specified for after clean targets and
	 * manual targets respectively
	 * 
	 * @throws Exception
	 */
	public void testConfigureTriggers10() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		args.put(IAntLaunchConstants.ATTR_ANT_AFTER_CLEAN_TARGETS, "def"); //$NON-NLS-1$
		args.put(IAntLaunchConstants.ATTR_ANT_MANUAL_TARGETS, "inc"); //$NON-NLS-1$
		args.put(IAntLaunchConstants.ATTR_ANT_AUTO_TARGETS, "auto"); //$NON-NLS-1$
		args.put(IAntLaunchConstants.ATTR_ANT_CLEAN_TARGETS, "clean"); //$NON-NLS-1$
		args.put(IExternalToolConstants.ATTR_LOCATION, getBuildFile(EXT_BUILD_FILE_NAME).getAbsolutePath());
		String kinds = IExternalToolConstants.BUILD_TYPE_CLEAN + "," + //$NON-NLS-1$
				IExternalToolConstants.BUILD_TYPE_INCREMENTAL + "," + //$NON-NLS-1$
				IExternalToolConstants.BUILD_TYPE_AUTO + "," + //$NON-NLS-1$
				IExternalToolConstants.BUILD_TYPE_FULL;
		args.put(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, kinds);
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testConfigureTriggers10", args); //$NON-NLS-1$
		assertNotNull("the test builder must not be null", config); //$NON-NLS-1$
		ICommand command = createBuildCommand(config);
		assertNotNull("the test build command must not be null", command); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD)); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.CLEAN_BUILD)); //$NON-NLS-1$
		assertTrue("the command must be building CLEAN builds", command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD)); //$NON-NLS-1$
		String[] names = AntLaunchingUtil.getTargetNames(config);
		assertNull("should be no target names resolved from the config - only available during a build", names); //$NON-NLS-1$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#isUnmigratedConfig(org.eclipse.debug.core.ILaunchConfiguration)} method
	 * 
	 * @throws Exception
	 */
	public void testIsUnmigratedConfig1() throws Exception {
		ILaunchConfigurationType type = AbstractAntUITest.getLaunchManager().getLaunchConfigurationType(IAntLaunchConstants.ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE);
		if (type != null) {
			ILaunchConfigurationWorkingCopy config = type.newInstance(BuilderCoreUtils.getBuilderFolder(getProject(), true), "testIsUnmigratedConfig1"); //$NON-NLS-1$
			assertTrue("should be considered 'unmigrated'", BuilderCoreUtils.isUnmigratedConfig(config)); //$NON-NLS-1$
		} else {
			fail("could not find the Ant builder launch configuration type"); //$NON-NLS-1$
		}
	}

	/**
	 * Tests the {@link BuilderCoreUtils#isUnmigratedConfig(org.eclipse.debug.core.ILaunchConfiguration)} method
	 * 
	 * @throws Exception
	 */
	public void testIsUnmigratedConfig2() throws Exception {
		ILaunchConfiguration config = createExternalToolBuilder(getProject(), "testIsUnmigratedConfig2", null); //$NON-NLS-1$
		assertFalse("Shoudl not be considered 'unmigrated'", BuilderCoreUtils.isUnmigratedConfig(config)); //$NON-NLS-1$
	}

	/**
	 * Tests the
	 * {@link BuilderCoreUtils#toBuildCommand(org.eclipse.core.resources.IProject, org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)}
	 * method <br>
	 * <br>
	 * Tests the case of a new un-saved {@link ILaunchConfiguration}
	 * 
	 * @throws Exception
	 */
	public void testToBuildCommand1() throws Exception {
		ILaunchConfigurationWorkingCopy copy = createExternalToolBuilderWorkingCopy(getProject(), "testToBuildCommand1", null); //$NON-NLS-1$
		ICommand command = BuilderCoreUtils.toBuildCommand(getProject(), copy, getProject().getDescription().newCommand());
		assertNotNull("There should have been a new build command created", command); //$NON-NLS-1$
	}

	/**
	 * Tests the
	 * {@link BuilderCoreUtils#toBuildCommand(org.eclipse.core.resources.IProject, org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)}
	 * method <br>
	 * <br>
	 * Tests the case of an existing configuration
	 * 
	 * @throws Exception
	 */
	public void testToBuildCommand2() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		ILaunchConfiguration copy = createExternalToolBuilder(getProject(), "testToBuildCommand2", args); //$NON-NLS-1$
		ICommand command = BuilderCoreUtils.toBuildCommand(getProject(), copy, getProject().getDescription().newCommand());
		assertNotNull("There should have been a new build command created", command); //$NON-NLS-1$
	}

	/**
	 * Tests the
	 * {@link BuilderCoreUtils#toBuildCommand(org.eclipse.core.resources.IProject, org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.resources.ICommand)}
	 * method <br>
	 * <br>
	 * Tests the case of the working copy of an existing configuration
	 * 
	 * @throws Exception
	 */
	public void testToBuildCommand3() throws Exception {
		Map<String, String> args = new HashMap<String, String>();
		ILaunchConfiguration copy = createExternalToolBuilder(getProject(), "testToBuildCommand3", args); //$NON-NLS-1$
		ICommand command = BuilderCoreUtils.toBuildCommand(getProject(), copy.getWorkingCopy(), getProject().getDescription().newCommand());
		assertNotNull("There should have been a new build command created", command); //$NON-NLS-1$
	}

	/**
	 * Tests the
	 * {@link BuilderCoreUtils#migrateBuilderConfiguration(org.eclipse.core.resources.IProject, org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)}
	 * method
	 * 
	 * @throws Exception
	 */
	public void testMigrateBuilderConfiguration1() throws Exception {
		ILaunchConfigurationWorkingCopy copy = createExternalToolBuilderWorkingCopy(getProject(), "testMigrateBuilderConfiguration1", null); //$NON-NLS-1$
		ILaunchConfiguration config = BuilderCoreUtils.migrateBuilderConfiguration(getProject(), copy);
		assertNotNull("The un-saved working copy should have been migrated", config); //$NON-NLS-1$
		assertTrue("The name of the migrated configuration should be testMigrateBuilderConfiguration1", config.getName().equals("testMigrateBuilderConfiguration1")); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Tests the
	 * {@link BuilderCoreUtils#migrateBuilderConfiguration(org.eclipse.core.resources.IProject, org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)}
	 * method
	 * 
	 * @throws Exception
	 */
	public void testMigrateBuilderConfiguration2() throws Exception {
		ILaunchConfigurationWorkingCopy copy = createExternalToolBuilderWorkingCopy(getProject(), "testMigra/teBuilderConfi/guration2", null); //$NON-NLS-1$
		ILaunchConfiguration config = BuilderCoreUtils.migrateBuilderConfiguration(getProject(), copy);
		assertNotNull("The un-saved working copy should have been migrated", config); //$NON-NLS-1$
		assertTrue("The name of the migrated configuration should be testMigra.teBuilderConfi.guration2", config.getName().equals("testMigra.teBuilderConfi.guration2")); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Tests the {@link BuilderCoreUtils#buildTypesToArray(String)} method
	 * 
	 * @throws Exception
	 */
	public void testBuildTypesToArray1() throws Exception {
		String kinds = IExternalToolConstants.BUILD_TYPE_CLEAN + "," + //$NON-NLS-1$
				IExternalToolConstants.BUILD_TYPE_INCREMENTAL + "," + //$NON-NLS-1$
				IExternalToolConstants.BUILD_TYPE_AUTO + "," + //$NON-NLS-1$
				IExternalToolConstants.BUILD_TYPE_FULL;
		int[] array = BuilderCoreUtils.buildTypesToArray(kinds);
		assertNotNull("The build kinds array cannot be null", array); //$NON-NLS-1$
		boolean contains = true;
		for (int i = 0; i < array.length; i++) {
			contains &= (array[i] == IncrementalProjectBuilder.AUTO_BUILD) | (array[i] == IncrementalProjectBuilder.CLEAN_BUILD)
					| (array[i] == IncrementalProjectBuilder.FULL_BUILD) | (array[i] == IncrementalProjectBuilder.INCREMENTAL_BUILD);
			if (!contains) {
				break;
			}
		}
		assertTrue("All of the build kinds should have been found", contains); //$NON-NLS-1$
	}
}
