blob: add611d7b6779d5119ab5c406e1f95a73da39778 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2012 Broadcom Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* James Blackburn (Broadcom Corp.)
*******************************************************************************/
package org.eclipse.cdt.core.settings.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import junit.framework.TestSuite;
/**
* Class for testing exported settings and project references.
* This functionality is provided by the CfgExportSettingContainerFactory which plugins
* into the CExternalSettingsManager
*/
public class CConfigurationDescriptionExportSettingsTests extends BaseTestCase {
CoreModel coreModel = CoreModel.getDefault();
public static TestSuite suite() {
return suite(CConfigurationDescriptionExportSettingsTests.class, "_");
}
// Setting entries 1
final ICLanguageSettingEntry entries[] = new ICLanguageSettingEntry[] { new CMacroEntry("a", "b", 0),
new CMacroEntry("c", "d", 0), new CIncludePathEntry("a/b/c", 0), new CIncludePathEntry("d/e/f", 0), };
// Setting entries 2
final ICLanguageSettingEntry entries2[] = new ICLanguageSettingEntry[] { new CMacroEntry("a2", "b2", 0),
new CMacroEntry("c2", "d2", 0), new CIncludePathEntry("a/b/c/2", 0), new CIncludePathEntry("d/e/f/2", 0), };
/**
* This tests for simple reference propagation.
* It used to live in the Managedbuild testsuite in ProjectModelTests.java
* but is moved here as it doesn't test any managedbuilder specific functionality
*/
public void testReferences() throws Exception {
final String projectName4 = "test4";
final String projectName5 = "test5";
IProject project4 = ResourceHelper.createCDTProjectWithConfig(projectName4);
IProject project5 = ResourceHelper.createCDTProjectWithConfig(projectName5);
ICProjectDescription des4 = coreModel.getProjectDescription(project4);
ICProjectDescription des5 = coreModel.getProjectDescription(project5);
ICConfigurationDescription dess[] = des5.getConfigurations();
dess[0].createExternalSetting(null, null, null, entries);
dess[0].setActive();
ICExternalSetting extSettings[] = dess[0].getExternalSettings();
assertEquals(extSettings.length, 1);
checkEquivContents(extSettings[0].getEntries(), entries);
List<ICLanguageSettingEntry> list = new ArrayList<>(Arrays.asList(entries));
list.remove(3);
list.remove(2);
checkEquivContents(extSettings[0].getEntries(ICSettingEntry.MACRO), list.toArray());
list = new ArrayList<>(Arrays.asList(entries));
list.remove(0);
list.remove(0);
checkEquivContents(extSettings[0].getEntries(ICSettingEntry.INCLUDE_PATH), list.toArray());
coreModel.setProjectDescription(project5, des5);
extSettings = coreModel.getProjectDescription(project5).getActiveConfiguration().getExternalSettings();
assertEquals(extSettings.length, 1);
checkEquivContents(extSettings[0].getEntries(), entries);
list = new ArrayList<>(Arrays.asList(entries));
list.remove(3);
list.remove(2);
checkEquivContents(extSettings[0].getEntries(ICSettingEntry.MACRO), list.toArray());
list = new ArrayList<>(Arrays.asList(entries));
list.remove(0);
list.remove(0);
checkEquivContents(extSettings[0].getEntries(ICSettingEntry.INCLUDE_PATH), list.toArray());
dess = des4.getConfigurations();
ICLanguageSetting ls = dess[0].getRootFolderDescription().getLanguageSettingForFile("a.c");
ICLanguageSettingEntry macros[] = ls.getSettingEntries(ICSettingEntry.MACRO);
ICLanguageSettingEntry includes[] = ls.getSettingEntries(ICSettingEntry.INCLUDE_PATH);
assertFalse(Arrays.asList(macros).contains(entries[0]));
assertFalse(Arrays.asList(macros).contains(entries[1]));
assertFalse(Arrays.asList(includes).contains(entries[2]));
assertFalse(Arrays.asList(includes).contains(entries[3]));
Map<String, String> map = new HashMap<>();
map.put(projectName5, "");
dess[0].setReferenceInfo(map);
ICLanguageSettingEntry updatedMacros[] = ls.getSettingEntries(ICSettingEntry.MACRO);
ICLanguageSettingEntry udatedIncludes[] = ls.getSettingEntries(ICSettingEntry.INCLUDE_PATH);
assertTrue(Arrays.asList(updatedMacros).contains(entries[0]));
assertTrue(Arrays.asList(updatedMacros).contains(entries[1]));
assertTrue(Arrays.asList(udatedIncludes).contains(entries[2]));
assertTrue(Arrays.asList(udatedIncludes).contains(entries[3]));
}
/**
* This tests importing projects with references works even if the projects are
* imported in opposite order
* @throws Exception
*/
public void testProjectImport() throws Exception {
final IProject libProj = ResourceHelper.createCDTProjectWithConfig("libProj");
final IProject mainProj = ResourceHelper.createCDTProjectWithConfig("mainProj");
// set the settings on the lib config; reference it from the main config
{
ICProjectDescription desLib = coreModel.getProjectDescription(libProj);
ICProjectDescription desMain = coreModel.getProjectDescription(mainProj);
ICConfigurationDescription cfgLib = desLib.getActiveConfiguration();
ICConfigurationDescription cfgMain = desMain.getActiveConfiguration();
cfgLib.createExternalSetting(null, null, null, entries);
coreModel.setProjectDescription(libProj, desLib);
// Main Project references lib project
cfgMain.setReferenceInfo(new HashMap<String, String>() {
{
put(libProj.getName(), "");
}
});
coreModel.setProjectDescription(mainProj, desMain);
// Referenced settings have been picked up
for (ICLanguageSettingEntry e : entries) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
// Now delete the two projects, import main first
// then lib and check we're A-Ok
libProj.delete(false, false, null);
mainProj.delete(false, false, null);
// project description obviously no longer eixsts
assertNull(coreModel.getProjectDescription(mainProj));
assertNull(coreModel.getProjectDescription(libProj));
// Re-import the main project first
mainProj.create(null);
mainProj.open(null);
// Now re-open the lib project
assertFalse(libProj.exists());
libProj.create(null);
libProj.open(null);
// Referenced settings should still exist
ICConfigurationDescription cfgMain = coreModel.getProjectDescription(mainProj, false).getActiveConfiguration();
ICConfigurationDescription cfgLib = coreModel.getProjectDescription(libProj, false).getActiveConfiguration();
checkEquivContents(cfgLib.getExternalSettings()[0].getEntries(), entries);
for (ICLanguageSettingEntry e : entries) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
/**
* Tests that updating the exported settings on the active configuration, without updating the set
* of references, is correctly picked up in referencing projects.
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=312575
*/
public void testUpdateExportedSettingsActiveCfg() throws Exception {
final IProject libProj = ResourceHelper.createCDTProjectWithConfig("libUpdateExtSettings");
final IProject mainProj = ResourceHelper.createCDTProjectWithConfig("mainProjUpdateExtSettings");
{
// set the settings on the lib config; reference it from the main config
ICProjectDescription desLib = coreModel.getProjectDescription(libProj);
ICProjectDescription desMain = coreModel.getProjectDescription(mainProj);
ICConfigurationDescription cfgLib = desLib.getActiveConfiguration();
ICConfigurationDescription cfgMain = desMain.getActiveConfiguration();
cfgLib.createExternalSetting(null, null, null, entries);
coreModel.setProjectDescription(libProj, desLib);
// Main Project references lib project
cfgMain.setReferenceInfo(new HashMap<String, String>() {
{
put(libProj.getName(), "");
}
});
coreModel.setProjectDescription(mainProj, desMain);
// Referenced settings have been picked up
for (ICLanguageSettingEntry e : entries) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
{
// Now apply different language setting entries
ICProjectDescription desLib = coreModel.getProjectDescription(libProj);
ICConfigurationDescription cfgLib = desLib.getActiveConfiguration();
cfgLib.removeExternalSetting(cfgLib.getExternalSettings()[0]);
cfgLib.createExternalSetting(null, null, null, entries2);
coreModel.setProjectDescription(libProj, desLib);
// Check the exported settings is correct
checkEquivContents(entries2, cfgLib.getExternalSettings()[0].getEntries());
// Fetch the configuration a-fresh to pick up the settings
ICConfigurationDescription cfgMain = coreModel.getProjectDescription(mainProj, false)
.getActiveConfiguration();
assertTrue(cfgMain.getReferenceInfo().containsKey(libProj.getName()));
// Referenced settings have changed from entries -> entries2
for (ICLanguageSettingEntry e : entries)
assertTrue(!cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
for (ICLanguageSettingEntry e : entries2)
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
/**
* This is the same as testeUpdateExprtedSettingsActiveCfg except we explicitly name the
* referenced configuration.
* Tests that updating the exported settings on a name configuration, without updating the set
* of references, is correctly picked up in referencing projects
*/
public void testUpdateExportedSettingsNamedConfig() throws Exception {
final IProject libProj = ResourceHelper.createCDTProjectWithConfig("libUpdateExpSettingsNamed");
final IProject mainProj = ResourceHelper.createCDTProjectWithConfig("mainProjUpdateExpSettingsNamed");
{
// set the settings on the lib config; reference it from the main config
ICProjectDescription desLib = coreModel.getProjectDescription(libProj);
ICProjectDescription desMain = coreModel.getProjectDescription(mainProj);
final ICConfigurationDescription cfgLib = desLib.getActiveConfiguration();
ICConfigurationDescription cfgMain = desMain.getActiveConfiguration();
cfgLib.createExternalSetting(null, null, null, entries);
coreModel.setProjectDescription(libProj, desLib);
// Main Project references lib project
cfgMain.setReferenceInfo(new HashMap<String, String>() {
{
put(libProj.getName(), cfgLib.getId());
}
});
coreModel.setProjectDescription(mainProj, desMain);
// Referenced settings have been picked up
for (ICLanguageSettingEntry e : entries) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
{
// Now apply different language setting entries
ICProjectDescription desLib = coreModel.getProjectDescription(libProj);
ICConfigurationDescription cfgLib = desLib.getActiveConfiguration();
cfgLib.removeExternalSetting(cfgLib.getExternalSettings()[0]);
cfgLib.createExternalSetting(null, null, null, entries2);
coreModel.setProjectDescription(libProj, desLib);
// Check the exported settings is correct
checkEquivContents(entries2, cfgLib.getExternalSettings()[0].getEntries());
// Fetch the configuration a-fresh to pick up the settings
ICConfigurationDescription cfgMain = coreModel.getProjectDescription(mainProj, false)
.getActiveConfiguration();
assertTrue(cfgMain.getReferenceInfo().get(libProj.getName()).equals(cfgLib.getId()));
// Referenced settings have changed from entries -> entries2
for (ICLanguageSettingEntry e : entries)
assertTrue(!cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
for (ICLanguageSettingEntry e : entries2)
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
/**
* Bug 312575 tests that updating a .cproject external (e.g. via a repository update)
* causes referencing projects to correctly pick up changes to the project exports.
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=312575
*/
public void testExportedSettingsExternalUpdate() throws Exception {
final IProject libProj = ResourceHelper.createCDTProjectWithConfig("libProj312575");
final IProject mainProj = ResourceHelper.createCDTProjectWithConfig("mainProj312575");
// .cproject file and its backup
IFile libCproject = libProj.getFile(".cproject");
IFile libCproject_back = libProj.getFile(".cproject_back");
// set the settings on the lib config; reference it from the main config
{
ICProjectDescription desLib = coreModel.getProjectDescription(libProj);
ICProjectDescription desMain = coreModel.getProjectDescription(mainProj);
final ICConfigurationDescription cfgLib = desLib.getActiveConfiguration();
ICConfigurationDescription cfgMain = desMain.getActiveConfiguration();
cfgLib.createExternalSetting(null, null, null, entries);
coreModel.setProjectDescription(libProj, desLib);
// Main Project references lib project
cfgMain.setReferenceInfo(new HashMap<String, String>() {
{
put(libProj.getName(), cfgLib.getId());
}
});
coreModel.setProjectDescription(mainProj, desMain);
checkEquivContents(entries, cfgLib.getExternalSettings()[0].getEntries());
// Referenced settings have been picked up
for (ICLanguageSettingEntry e : entries) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
// Backup the .cproject
libCproject_back.create(libCproject.getContents(), false, null);
// Now apply different language setting entries
cfgLib.removeExternalSetting(cfgLib.getExternalSettings()[0]);
cfgLib.createExternalSetting(null, null, null, entries2);
coreModel.setProjectDescription(libProj, desLib);
checkEquivContents(entries2, cfgLib.getExternalSettings()[0].getEntries());
// Referenced settings have been picked up
for (ICLanguageSettingEntry e : entries2) {
assertTrue(coreModel.getProjectDescription(mainProj).getActiveConfiguration().getRootFolderDescription()
.getLanguageSettingForFile("a.c").getSettingEntriesList(e.getKind()).contains(e));
}
}
// Now replace the .cproject with .cproject_back. The exported settings should be picked up in the referenced config
libCproject.setContents(libCproject_back.getContents(), IResource.NONE, null);
// Referenced settings should still exist
ICConfigurationDescription cfgLib = coreModel.getProjectDescription(libProj, false).getActiveConfiguration();
ICConfigurationDescription cfgMain = coreModel.getProjectDescription(mainProj, false).getActiveConfiguration();
checkEquivContents(entries, cfgLib.getExternalSettings()[0].getEntries());
// Referencing project contains entries and not entries2
for (ICLanguageSettingEntry e : entries) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
for (ICLanguageSettingEntry e : entries2) {
assertTrue(!cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
/**
* Two configurations in two projects reference each other.
* Test that the system is happy with this and updates each correctly on
* the other's change.
*/
public void _testExportedSettingsCyclicExternalUpdate() throws Exception {
final IProject libProj = ResourceHelper.createCDTProjectWithConfig("libProjCyclic");
final IProject mainProj = ResourceHelper.createCDTProjectWithConfig("libProjCyclic2");
// .cproject file and its backup
final IFile libCproject = libProj.getFile(".cproject");
final IFile libCproject_back = libProj.getFile(".cproject_back");
final IFile mainCproject = mainProj.getFile(".cproject");
final IFile mainCproject_back = mainProj.getFile(".cproject_back");
// set the settings on the lib config; reference it from the main config & vice versa
{
ICProjectDescription desLib = coreModel.getProjectDescription(libProj);
ICProjectDescription desMain = coreModel.getProjectDescription(mainProj);
final ICConfigurationDescription cfgLib = desLib.getActiveConfiguration();
final ICConfigurationDescription cfgMain = desMain.getActiveConfiguration();
// Lib Exports entries
cfgLib.createExternalSetting(null, null, null, entries);
// Main Exports entries2
cfgMain.createExternalSetting(null, null, null, entries2);
// Main Project references lib project
cfgMain.setReferenceInfo(new HashMap<String, String>() {
{
put(libProj.getName(), cfgLib.getId());
}
});
cfgLib.setReferenceInfo(new HashMap<String, String>() {
{
put(mainProj.getName(), cfgMain.getId());
}
});
coreModel.setProjectDescription(libProj, desLib);
coreModel.setProjectDescription(mainProj, desMain);
checkEquivContents(entries, cfgLib.getExternalSettings()[0].getEntries());
checkEquivContents(entries2, cfgMain.getExternalSettings()[0].getEntries());
// Backup the .cproject
libCproject_back.create(libCproject.getContents(), false, null);
mainCproject_back.create(mainCproject.getContents(), false, null);
// Now apply different language setting entries
cfgLib.removeExternalSetting(cfgLib.getExternalSettings()[0]);
cfgLib.createExternalSetting(null, null, null, entries2);
coreModel.setProjectDescription(libProj, desLib);
cfgMain.removeExternalSetting(cfgMain.getExternalSettings()[0]);
cfgMain.createExternalSetting(null, null, null, entries);
coreModel.setProjectDescription(mainProj, desMain);
checkEquivContents(entries2, cfgLib.getExternalSettings()[0].getEntries());
checkEquivContents(entries, cfgMain.getExternalSettings()[0].getEntries());
}
ICConfigurationDescription cfgLib = coreModel.getProjectDescription(libProj).getActiveConfiguration();
ICConfigurationDescription cfgMain = coreModel.getProjectDescription(mainProj).getActiveConfiguration();
// Tests the exports are now the right way round
for (ICLanguageSettingEntry e : entries) {
assertTrue(!cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
assertTrue(cfgLib.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
for (ICLanguageSettingEntry e : entries2) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
assertTrue(!cfgLib.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
// Now replace the .cproject with .cproject_back. The exported settings should be picked up in the referenced config
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
libCproject.setContents(libCproject_back.getContents(), IResource.NONE, null);
mainCproject.setContents(mainCproject_back.getContents(), IResource.NONE, null);
}
}, null);
// Referenced settings should still exist
cfgLib = coreModel.getProjectDescription(libProj).getActiveConfiguration();
cfgMain = coreModel.getProjectDescription(mainProj).getActiveConfiguration();
checkEquivContents(entries, cfgLib.getExternalSettings()[0].getEntries());
checkEquivContents(entries2, cfgMain.getExternalSettings()[0].getEntries());
// Referencing project contains entries and not entries2
for (ICLanguageSettingEntry e : entries) {
assertTrue(cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
assertTrue(!cfgLib.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
for (ICLanguageSettingEntry e : entries2) {
assertTrue(!cfgMain.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
assertTrue(cfgLib.getRootFolderDescription().getLanguageSettingForFile("a.c")
.getSettingEntriesList(e.getKind()).contains(e));
}
}
private void checkEquivContents(Object[] expected, Object[] actual) {
if (expected == null) {
assertTrue(actual == null);
return;
}
assertTrue(actual != null);
assertEquals(expected.length, actual.length);
Set s1 = new HashSet(Arrays.asList(expected));
Set s2 = new HashSet(Arrays.asList(actual));
assertEquals(expected.length, s1.size());
assertEquals(s1, s2);
}
}