/******************************************************************************* * Copyright (c) 2010, 2013 Andrew Gvozdev 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: * Andrew Gvozdev - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.managedbuilder.language.settings.providers.tests; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.ICommandLauncher; import org.eclipse.cdt.core.envvar.EnvironmentVariable; import org.eclipse.cdt.core.envvar.IContributedEnvironment; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvidersKeeper; import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.settings.model.CIncludeFileEntry; import org.eclipse.cdt.core.settings.model.CIncludePathEntry; import org.eclipse.cdt.core.settings.model.CLibraryFileEntry; import org.eclipse.cdt.core.settings.model.CLibraryPathEntry; import org.eclipse.cdt.core.settings.model.CMacroEntry; import org.eclipse.cdt.core.settings.model.CMacroFileEntry; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager; import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.testplugin.ResourceHelper; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.internal.core.XmlUtil; import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager; import org.eclipse.cdt.internal.core.envvar.UserDefinedEnvironmentSupplier; import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager; import org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector; import org.eclipse.cdt.utils.envvar.StorableEnvironment; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.jobs.Job; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Test cases to test built-in specs detectors. */ public class BuiltinSpecsDetectorTest extends BaseTestCase { private static final String PROVIDER_ID = "provider.id"; private static final String PROVIDER_NAME = "provider name"; private static final String LANGUAGE_ID = "language.test.id"; private static final String CUSTOM_COMMAND_1 = "echo 1"; private static final String CUSTOM_COMMAND_2 = "echo 2"; private static final String ELEM_TEST = "test"; private static final String ENV_SAMPLE = "SAMPLE"; private static final String ENV_SAMPLE_VALUE_1 = "Sample Value 1"; private static final String ENV_SAMPLE_VALUE_2 = "Sample Value 2"; // those attributes must match that in AbstractBuiltinSpecsDetector private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$ private static final String ATTR_CONSOLE = "console"; //$NON-NLS-1$ /** * Dummy to keep boilerplate code. */ private class DummyBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector { @Override protected List<String> parseOptions(String line) { return null; } @Override protected AbstractOptionParser[] getOptionParsers() { return null; } @Override protected String getCompilerCommand(String languageId) { return null; } } /** * Mock built-in specs detector to test basic functionality of {@link AbstractBuiltinSpecsDetector}. */ private class MockBuiltinSpecsDetector extends DummyBuiltinSpecsDetector { @Override protected void startupForLanguage(String languageId) throws CoreException { super.startupForLanguage(languageId); } @Override protected void shutdownForLanguage() { super.shutdownForLanguage(); } } /** * Mock built-in specs detector to test execute() functionality. */ private class MockBuiltinSpecsDetectorExecutedFlag extends DummyBuiltinSpecsDetector { @Override protected void execute() { super.execute(); waitForProviderToFinish(); } protected boolean isExecuted() { return isExecuted; } } /** * Mock built-in specs detector which track how many times it was run. */ private class MockBuiltinSpecsDetectorWithRunCount extends DummyBuiltinSpecsDetector { private int executedCount = 0; @Override public void startup(ICConfigurationDescription cfgDescription, IWorkingDirectoryTracker cwdTracker) throws CoreException { executedCount++; super.startup(cfgDescription, cwdTracker); } @Override public MockBuiltinSpecsDetectorEnvironmentChangeListener cloneShallow() throws CloneNotSupportedException { MockBuiltinSpecsDetectorEnvironmentChangeListener clone = (MockBuiltinSpecsDetectorEnvironmentChangeListener) super.cloneShallow(); return clone; } @Override public MockBuiltinSpecsDetectorEnvironmentChangeListener clone() throws CloneNotSupportedException { MockBuiltinSpecsDetectorEnvironmentChangeListener clone = (MockBuiltinSpecsDetectorEnvironmentChangeListener) super.clone(); return clone; } public int getExecutedCount() { return executedCount; } } /** * Mock built-in specs detector to test environment change functionality. */ private class MockBuiltinSpecsDetectorEnvironmentChangeListener extends DummyBuiltinSpecsDetector { private String sampleEnvVarValue = null; @Override protected boolean validateEnvironment() { return false; } @Override protected void execute() { super.execute(); sampleEnvVarValue = environmentMap.get(ENV_SAMPLE); } @Override public MockBuiltinSpecsDetectorEnvironmentChangeListener cloneShallow() throws CloneNotSupportedException { MockBuiltinSpecsDetectorEnvironmentChangeListener clone = (MockBuiltinSpecsDetectorEnvironmentChangeListener) super.cloneShallow(); clone.sampleEnvVarValue = sampleEnvVarValue; return clone; } @Override public MockBuiltinSpecsDetectorEnvironmentChangeListener clone() throws CloneNotSupportedException { MockBuiltinSpecsDetectorEnvironmentChangeListener clone = (MockBuiltinSpecsDetectorEnvironmentChangeListener) super.clone(); clone.sampleEnvVarValue = sampleEnvVarValue; return clone; } protected boolean isExecuted() { return isExecuted; } public String getSampleEnvVar() { return sampleEnvVarValue; } } /** * Mock built-in specs detector to test parsing functionality. */ private class MockConsoleBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector { @SuppressWarnings("nls") private final AbstractOptionParser[] optionParsers = { new MacroOptionParser("#define (\\S*) *(\\S*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), }; @Override protected int runProgramForLanguage(String languageId, String command, String[] envp, URI workingDirectoryURI, OutputStream consoleOut, OutputStream consoleErr, IProgressMonitor monitor) throws CoreException, IOException { String line = "#define MACRO VALUE"; consoleOut.write((line + '\n').getBytes()); consoleOut.flush(); return ICommandLauncher.OK; } @Override protected IStatus runForEachLanguage(IProgressMonitor monitor) { return super.runForEachLanguage(monitor); } @Override protected List<String> parseOptions(final String line) { return new ArrayList<String>() {{ add(line); }}; } @Override protected AbstractOptionParser[] getOptionParsers() { return optionParsers; } @Override protected String getCompilerCommand(String languageId) { return null; } } @Override protected void setUp() throws Exception { super.setUp(); } @Override protected void tearDown() throws Exception { waitForProviderToFinish(); super.tearDown(); } /** * Waits until all AbstractBuiltinSpecsDetector jobs are finished. */ private void waitForProviderToFinish() { try { Job.getJobManager().join(AbstractBuiltinSpecsDetector.JOB_FAMILY_BUILTIN_SPECS_DETECTOR, null); } catch (Exception e) { // ignore } } /** * Helper method to fetch configuration descriptions. */ private ICConfigurationDescription[] getConfigurationDescriptions(IProject project) { CoreModel coreModel = CoreModel.getDefault(); ICProjectDescriptionManager mngr = coreModel.getProjectDescriptionManager(); // project description ICProjectDescription projectDescription = mngr.getProjectDescription(project, false); assertNotNull(projectDescription); assertEquals(1, projectDescription.getConfigurations().length); // configuration description ICConfigurationDescription[] cfgDescriptions = projectDescription.getConfigurations(); return cfgDescriptions; } /** * Test configure, getters and setters. */ public void testAbstractBuiltinSpecsDetector_GettersSetters() throws Exception { { // provider configured with null parameters MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); provider.configureProvider(PROVIDER_ID, PROVIDER_NAME, null, null, null); assertEquals(PROVIDER_ID, provider.getId()); assertEquals(PROVIDER_NAME, provider.getName()); assertEquals(null, provider.getLanguageScope()); assertEquals(null, provider.getSettingEntries(null, null, null)); assertEquals("", provider.getCommand()); assertEquals(false, provider.isExecuted()); assertEquals(false, provider.isConsoleEnabled()); } { // provider configured with non-null parameters MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); List<String> languages = new ArrayList<String>(); languages.add(LANGUAGE_ID); Map<String, String> properties = new HashMap<String, String>(); properties.put(ATTR_PARAMETER, CUSTOM_COMMAND_1); List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>(); ICLanguageSettingEntry entry = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); entries.add(entry); provider.configureProvider(PROVIDER_ID, PROVIDER_NAME, languages, entries, properties); assertEquals(PROVIDER_ID, provider.getId()); assertEquals(PROVIDER_NAME, provider.getName()); assertEquals(languages, provider.getLanguageScope()); assertEquals(entries, provider.getSettingEntries(null, null, null)); assertEquals(CUSTOM_COMMAND_1, provider.getCommand()); assertEquals(false, provider.isConsoleEnabled()); assertEquals(false, provider.isExecuted()); // setters provider.setCommand(CUSTOM_COMMAND_2); assertEquals(CUSTOM_COMMAND_2, provider.getCommand()); provider.setConsoleEnabled(true); assertEquals(true, provider.isConsoleEnabled()); provider.execute(); assertEquals(true, provider.isExecuted()); assertEquals(null, provider.getSettingEntries(null, null, null)); } } /** * Test clone() and equals(). */ public void testAbstractBuiltinSpecsDetector_CloneAndEquals() throws Exception { // define mock detector class MockDetectorCloneable extends MockBuiltinSpecsDetectorExecutedFlag implements Cloneable { @Override public MockDetectorCloneable clone() throws CloneNotSupportedException { return (MockDetectorCloneable) super.clone(); } @Override public MockDetectorCloneable cloneShallow() throws CloneNotSupportedException { return (MockDetectorCloneable) super.cloneShallow(); } } // create instance to compare to MockDetectorCloneable provider = new MockDetectorCloneable(); List<String> languages = new ArrayList<String>(); languages.add(LANGUAGE_ID); List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>(); ICLanguageSettingEntry entry = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); entries.add(entry); // check clone after initialization MockDetectorCloneable clone0 = provider.clone(); assertTrue(provider.equals(clone0)); // configure provider Map<String, String> properties = new HashMap<String, String>(); properties.put(ATTR_PARAMETER, CUSTOM_COMMAND_1); provider.configureProvider(PROVIDER_ID, PROVIDER_NAME, languages, entries, properties); assertEquals(false, provider.isConsoleEnabled()); provider.setConsoleEnabled(true); provider.execute(); assertEquals(true, provider.isExecuted()); assertFalse(provider.equals(clone0)); // check another clone after configuring { MockDetectorCloneable clone = provider.clone(); assertTrue(provider.equals(clone)); } // check custom parameter { MockDetectorCloneable clone = provider.clone(); clone.setCommand("changed"); assertFalse(provider.equals(clone)); } // check language scope { MockDetectorCloneable clone = provider.clone(); clone.setLanguageScope(null); assertFalse(provider.equals(clone)); } // check console flag { MockDetectorCloneable clone = provider.clone(); boolean isConsoleEnabled = clone.isConsoleEnabled(); clone.setConsoleEnabled( ! isConsoleEnabled ); assertFalse(provider.equals(clone)); } // check isExecuted flag { MockDetectorCloneable clone = provider.clone(); assertEquals(true, clone.isExecuted()); clone.clear(); assertEquals(false, clone.isExecuted()); assertFalse(provider.equals(clone)); } // check entries { MockDetectorCloneable clone = provider.clone(); List<ICLanguageSettingEntry> entries2 = new ArrayList<ICLanguageSettingEntry>(); entries2.add(new CMacroEntry("MACRO2", "VALUE2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY)); clone.setSettingEntries(null, null, null, entries2); assertFalse(provider.equals(clone)); } // check cloneShallow() { MockDetectorCloneable provider2 = provider.clone(); MockDetectorCloneable clone = provider2.cloneShallow(); assertEquals(false, clone.isExecuted()); assertFalse(provider2.equals(clone)); provider2.setSettingEntries(null, null, null, null); assertFalse(provider2.equals(clone)); clone.execute(); assertTrue(provider2.equals(clone)); } } /** * Test basic serialization functionality. */ public void testAbstractBuiltinSpecsDetector_SerializeDOM() throws Exception { { // create empty XML Document doc = XmlUtil.newDocument(); Element rootElement = XmlUtil.appendElement(doc, ELEM_TEST); // initialize provider MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); assertEquals(false, provider.isExecuted()); // load the XML to new provider provider.load(rootElement); assertEquals(false, provider.isConsoleEnabled()); assertEquals(false, provider.isExecuted()); } Element elementProvider; { // define mock detector MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); assertEquals(false, provider.isConsoleEnabled()); assertEquals(false, provider.isExecuted()); // redefine the settings provider.setConsoleEnabled(true); assertEquals(true, provider.isConsoleEnabled()); // serialize in XML Document doc = XmlUtil.newDocument(); Element rootElement = XmlUtil.appendElement(doc, ELEM_TEST); elementProvider = provider.serialize(rootElement); String xmlString = XmlUtil.toString(doc); assertTrue(xmlString.contains(ATTR_CONSOLE)); } { // create another instance of the provider MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); assertEquals(false, provider.isConsoleEnabled()); assertEquals(false, provider.isExecuted()); // load element provider.load(elementProvider); assertEquals(true, provider.isConsoleEnabled()); assertEquals(false, provider.isExecuted()); } } /** * Test serialization of entries and "isExecuted" flag handling. */ public void testAbstractBuiltinSpecsDetector_SerializeEntriesDOM() throws Exception { Element rootElement; { // create provider MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>(); entries.add(new CIncludePathEntry("path0", 1)); provider.setSettingEntries(null, null, null, entries); // serialize entries Document doc = XmlUtil.newDocument(); rootElement = XmlUtil.appendElement(doc, ELEM_TEST); provider.serializeEntries(rootElement); // check XML String xmlString = XmlUtil.toString(doc); assertTrue(xmlString.contains("path0")); } { // create new provider MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); assertEquals(true, provider.isEmpty()); assertEquals(false, provider.isExecuted()); // load the XML to the new provider provider.load(rootElement); List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null); assertNotNull(entries); assertTrue(entries.size() > 0); assertEquals(new CIncludePathEntry("path0", 1), entries.get(0)); assertEquals(false, provider.isEmpty()); assertEquals(true, provider.isExecuted()); // clear the new provider provider.clear(); assertEquals(true, provider.isEmpty()); assertEquals(false, provider.isExecuted()); } { // create new provider MockBuiltinSpecsDetectorExecutedFlag provider = new MockBuiltinSpecsDetectorExecutedFlag(); assertEquals(true, provider.isEmpty()); assertEquals(false, provider.isExecuted()); // execute provider provider.execute(); List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null); assertEquals(null, entries); // executed provider should NOT appear as empty even with no entries set assertEquals(false, provider.isEmpty()); assertEquals(true, provider.isExecuted()); } } /** * Smoke test exercising passing {@code null} to the functions. */ public void testAbstractBuiltinSpecsDetector_Nulls() throws Exception { { // test AbstractBuiltinSpecsDetector.processLine(...) flow MockBuiltinSpecsDetector provider = new MockBuiltinSpecsDetector(); provider.startup(null, null); provider.startupForLanguage(null); provider.processLine(null); provider.shutdownForLanguage(); provider.shutdown(); } { // test AbstractBuiltinSpecsDetector.processLine(...) flow MockConsoleBuiltinSpecsDetector provider = new MockConsoleBuiltinSpecsDetector(); provider.startup(null, null); provider.runForEachLanguage(null); provider.shutdown(); } } /** * Test basic parsing functionality. */ public void testAbstractBuiltinSpecsDetector_RunConfiguration() throws Exception { // Create model project and accompanied descriptions String projectName = getName(); IProject project = ResourceHelper.createCDTProjectWithConfig(projectName); ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project); ICConfigurationDescription cfgDescription = cfgDescriptions[0]; MockConsoleBuiltinSpecsDetector provider = new MockConsoleBuiltinSpecsDetector(); provider.setLanguageScope(new ArrayList<String>() {{add(LANGUAGE_ID);}}); // Run provider provider.startup(cfgDescription, null); provider.runForEachLanguage(null); provider.shutdown(); assertFalse(provider.isEmpty()); List<ICLanguageSettingEntry> noentries = provider.getSettingEntries(null, null, null); assertNull(noentries); // Check parsed entries List<ICLanguageSettingEntry> entries = provider.getSettingEntries(cfgDescription, null, LANGUAGE_ID); ICLanguageSettingEntry expected = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); assertEquals(expected, entries.get(0)); } /** * Smoke test running as global provider on workspace level. */ public void testAbstractBuiltinSpecsDetector_RunGlobal() throws Exception { // Create provider MockConsoleBuiltinSpecsDetector provider = new MockConsoleBuiltinSpecsDetector(); provider.setLanguageScope(new ArrayList<String>() {{add(LANGUAGE_ID);}}); // Run provider provider.startup(null, null); provider.runForEachLanguage(null); provider.shutdown(); assertFalse(provider.isEmpty()); // Check parsed entries List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, LANGUAGE_ID); ICLanguageSettingEntry expected = new CMacroEntry("MACRO", "VALUE", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); assertEquals(expected, entries.get(0)); } /** * Test environment changes for provider registered to configuration. */ public void testAbstractBuiltinSpecsDetector_EnvChangesConfiguration_1() throws Exception { // Create model project and accompanied descriptions String projectName = getName(); IProject project = ResourceHelper.createCDTProjectWithConfig(projectName); ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project); ICConfigurationDescription cfgDescription = cfgDescriptions[0]; // Create provider MockBuiltinSpecsDetectorEnvironmentChangeListener provider = new MockBuiltinSpecsDetectorEnvironmentChangeListener(); // register environment listener on configuration - note that provider is not included in the configuration provider.registerListener(cfgDescription); waitForProviderToFinish(); assertEquals(true, provider.isExecuted()); assertEquals(null, provider.getSampleEnvVar()); // unset "isExecuted" flag provider.clear(); assertEquals(false, provider.isExecuted()); assertEquals(null, provider.getSampleEnvVar()); // Set an environment variable to the configuration { ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true); ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration(); // create and set sample environment variable in the configuration IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager(); IContributedEnvironment contribEnv = envManager.getContributedEnvironment(); // Set an environment variable IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_1); contribEnv.addVariable(var, cfgDescriptionWritable); assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true)); CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); } waitForProviderToFinish(); // check if provider got executed with new value assertEquals(true, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar()); // Repeat one more time with different value of environment variable // unset "isExecuted" flag provider.clear(); assertEquals(false, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar()); // Set an environment variable to the configuration { ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true); ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration(); // create and set sample environment variable in the configuration IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager(); IContributedEnvironment contribEnv = envManager.getContributedEnvironment(); // Set an environment variable IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_2); contribEnv.addVariable(var, cfgDescriptionWritable); assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true)); CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); } waitForProviderToFinish(); // check if provider got executed with new value assertEquals(true, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_2, provider.getSampleEnvVar()); // unregister listeners provider.unregisterListener(); } /** * Test running on environment changes as provider assigned to a configuration. */ public void testAbstractBuiltinSpecsDetector_EnvChangesConfiguration_2() throws Exception { // Create a project with one configuration IProject project = ResourceHelper.createCDTProjectWithConfig(getName()); // Assign a provider to configuration { ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true); ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration(); // Create provider MockBuiltinSpecsDetectorEnvironmentChangeListener provider = new MockBuiltinSpecsDetectorEnvironmentChangeListener(); List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>(); providers.add(provider); ((ILanguageSettingsProvidersKeeper) cfgDescriptionWritable).setLanguageSettingProviders(providers); // Write to project description CProjectDescriptionManager.getInstance().setProjectDescription(project, prjDescriptionWritable); waitForProviderToFinish(); // Check that provider got executed assertEquals(true, provider.isExecuted()); assertEquals(null, provider.getSampleEnvVar()); } // Set environment variable to the configuration { ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true); ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration(); IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager(); IContributedEnvironment contribEnv = envManager.getContributedEnvironment(); // Set an environment variable IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_1); contribEnv.addVariable(var, cfgDescriptionWritable); assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true)); List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescriptionWritable).getLanguageSettingProviders(); MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0); // unset "isExecuted" flag provider.clear(); assertEquals(false, provider.isExecuted()); assertEquals(null, provider.getSampleEnvVar()); // Save project description including saving environment to the configuration CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); } waitForProviderToFinish(); // Check if the provider got executed { // check if environment variable got there ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project, false); ICConfigurationDescription cfgDescription = prjDescription.getActiveConfiguration(); IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager(); IEnvironmentVariable var = envManager.getVariable(ENV_SAMPLE, cfgDescription, true); assertNotNull(var); assertEquals(ENV_SAMPLE_VALUE_1, var.getValue()); // check if provider got executed with new value List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0); assertEquals(true, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar()); } // Repeat one more time with different value of environment variable // Set another environment variable to the configuration { ICProjectDescription prjDescriptionWritable = CoreModel.getDefault().getProjectDescription(project, true); ICConfigurationDescription cfgDescriptionWritable = prjDescriptionWritable.getActiveConfiguration(); IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager(); IContributedEnvironment contribEnv = envManager.getContributedEnvironment(); // Set an environment variable IEnvironmentVariable var = new EnvironmentVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_2); contribEnv.addVariable(var, cfgDescriptionWritable); assertEquals(var, envManager.getVariable(ENV_SAMPLE, cfgDescriptionWritable, true)); List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescriptionWritable).getLanguageSettingProviders(); MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0); // unset "isExecuted" flag provider.clear(); assertEquals(false, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar()); // Save project description including saving environment to the configuration CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); } waitForProviderToFinish(); // Check if the provider got executed { // check if environment variable got there ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project, false); ICConfigurationDescription cfgDescription = prjDescription.getActiveConfiguration(); IEnvironmentVariableManager envManager = CCorePlugin.getDefault().getBuildEnvironmentManager(); IEnvironmentVariable var = envManager.getVariable(ENV_SAMPLE, cfgDescription, true); assertNotNull(var); assertEquals(ENV_SAMPLE_VALUE_2, var.getValue()); // check if provider got executed with new value List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); MockBuiltinSpecsDetectorEnvironmentChangeListener provider = (MockBuiltinSpecsDetectorEnvironmentChangeListener) providers.get(0); assertEquals(true, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_2, provider.getSampleEnvVar()); } } /** * Test running on environment changes as global provider on workspace level. */ public void testAbstractBuiltinSpecsDetector_EnvChangesGlobal() throws Exception { // Create provider MockBuiltinSpecsDetectorEnvironmentChangeListener provider = new MockBuiltinSpecsDetectorEnvironmentChangeListener(); // register environment listener on workspace provider.registerListener(null); waitForProviderToFinish(); assertEquals(true, provider.isExecuted()); assertEquals(null, provider.getSampleEnvVar()); // unset "isExecuted" flag provider.clear(); assertEquals(false, provider.isExecuted()); assertEquals(null, provider.getSampleEnvVar()); // create and set sample environment variable in the workspace UserDefinedEnvironmentSupplier fUserSupplier = EnvironmentVariableManager.fUserSupplier; StorableEnvironment vars = fUserSupplier.getWorkspaceEnvironmentCopy(); vars.createVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_1); fUserSupplier.setWorkspaceEnvironment(vars); waitForProviderToFinish(); // check if provider got executed with new value assertEquals(true, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_1, provider.getSampleEnvVar()); provider.clear(); // create and set sample environment variable in the workspace vars.deleteAll(); vars.createVariable(ENV_SAMPLE, ENV_SAMPLE_VALUE_2); fUserSupplier.setWorkspaceEnvironment(vars); waitForProviderToFinish(); // check if provider got executed with new value assertEquals(true, provider.isExecuted()); assertEquals(ENV_SAMPLE_VALUE_2, provider.getSampleEnvVar()); // unregister listeners provider.unregisterListener(); } /** * Test running a provider on compiler upgrades. */ public void testAbstractBuiltinSpecsDetector_CompilerUpgrade() throws Exception { // Create a folder for this test IPath folder = ResourceHelper.createWorkspaceFolder(getName()); // Create test "compiler" java.io.File compiler = new java.io.File(folder.append("compiler").toOSString()); compiler.createNewFile(); assertTrue(compiler.exists()); String compilerPath = compiler.getAbsolutePath(); // Create provider MockBuiltinSpecsDetectorWithRunCount provider = new MockBuiltinSpecsDetectorWithRunCount(); provider.setCommand('"' + compilerPath + '"' + " arg1"); // register environment listener on workspace provider.registerListener(null); waitForProviderToFinish(); assertEquals(1, provider.getExecutedCount()); // Check that an event doesn't trigger unnecessary rerun provider.handleEvent(null); waitForProviderToFinish(); assertEquals(1, provider.getExecutedCount()); // "Upgrade" the "compiler" long lastModified = compiler.lastModified(); // less than 1 sec might be truncated compiler.setLastModified(lastModified + 1000); long lastModifiedUpdated = compiler.lastModified(); assertTrue(lastModifiedUpdated != lastModified); // Check that an event triggers rerun after upgrade provider.handleEvent(null); waitForProviderToFinish(); assertEquals(2, provider.getExecutedCount()); // unregister listeners provider.unregisterListener(); } /** * Test running a provider on compiler upgrades when the compiler is a symbolic link. */ public void testAbstractBuiltinSpecsDetector_CompilerUpgrade_SymbolicLink() throws Exception { // do not test on systems where symbolic links are not supported if (!ResourceHelper.isSymbolicLinkSupported()) { return; } // Create a folder for this test IPath folder = ResourceHelper.createWorkspaceFolder(getName()); // Create test "compiler" IPath compilerLocation = folder.append("compiler"); java.io.File compiler = new java.io.File(compilerLocation.toOSString()); compiler.createNewFile(); assertTrue(compiler.exists()); // Create symbolic link to the test compiler IPath compilerLinkLocation = folder.append("compilerLink"); ResourceHelper.createSymbolicLink(compilerLinkLocation, compilerLocation); java.io.File compilerLink = new java.io.File(compilerLinkLocation.toOSString()); assertTrue(compilerLink.exists()); String compilerLinkPath = compilerLink.getAbsolutePath(); // Create provider MockBuiltinSpecsDetectorWithRunCount provider = new MockBuiltinSpecsDetectorWithRunCount(); provider.setCommand('"' + compilerLinkPath + '"' + " arg1"); // register environment listener on workspace provider.registerListener(null); waitForProviderToFinish(); assertEquals(1, provider.getExecutedCount()); // Check that an event doesn't trigger unnecessary rerun provider.handleEvent(null); waitForProviderToFinish(); assertEquals(1, provider.getExecutedCount()); // "Upgrade" the "compiler". Note that less than 1 sec might be truncated. long lastModified = compiler.lastModified(); // less than 1 sec might be truncated compiler.setLastModified(lastModified + 1000); long lastModifiedUpdated = compiler.lastModified(); assertTrue(lastModifiedUpdated != lastModified); // Check that an event triggers rerun after upgrade provider.handleEvent(null); waitForProviderToFinish(); assertEquals(2, provider.getExecutedCount()); // unregister listeners provider.unregisterListener(); } /** * Test running a provider after changing the compiler command. */ public void testAbstractBuiltinSpecsDetector_RerunOnCommandArgsChange() throws Exception { // Create provider MockBuiltinSpecsDetectorWithRunCount provider = new MockBuiltinSpecsDetectorWithRunCount(); provider.setCommand("compiler arg1"); // register environment listener on workspace provider.registerListener(null); waitForProviderToFinish(); assertEquals(1, provider.getExecutedCount()); // Check that an event doesn't trigger unnecessary rerun provider.handleEvent(null); waitForProviderToFinish(); assertEquals(1, provider.getExecutedCount()); // Change the compiler command argument provider.setCommand("compiler arg2"); // Check that an event triggers rerun after changing the compiler command provider.handleEvent(null); waitForProviderToFinish(); assertEquals(2, provider.getExecutedCount()); // unregister listeners provider.unregisterListener(); } /** * Check that entries get grouped by kinds by stock built-in specs detector. */ public void testAbstractBuiltinSpecsDetector_GroupSettings() throws Exception { // define benchmarks final CIncludePathEntry includePath_1 = new CIncludePathEntry("/include/path_1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CIncludePathEntry includePath_2 = new CIncludePathEntry("/include/path_2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CIncludeFileEntry includeFile_1 = new CIncludeFileEntry(new Path("/include.file1"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CIncludeFileEntry includeFile_2 = new CIncludeFileEntry(new Path("/include.file2"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CMacroEntry macro_1 = new CMacroEntry("MACRO_1", "", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CMacroEntry macro_2 = new CMacroEntry("MACRO_2", "", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY |ICSettingEntry.UNDEFINED); final CMacroFileEntry macroFile_1 = new CMacroFileEntry(new Path("/macro.file1"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CMacroFileEntry macroFile_2 = new CMacroFileEntry(new Path("/macro.file2"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CLibraryPathEntry libraryPath_1 = new CLibraryPathEntry(new Path("/lib/path_1"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CLibraryPathEntry libraryPath_2 = new CLibraryPathEntry(new Path("/lib/path_2"), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CLibraryFileEntry libraryFile_1 = new CLibraryFileEntry("lib_1.a", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); final CLibraryFileEntry libraryFile_2 = new CLibraryFileEntry("lib_2.a", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY); // Define mock detector adding unorganized entries MockBuiltinSpecsDetector provider = new MockBuiltinSpecsDetector() { @Override public boolean processLine(String line) { detectedSettingEntries.add(libraryFile_1); detectedSettingEntries.add(libraryPath_1); detectedSettingEntries.add(macroFile_1); detectedSettingEntries.add(macro_1); detectedSettingEntries.add(includeFile_1); detectedSettingEntries.add(includePath_1); detectedSettingEntries.add(includePath_2); detectedSettingEntries.add(includeFile_2); detectedSettingEntries.add(macro_2); detectedSettingEntries.add(macroFile_2); detectedSettingEntries.add(libraryPath_2); detectedSettingEntries.add(libraryFile_2); return true; } }; // run specs detector provider.startup(null, null); provider.startupForLanguage(null); provider.processLine(""); provider.shutdownForLanguage(); provider.shutdown(); // compare benchmarks, expected well-sorted List<ICLanguageSettingEntry> entries = provider.getSettingEntries(null, null, null); int i = 0; assertEquals(includePath_1, entries.get(i++)); assertEquals(includePath_2, entries.get(i++)); assertEquals(includeFile_1, entries.get(i++)); assertEquals(includeFile_2, entries.get(i++)); assertEquals(macro_1, entries.get(i++)); assertEquals(macro_2, entries.get(i++)); assertEquals(macroFile_1, entries.get(i++)); assertEquals(macroFile_2, entries.get(i++)); assertEquals(libraryPath_1, entries.get(i++)); assertEquals(libraryPath_2, entries.get(i++)); assertEquals(libraryFile_1, entries.get(i++)); assertEquals(libraryFile_2, entries.get(i++)); assertEquals(12, entries.size()); } }