/******************************************************************************* * Copyright (c) 2004, 2015 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 - Initial API and implementation ******************************************************************************/ 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; /** * These tests exercise the function added in Eclipse 3.1 to allow a builder * to specify what build triggers it responds to. Related API includes: * ICommand#isConfigurable() * ICommand.isBuilding(int) * ICommand.setBuilding(int, boolean) * The "isConfigurable" attribute in the builder extension schema */ public class CustomBuildTriggerTest extends AbstractBuilderTest { public static Test suite() { return new TestSuite(CustomBuildTriggerTest.class); } public CustomBuildTriggerTest(String name) { super(name); } @Override protected void setUp() throws Exception { super.setUp(); SortBuilder.resetSingleton(); CustomTriggerBuilder.resetSingleton(); } /** * Tests that a builder that responds only to the "full" trigger will be called * on the first build after a clean. * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=182781. */ public void testBuildAfterClean_builderRespondingToFull() throws CoreException { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; // Turn auto-building off setAutoBuilding(false); // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; setAutoBuilding(true); //do an initial workspace build to get the builder instance workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); assertNotNull("1.0", builder); assertTrue("1.1", builder.triggerForLastBuild == 0); //do a clean - builder should not be called waitForBuild(); builder.reset(); workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); assertEquals("2.0", 0, builder.triggerForLastBuild); // Ensure that Auto-build doesn't cause a FULL_BUILD waitForBuild(); assertEquals("2.1", 0, builder.triggerForLastBuild); // But first requested build should cause a FULL_BUILD builder.reset(); workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); assertTrue("3.0", builder.wasFullBuild()); // But subsequent builds shouldn't builder.reset(); builder.clearBuildTrigger(); workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); assertTrue("3.1", builder.triggerForLastBuild == 0); } /** * Tests that a builder that responds only to the "incremental" trigger will be called * on the first build after a clean. */ public void testBuildAfterClean_builderRespondingToIncremental() throws CoreException { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; // Turn auto-building off setAutoBuilding(false); // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; setAutoBuilding(true); //do an initial workspace build to get the builder instance workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); assertNotNull("1.0", builder); assertEquals("1.1", 0, builder.triggerForLastBuild); //do a clean - builder should not be called waitForBuild(); builder.reset(); workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); assertEquals("2.0", 0, builder.triggerForLastBuild); // Ensure that Auto-build doesn't cause a FULL_BUILD waitForBuild(); assertEquals("2.1", 0, builder.triggerForLastBuild); // But first requested build should cause a FULL_BUILD builder.reset(); workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); assertTrue("3.0", builder.wasFullBuild()); IFile file = project.getFile("a.txt"); try { file.create(getRandomContents(), IResource.NONE, getMonitor()); } catch (CoreException e) { fail("4.0", e); } // But subsequent INCREMENTAL_BUILD builds should cause INCREMENTAL_BUILD builder.reset(); builder.clearBuildTrigger(); workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); assertEquals("5.0", IncrementalProjectBuilder.INCREMENTAL_BUILD, builder.triggerForLastBuild); } /** * Tests that a builder that responds only to the "auto" trigger will be called * on the first build after a clean. */ public void testBuildAfterClean_builderRespondingToAuto() throws CoreException { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; // Turn auto-building off setAutoBuilding(false); // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; setAutoBuilding(true); // do an initial workspace build to get the builder instance workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); assertNotNull("1.0", builder); assertTrue("1.1", builder.triggerForLastBuild == 0); //do a clean - Ensure that Auto-build causes a FULL_BUILD waitForBuild(); builder.reset(); workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); waitForBuild(); assertTrue("2.1", builder.wasFullBuild()); // add a file in the project to trigger an auto-build - no FULL_BUILD should be triggered builder.clearBuildTrigger(); builder.reset(); IFile file = project.getFile("b.txt"); try { file.create(getRandomContents(), IResource.NONE, getMonitor()); } catch (CoreException e) { fail("3.00", e); } waitForBuild(); assertTrue("6.0", !builder.wasCleanBuild()); assertTrue("6.1", builder.wasAutobuild()); } /** * Tests that a builder that does not declare itself as configurable * is not configurable. */ public void testConfigurable() { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; try { // Turn auto-building off setAutoBuilding(false); // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); desc.setBuildSpec(new ICommand[] {createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0")}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; } catch (CoreException e) { fail("0.99", e); } assertTrue("1.0", command.isConfigurable()); //ensure that setBuilding has effect assertTrue("1.1", command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD)); command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); assertTrue("1.2", !command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD)); assertTrue("1.3", command.isBuilding(IncrementalProjectBuilder.CLEAN_BUILD)); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); assertTrue("1.4", !command.isBuilding(IncrementalProjectBuilder.CLEAN_BUILD)); assertTrue("1.5", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false); assertTrue("1.6", !command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); assertTrue("1.7", command.isBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD)); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); assertTrue("1.8", !command.isBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD)); try { //set the command back into the project for change to take effect IProjectDescription desc = project.getDescription(); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); } catch (CoreException e1) { fail("1.99", e1); } //ensure the builder is not called try { project.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor()); } catch (CoreException e) { fail("2.99", e); } CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); assertTrue("2.0", builder == null || builder.triggerForLastBuild == 0); try { project.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); } catch (CoreException e) { fail("2.91", e); } builder = CustomTriggerBuilder.getInstance(); assertTrue("2.1", builder == null || builder.triggerForLastBuild == 0); try { project.touch(getMonitor()); project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); } catch (CoreException e) { fail("3.99", e); } builder = CustomTriggerBuilder.getInstance(); assertTrue("3.0", builder == null || builder.triggerForLastBuild == 0); try { setAutoBuilding(true); project.touch(getMonitor()); } catch (CoreException e) { fail("4.99", e); } builder = CustomTriggerBuilder.getInstance(); assertTrue("4.0", builder == null || builder.triggerForLastBuild == 0); //turn the builder back on and make sure it runs command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, true); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true); try { //set the command back into the project for change to take effect setAutoBuilding(false); IProjectDescription desc = project.getDescription(); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); } catch (CoreException e1) { fail("5.99", e1); } //ensure the builder is called try { project.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor()); } catch (CoreException e) { fail("6.99", e); } builder = CustomTriggerBuilder.getInstance(); assertTrue("6.1", builder.wasFullBuild()); try { project.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor()); } catch (CoreException e) { fail("7.99", e); } builder = CustomTriggerBuilder.getInstance(); assertTrue("7.1", builder.wasFullBuild()); try { project.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); } catch (CoreException e) { fail("8.99", e); } assertTrue("8.1", builder.wasCleanBuild()); } /** * Tests that a builder that does not declare itself as configurable * is not configurable. */ public void testNonConfigurable() { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; try { // Turn auto-building off setAutoBuilding(false); // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); desc.setBuildSpec(new ICommand[] {createCommand(desc, "Build0")}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; } catch (CoreException e) { fail("0.99", e); } assertTrue("1.0", !command.isConfigurable()); //ensure that setBuilding has no effect command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); assertTrue("1.1", command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD)); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); assertTrue("1.2", command.isBuilding(IncrementalProjectBuilder.CLEAN_BUILD)); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false); assertTrue("1.3", command.isBuilding(IncrementalProjectBuilder.FULL_BUILD)); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); assertTrue("1.4", command.isBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD)); //set the command back into the project for change to take effect try { IProjectDescription desc = project.getDescription(); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); } catch (CoreException e1) { fail("1.99", e1); } //ensure that builder is still called try { project.build(IncrementalProjectBuilder.FULL_BUILD, getMonitor()); } catch (CoreException e) { fail("2.99", e); } SortBuilder builder = SortBuilder.getInstance(); assertTrue("2.0", builder.wasBuilt()); assertTrue("2.1", builder.wasFullBuild()); assertEquals("2.2", command, builder.getCommand()); try { project.touch(getMonitor()); project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); } catch (CoreException e) { fail("3.99", e); } assertTrue("3.0", builder.wasBuilt()); assertTrue("3.1", builder.wasIncrementalBuild()); } /** * Tests that a builder that skips autobuild still receives the correct resource delta * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=173931 */ public void testSkipAutobuildDelta() { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; CustomTriggerBuilder.resetSingleton(); try { // Turn auto-building off setAutoBuilding(false); // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; //turn autobuild back on setAutoBuilding(true); } catch (CoreException e) { fail("0.99", e); } assertTrue("1.0", command.isConfigurable()); //ensure that setBuilding has effect assertTrue("1.1", !command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD)); //do an initial build to get the builder instance try { project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); } catch (CoreException e) { fail("1.2", e); } waitForBuild(); CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); assertNotNull("1.3", builder); builder.clearBuildTrigger(); //add a file in the project, to trigger an autobuild IFile file = project.getFile("a.txt"); try { file.create(getRandomContents(), IResource.NONE, getMonitor()); } catch (CoreException e) { fail("1.99", e); } //autobuild should not call our builder waitForBuild(); assertTrue("2.0", !builder.wasIncrementalBuild()); assertTrue("2.1", !builder.wasAutobuild()); //but, a subsequent incremental build should call it try { project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); } catch (CoreException e) { fail("2.99", e); } assertTrue("2.1", !builder.wasAutobuild()); assertTrue("3.0", builder.wasIncrementalBuild()); } /** * Tests that a builder that responds only to the "full" trigger will be called * on the first and only first build after a clean. * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=206540. */ public void testCleanBuild_AfterCleanBuilder() throws CoreException { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; // turn auto-building off setAutoBuilding(false); // do an initial build to get the builder instance try { project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); } catch (CoreException e) { fail("1.0", e); } waitForBuild(); CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); assertNotNull("2.0", builder); assertTrue("2.1", builder.wasFullBuild()); // do a clean - builder should not be called builder.clearBuildTrigger(); builder.reset(); workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); assertTrue("3.0", !builder.wasCleanBuild()); assertTrue("3.1", !builder.wasFullBuild()); // do an incremental build - FULL_BUILD should be triggered builder.clearBuildTrigger(); builder.reset(); workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); waitForBuild(); assertTrue("4.0", !builder.wasCleanBuild()); assertTrue("4.1", builder.wasFullBuild()); // add a file in the project before an incremental build is triggered again IFile file = project.getFile("a.txt"); try { file.create(getRandomContents(), IResource.NONE, getMonitor()); } catch (CoreException e) { fail("5.00", e); } // do an incremental build - build should NOT be triggered builder.clearBuildTrigger(); builder.reset(); workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); waitForBuild(); assertTrue("6.0", !builder.wasCleanBuild()); assertTrue("6.1", !builder.wasFullBuild()); } /** * Tests that a builder that responds only to the "full" trigger will be called * on the first and only first (non-auto) build after a clean. * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=206540. */ public void testCleanAutoBuild_AfterCleanBuilder() throws CoreException { IWorkspace workspace = getWorkspace(); IProject project = workspace.getRoot().getProject("PROJECT" + 1); ICommand command = null; // Create some resources project.create(getMonitor()); project.open(getMonitor()); // Create and set a build specs for project IProjectDescription desc = project.getDescription(); command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true); command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); desc.setBuildSpec(new ICommand[] {command}); project.setDescription(desc, getMonitor()); command = project.getDescription().getBuildSpec()[0]; // turn auto-building on setAutoBuilding(true); waitForBuild(); CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); assertNotNull("1.0", builder); assertEquals("1.1", 0, builder.triggerForLastBuild); // do a clean - builder should not be called builder.clearBuildTrigger(); builder.reset(); workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); assertTrue("2.0", !builder.wasCleanBuild()); assertTrue("2.1", !builder.wasFullBuild()); // add a file in the project to trigger an auto-build - no FULL_BUILD should be triggered builder.clearBuildTrigger(); builder.reset(); IFile file = project.getFile("a.txt"); try { file.create(getRandomContents(), IResource.NONE, getMonitor()); } catch (CoreException e) { fail("3.00", e); } waitForBuild(); assertEquals("4.0", 0, builder.triggerForLastBuild); // Build the project explicitly -- full build should be triggered project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); waitForBuild(); assertTrue("4.1", builder.wasFullBuild()); // add another file in the project to trigger an auto-build - build should NOT be triggered builder.clearBuildTrigger(); builder.reset(); file = project.getFile("b.txt"); try { file.create(getRandomContents(), IResource.NONE, getMonitor()); } catch (CoreException e) { fail("5.00", e); } waitForBuild(); assertTrue("6.0", !builder.wasCleanBuild()); assertTrue("6.1", !builder.wasFullBuild()); } }