/******************************************************************************* * Copyright (c) 2011, 2012 QNX Software Systems 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: * QNX Software Systems - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.core.tests; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.managedbuilder.core.IBuilder; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo; import org.eclipse.cdt.managedbuilder.core.IToolChain; import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; import org.eclipse.cdt.managedbuilder.internal.core.FolderInfo; import org.eclipse.cdt.managedbuilder.tcmodification.IConfigurationModification; import org.eclipse.cdt.managedbuilder.tcmodification.IToolChainModificationManager; import org.eclipse.cdt.managedbuilder.testplugin.AbstractBuilderTest; import org.eclipse.cdt.managedbuilder.testplugin.ManagedBuildTestHelper; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceDescription; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; public class ManagedBuildDependencyLibsTests extends AbstractBuilderTest { private static final String PROJ_PATH = "depLibsProjects"; private static final String MESSAGE_TAIL = " (see .log file for more details)."; private IProject fTapp, fTlib, fTobjs; private IToolChain[] allToolChains; public ManagedBuildDependencyLibsTests(String name) { super(name); } public static Test suite() { TestSuite suite = new TestSuite(ManagedBuildDependencyLibsTests.class.getName()); suite.addTest(new ManagedBuildDependencyLibsTests("testDepLibs")); suite.addTest(new ManagedBuildDependencyLibsTests("testDepUObjs")); suite.addTest(new ManagedBuildDependencyLibsTests("testGetArtifactTimeStampEscapeURI_bug377295")); return suite; } private void buildProject(IProject curProject) { try { IProject[] referencedProjects = curProject.getReferencedProjects(); for(int i = 0; i < referencedProjects.length; ++i) buildProject(referencedProjects[i]); // Build the project in order to generate the makefiles curProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD,new NullProgressMonitor()); } catch(CoreException e){ fail(e.getStatus().getMessage()); } catch(OperationCanceledException e){ fail("the project \"" + curProject.getName() + "\" build was cancelled, exception message: " + e.getMessage()); } } @Override protected void setUp() throws Exception { super.setUp(); allToolChains = ManagedBuildManager. getRealToolChains(); IWorkspaceDescription wsDescription = ResourcesPlugin.getWorkspace().getDescription(); wsDescription.setAutoBuilding(false); ResourcesPlugin.getWorkspace().setDescription(wsDescription); assertNotNull("Cannot create tapp project", fTapp = ManagedBuildTestHelper.loadProject("tapp", PROJ_PATH)); assertNotNull("Cannot create tlib project", fTlib = ManagedBuildTestHelper.loadProject("tlib", PROJ_PATH)); assertNotNull("Cannot create tobjs project", fTobjs = ManagedBuildTestHelper.loadProject("tobjs", PROJ_PATH)); IProjectDescription projDescription = fTapp.getDescription(); projDescription.setReferencedProjects(new IProject[] {fTlib, fTobjs}); fTapp.setDescription(projDescription, new NullProgressMonitor()); IToolChain toolChain = setToolChain(fTapp, null); assertNotNull("No compatible tool chain.", toolChain); setToolChain(fTlib, toolChain); setToolChain(fTobjs, toolChain); } @Override protected void tearDown() throws Exception { super.tearDown(); ManagedBuildTestHelper.removeProject(fTapp.getName()); ManagedBuildTestHelper.removeProject(fTlib.getName()); ManagedBuildTestHelper.removeProject(fTobjs.getName()); } private void findFiles(IResource dir, String pattern, List<IFile> files) { IResource resource = null; try { IResource[] members; if(dir instanceof IContainer) members = ((IContainer)dir).members(IFolder.INCLUDE_PHANTOMS); else if(dir instanceof IFolder) members = ((IFolder)dir).members(IFolder.INCLUDE_PHANTOMS); else // Not possible return; for(int i = 0; i < members.length; ++i) { resource = members[i]; if(resource.getType() == IResource.FOLDER) findFiles(resource, pattern, files); else { if(resource.getName().matches(pattern)) files.add((IFile)resource); } } } catch (CoreException e) { e.printStackTrace(); fail("Error while collecting files." + MESSAGE_TAIL); } } private IToolChain setToolChain(IProject project, IToolChain setTo) { try { IConfiguration cfg = getProjectConfiguration(project); IToolChain currentToolChain = cfg.getToolChain(); IToolChainModificationManager mngr = ManagedBuildManager.getToolChainModificationManager(); IConfigurationModification cfgM = (IConfigurationModification)mngr. createModification(cfg.getRootFolderInfo()); FolderInfo folderInfo = (FolderInfo)cfg.getRootFolderInfo(); if(setTo == null) { for(int i = 0; i < allToolChains.length; ++i) { // If predefined tool chain supported, leave it alone if(allToolChains[i].equals(currentToolChain)) return currentToolChain; // In the same loop try to find compatible tool chain if(setTo == null) { IBuilder builder = allToolChains[i].getBuilder(); if(cfg.isBuilderCompatible(builder) && folderInfo.isToolChainCompatible(allToolChains[i])) setTo = allToolChains[i]; } } } if(null != setTo) { cfgM.setToolChain(setTo); assertEquals(setTo, cfgM.getToolChain()); assertEquals(setTo.getBuilder(), cfgM.getBuilder()); } } catch (CoreException e) { e.printStackTrace(); fail("Error. " + MESSAGE_TAIL); } return setTo; } private IConfiguration getProjectConfiguration(IProject project) throws CoreException { ICProjectDescription cProjDescription = CoreModel.getDefault(). createProjectDescription(project, true); return ManagedBuildManager. getConfigurationForDescription( cProjDescription.getConfigurations()[0]); } private void rebuildArtefact(IProject project) { // deleteFiles(getProjectFolder(project), // getArtefactFullName(project), // new NullProgressMonitor()); try { project.build(IncrementalProjectBuilder.CLEAN_BUILD, new NullProgressMonitor()); } catch (CoreException e) { e.printStackTrace(); fail("Cannot clean project " + fTapp.getName() + '.' + MESSAGE_TAIL); } buildProject(project); } private long getArtifactTimeStamp(IProject project) { List<IFile> files = new ArrayList<IFile>(); findFiles(project, getArtefactFullName(project), files); if(files.size() == 0) // File not exists return 0; IFile artefact = files.iterator().next(); return artefact.getModificationStamp(); } private String getArtefactFullName(IProject project) { IConfiguration cfg = null; try { cfg = getProjectConfiguration(project); } catch (CoreException e) { e.printStackTrace(); fail("Error. " + MESSAGE_TAIL); } String name = cfg.getArtifactName(); String ext = cfg.getArtifactExtension(); if((null != ext) && (ext.length() > 0)) { name += '.'; name += ext; } return name; } public void testDepLibs() { buildProject(fTapp); long timeStamp = getArtifactTimeStamp(fTapp); if(timeStamp == 0) { fail("Cannot build project " + fTapp.getName()); } try { // To be sure that in case of build the time should be changed Thread.sleep(1000); } catch (InterruptedException e) { // Do nothing } // Check if no build any more buildProject(fTapp); if(timeStamp != getArtifactTimeStamp(fTapp)) { fail("Error. This time it should be nothing to build"); } rebuildArtefact(fTlib); buildProject(fTapp); if(timeStamp == getArtifactTimeStamp(fTapp)) { fail("Error. This time it should build application."); } } public void testDepUObjs() { buildProject(fTapp); long timeStamp = getArtifactTimeStamp(fTapp); if(timeStamp == 0) { fail("Cannot build project " + fTapp.getName()); } try { // To be sure that in case of build the time should be changed Thread.sleep(1000); } catch (InterruptedException e) { // Do nothing } // Check if no build any more buildProject(fTapp); if(timeStamp != getArtifactTimeStamp(fTapp)) { fail("Error. This time it should be nothing to build"); } // deleteFiles(getProjectFolder(fTobjs), "*.o", new NullProgressMonitor()); rebuildArtefact(fTobjs); buildProject(fTapp); if(timeStamp == getArtifactTimeStamp(fTapp)) { fail("Error. This time it should build application."); } } // Tests that the URI used to get the time stamp of the artifact is escaped correctly // See AdditionalInput.getArtifactTimeStamp(IToolChain toolChain) public void testGetArtifactTimeStampEscapeURI_bug377295() throws CoreException { setWorkspace("regressions"); final IProject project = loadProject("helloworldC"); IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project); IConfiguration[] configs = buildInfo.getManagedProject().getConfigurations(); for (IConfiguration configuration : configs) { configuration.setArtifactName("test [377295]"); } project.build(IncrementalProjectBuilder.FULL_BUILD, null); // This will trigger AdditionalInput.getArtifactTimeStamp to get called, no IllegalArgumentException should be thrown project.build(IncrementalProjectBuilder.FULL_BUILD, null); } }