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