/*******************************************************************************
 * Copyright (c) 2010, 2015 Broadcom 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:
 * Broadcom Corporation - initial API and implementation
 * Baltasar Belyavsky (Texas Instruments) - [361675] Order mismatch when saving/restoring workspace trees
 ******************************************************************************/
package org.eclipse.core.tests.internal.builders;

import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.tests.resources.ResourceDeltaVerifier;

/**
 * These tests exercise the project buildConfigs functionality which allows a different
 * builder to be run for different project buildConfigs.
 */
public class BuildConfigurationsTest extends AbstractBuilderTest {
	public static Test suite() {
		return new TestSuite(BuildConfigurationsTest.class);
	}

	private IProject project0;
	private IProject project1;
	private IFile file0;
	private IFile file1;
	private final String variant0 = "Variant0";
	private final String variant1 = "Variant1";
	private final String variant2 = "Variant2";

	public BuildConfigurationsTest(String name) {
		super(name);
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		// Create resources
		IWorkspaceRoot root = getWorkspace().getRoot();
		project0 = root.getProject("BuildVariantTest_p0");
		project1 = root.getProject("BuildVariantTest_p1");
		file0 = project0.getFile("File0");
		file1 = project1.getFile("File1");
		IResource[] resources = {project0, project1, file0, file1};
		ensureExistsInWorkspace(resources, true);
		setAutoBuilding(false);
		setupProject(project0);
		setupProject(project1);
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();

		// Delete resources
		project0.delete(true, null);
		project1.delete(true, null);
	}

	/**
	 * Helper method to configure a project with a build command and several buildConfigs.
	 */
	private void setupProject(IProject project) throws CoreException {
		IProjectDescription desc = project.getDescription();

		// Add build command
		ICommand command = createCommand(desc, ConfigurationBuilder.BUILDER_NAME, "Build0");
		command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true);
		command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true);
		command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true);
		command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, true);
		desc.setBuildSpec(new ICommand[] {command});

		// Create buildConfigs
		desc.setBuildConfigs(new String[] {variant0, variant1, variant2});

		project.setDescription(desc, getMonitor());
	}

	/**
	 * Tests that an incremental builder is run/not run correctly, depending on deltas,
	 * and is given the correct deltas depending on which project variant is being built
	 */
	public void testDeltas() throws CoreException {
		ConfigurationBuilder.clearStats();
		// Run some incremental builds while varying the active variant and whether the project was modified
		// and check that the builder is run/not run with the correct trigger
		file0.setContents(getRandomContents(), true, true, getMonitor());
		incrementalBuild(1, project0, variant1, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		incrementalBuild(2, project0, variant1, false, 1, 0);
		incrementalBuild(3, project0, variant2, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		incrementalBuild(4, project0, variant1, false, 1, 0);
		file0.setContents(getRandomContents(), true, true, getMonitor());
		incrementalBuild(5, project0, variant1, true, 2, IncrementalProjectBuilder.INCREMENTAL_BUILD);
		incrementalBuild(6, project0, variant2, true, 2, IncrementalProjectBuilder.INCREMENTAL_BUILD);
		incrementalBuild(7, project0, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);
	}

	/**
	 * Tests that deltas are preserved per variant when a project is closed then opened.
	 */
	public void testCloseAndOpenProject() throws CoreException {
		ConfigurationBuilder.clearStats();
		file0.setContents(getRandomContents(), true, true, getMonitor());
		incrementalBuild(1, project0, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		incrementalBuild(2, project0, variant1, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		incrementalBuild(3, project0, variant2, true, 1, IncrementalProjectBuilder.FULL_BUILD);

		project0.close(getMonitor());
		ConfigurationBuilder.clearStats();
		project0.open(getMonitor());

		incrementalBuild(4, project0, variant0, false, 0, 0);
		incrementalBuild(5, project0, variant1, false, 0, 0);
		incrementalBuild(6, project0, variant2, false, 0, 0);
	}

	/**
	 * Tests that deltas are restored in the correct order per variant when a project is closed then opened.
	 */
	public void testCloseAndOpenProject_Bug361675() throws CoreException {
		IWorkspaceRoot root = getWorkspace().getRoot();
		IProject tempProject = root.getProject("BuildVariantTest_pTemp");
		IFile tempFile0 = tempProject.getFile("File0");
		IFile tempFile1 = tempProject.getFile("File1");
		IResource[] resources = {tempProject, tempFile0, tempFile1};
		ensureExistsInWorkspace(resources, true);
		setupProject(tempProject);

		try {
			ConfigurationBuilder.clearStats();

			tempFile0.setContents(getRandomContents(), true, true, getMonitor());
			tempFile1.setContents(getRandomContents(), true, true, getMonitor());
			incrementalBuild(1, tempProject, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);
			incrementalBuild(2, tempProject, variant1, true, 1, IncrementalProjectBuilder.FULL_BUILD);
			incrementalBuild(3, tempProject, variant2, true, 1, IncrementalProjectBuilder.FULL_BUILD);

			tempFile0.setContents(getRandomContents(), true, true, getMonitor());
			incrementalBuild(4, tempProject, variant1, true, 2, IncrementalProjectBuilder.INCREMENTAL_BUILD);

			tempFile1.setContents(getRandomContents(), true, true, getMonitor());
			incrementalBuild(5, tempProject, variant2, true, 2, IncrementalProjectBuilder.INCREMENTAL_BUILD);

			tempProject.close(getMonitor());
			ConfigurationBuilder.clearStats();
			tempProject.open(getMonitor());

			// verify variant0 - both File0 and File1 are expected to have changed since it was last built
			incrementalBuild(6, tempProject, variant0, true, 1, IncrementalProjectBuilder.INCREMENTAL_BUILD);
			ConfigurationBuilder builder0 = ConfigurationBuilder.getBuilder(tempProject.getBuildConfig(variant0));
			assertNotNull("6.10", builder0);
			ResourceDeltaVerifier verifier0 = new ResourceDeltaVerifier();
			verifier0.addExpectedChange(tempFile0, tempProject, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			verifier0.addExpectedChange(tempFile1, tempProject, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			verifier0.verifyDelta(builder0.deltaForLastBuild);
			assertTrue("6.11: " + verifier0.getMessage(), verifier0.isDeltaValid());

			// verify variant1 - only File1 is expected to have changed since it was last built
			incrementalBuild(7, tempProject, variant1, true, 1, IncrementalProjectBuilder.INCREMENTAL_BUILD);
			ConfigurationBuilder builder1 = ConfigurationBuilder.getBuilder(tempProject.getBuildConfig(variant1));
			assertNotNull("7.10", builder1);
			ResourceDeltaVerifier verifier1 = new ResourceDeltaVerifier();
			verifier1.addExpectedChange(tempFile1, tempProject, IResourceDelta.CHANGED, IResourceDelta.CONTENT);
			verifier1.verifyDelta(builder1.deltaForLastBuild);
			assertTrue("7.11: " + verifier1.getMessage(), verifier1.isDeltaValid());

			// verify variant2 - no changes are expected since it was last built
			incrementalBuild(8, tempProject, variant2, false, 0, 0);

		} finally {
			tempProject.delete(true, getMonitor());
		}
	}

	/**
	 * Run a workspace build with project references
	 *
	 * References are:
	 *     p0,v0 depends on p0,v1
	 *     p0,v0 depends on p1,v0
	 *     p0,v0 depends on p1,v2
	 * Active buildConfigs are:
	 *     p0,v0 and p1,v0
	 * Build order should be:
	 *     p0,v1  p1,v0  p1,v2  p0,v0
	 */
	public void testBuildReferences() throws CoreException {
		ConfigurationBuilder.clearStats();
		ConfigurationBuilder.clearBuildOrder();
		IProjectDescription desc = project0.getDescription();
		desc.setActiveBuildConfig(variant0);
		project0.setDescription(desc, getMonitor());
		desc = project1.getDescription();
		desc.setActiveBuildConfig(variant0);
		project1.setDescription(desc, getMonitor());

		// Note: references are not alphabetically ordered to check that references are sorted into a stable order
		setReferences(project0, variant0, new IBuildConfiguration[] {project0.getBuildConfig(variant1), project1.getBuildConfig(variant2), project1.getBuildConfig(variant0)});
		getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());

		assertEquals("1.0", 4, ConfigurationBuilder.buildOrder.size());
		assertEquals("1.1", project0.getBuildConfig(variant1), ConfigurationBuilder.buildOrder.get(0));
		assertEquals("1.2", project1.getBuildConfig(variant0), ConfigurationBuilder.buildOrder.get(1));
		assertEquals("1.3", project1.getBuildConfig(variant2), ConfigurationBuilder.buildOrder.get(2));
		assertEquals("1.4", project0.getBuildConfig(variant0), ConfigurationBuilder.buildOrder.get(3));
		checkBuild(2, project0, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		checkBuild(3, project0, variant1, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		checkBuild(4, project0, variant2, false, 0, 0);
		checkBuild(5, project1, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		checkBuild(6, project1, variant1, false, 0, 0);
		checkBuild(7, project1, variant2, true, 1, IncrementalProjectBuilder.FULL_BUILD);

		// Modify project1, all project1 builders should do an incremental build
		file1.setContents(getRandomContents(), true, true, getMonitor());

		ConfigurationBuilder.clearBuildOrder();
		getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());

		assertEquals("8.0", 2, ConfigurationBuilder.buildOrder.size());
		assertEquals("8.1", project1.getBuildConfig(variant0), ConfigurationBuilder.buildOrder.get(0));
		assertEquals("8.2", project1.getBuildConfig(variant2), ConfigurationBuilder.buildOrder.get(1));
		checkBuild(9, project0, variant0, false, 1, 0);
		checkBuild(10, project0, variant1, false, 1, 0);
		checkBuild(11, project0, variant2, false, 0, 0);
		checkBuild(12, project1, variant0, true, 2, IncrementalProjectBuilder.INCREMENTAL_BUILD);
		checkBuild(13, project1, variant1, false, 0, 0);
		checkBuild(14, project1, variant2, true, 2, IncrementalProjectBuilder.INCREMENTAL_BUILD);
	}

	/**
	 * Tests that building a configuration that references a closed / inaccessible project works correctly.
	 * References are:
	 *     p0,v0 depends on p1,v0
	 * p1 is closed.
	 * p0v0 should still be built.
	 * @throws CoreException
	 */
	public void testBuildReferencesOfClosedProject() throws CoreException {
		ConfigurationBuilder.clearStats();
		ConfigurationBuilder.clearBuildOrder();
		IProjectDescription desc = project0.getDescription();
		desc.setActiveBuildConfig(variant0);
		desc.setBuildConfigReferences(variant0, new IBuildConfiguration[] {project1.getBuildConfig(variant0)});
		project0.setDescription(desc, getMonitor());

		// close project 1
		project1.close(getMonitor());
		// should still be able to build project 0.
		getWorkspace().build(new IBuildConfiguration[] {project0.getBuildConfig(variant0)}, IncrementalProjectBuilder.FULL_BUILD, true, getMonitor());
		assertEquals("1.0", 1, ConfigurationBuilder.buildOrder.size());
		assertEquals("1.1", project0.getBuildConfig(variant0), ConfigurationBuilder.buildOrder.get(0));
		checkBuild(2, project0, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);

		// Workspace full build should also build project 0
		ConfigurationBuilder.clearStats();
		ConfigurationBuilder.clearBuildOrder();
		getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());
		assertEquals("1.0", 1, ConfigurationBuilder.buildOrder.size());
		assertEquals("1.1", project0.getBuildConfig(variant0), ConfigurationBuilder.buildOrder.get(0));
		checkBuild(2, project0, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);

		// re-open project 1
		project1.open(getMonitor());

		ConfigurationBuilder.clearStats();
		ConfigurationBuilder.clearBuildOrder();
		getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, getMonitor());

		assertEquals("8.0", 2, ConfigurationBuilder.buildOrder.size());
		assertEquals("8.1", project1.getBuildConfig(variant0), ConfigurationBuilder.buildOrder.get(0));
		assertEquals("8.2", project0.getBuildConfig(variant0), ConfigurationBuilder.buildOrder.get(1));
	}

	/**
	 * Tests that cleaning a project variant does not affect other buildConfigs in the same project
	 */
	public void testClean() throws CoreException {
		ConfigurationBuilder.clearStats();
		incrementalBuild(1, project0, variant0, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		incrementalBuild(2, project0, variant1, true, 1, IncrementalProjectBuilder.FULL_BUILD);
		clean(3, project0, variant0, 2);
		incrementalBuild(4, project0, variant1, false, 1, 0);
	}

	/**
	 * Helper method to set the references for a project.
	 */
	private void setReferences(IProject project, String configId, IBuildConfiguration[] configs) throws CoreException {
		IProjectDescription desc = project.getDescription();
		desc.setBuildConfigReferences(configId, configs);
		project.setDescription(desc, getMonitor());
	}

	/**
	 * Run an incremental build for the given project variant, and check the behaviour of the build.
	 */
	private void incrementalBuild(int testId, IProject project, String variant, boolean shouldBuild, int expectedCount, int expectedTrigger) throws CoreException {
		project.build(project.getBuildConfig(variant), IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor());
		checkBuild(testId, project, variant, shouldBuild, expectedCount, expectedTrigger);
	}

	/**
	 * Clean the specified project variant.
	 */
	private void clean(int testId, IProject project, String variant, int expectedCount) throws CoreException {
		project.build(project.getBuildConfig(variant), IncrementalProjectBuilder.CLEAN_BUILD, getMonitor());
		ConfigurationBuilder builder = ConfigurationBuilder.getBuilder(project.getBuildConfig(variant));
		assertNotNull(testId + ".0", builder);
		assertEquals(testId + ".1", expectedCount, builder.buildCount);
		assertEquals(testId + ".2", IncrementalProjectBuilder.CLEAN_BUILD, builder.triggerForLastBuild);
	}

	/**
	 * Check the behaviour of a build
	 */
	private void checkBuild(int testId, IProject project, String variant, boolean shouldBuild, int expectedCount, int expectedTrigger) throws CoreException {
		try {
			project.getBuildConfig(variant);
		} catch (CoreException e) {
			fail(testId + ".0");
		}
		ConfigurationBuilder builder = ConfigurationBuilder.getBuilder(project.getBuildConfig(variant));
		if (builder == null) {
			assertFalse(testId + ".1", shouldBuild);
			assertEquals(testId + ".2", 0, expectedCount);
		} else {
			assertEquals(testId + ".3", expectedCount, builder.buildCount);
			if (shouldBuild) {
				assertEquals(testId + ".4", expectedTrigger, builder.triggerForLastBuild);
			}
		}
	}
}
