| /******************************************************************************* |
| * 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 2.0 which accompanies this distribution, |
| t https://www.eclipse.org/legal/epl-2.0/ |
| t |
| t SPDX-License-Identifier: EPL-2.0 |
| * |
| * 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); |
| } |
| } |
| } |
| } |