/******************************************************************************* * 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); } } } }