1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 17:35:35 +02:00

[259964] - race conditions with model creation - applying patch

This commit is contained in:
Alena Laskavaia 2009-01-08 18:06:56 +00:00
parent 7982f97b6c
commit 31376779f5
3 changed files with 175 additions and 68 deletions

View file

@ -33,6 +33,7 @@ import org.eclipse.cdt.managedbuilder.core.tests.OptionEnablementTests;
import org.eclipse.cdt.managedbuilder.core.tests.PathConverterTest;
import org.eclipse.cdt.managedbuilder.core.tests.ResourceBuildCoreTests;
import org.eclipse.cdt.projectmodel.tests.BackwardCompatiblityTests;
import org.eclipse.cdt.projectmodel.tests.CProjectDescriptionSerializationTests;
import org.eclipse.cdt.projectmodel.tests.OptionStringListValueTests;
import org.eclipse.cdt.projectmodel.tests.ProjectModelTests;
@ -73,6 +74,7 @@ public class AllManagedBuildTests {
suite.addTest(ProjectModelTests.suite());
suite.addTest(OptionStringListValueTests.suite());
suite.addTest(BackwardCompatiblityTests.suite());
suite.addTest(CProjectDescriptionSerializationTests.suite());
//$JUnit-END$
return suite;
}

View file

@ -0,0 +1,142 @@
/*******************************************************************************
* Copyright (c) 2005, 2007 Intel 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:
* Intel Corporation - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.projectmodel.tests;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IProjectType;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.Configuration;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.internal.core.ManagedProject;
import org.eclipse.cdt.managedbuilder.testplugin.BuildSystemTestHelper;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
/**
* Creates a project in a loop and checks that it is created with appropriate number
* of build configurations
*
*/
public class CProjectDescriptionSerializationTests extends TestCase {
/**
* @return Test
*/
public static Test suite() {
return new TestSuite(CProjectDescriptionSerializationTests.class);
}
@Override
protected void setUp() throws Exception {
}
@Override
protected void tearDown() throws Exception {
}
/**
* This test is intended to test serialization of C++ project
* @throws Exception
*/
public void testTooManyConfigurations() throws Exception {
String projectName = "testTooManyConfigurations";
String pluginProjectTypeId = "cdt.managedbuild.target.gnu.cygwin.exe";
CoreModel coreModel = CoreModel.getDefault();
{
// Create model project and accompanied descriptions
IProject project = BuildSystemTestHelper.createProject(projectName);
ICProjectDescription des = coreModel.createProjectDescription(project, false);
Assert.assertNotNull("createDescription returned null!", des);
{
ManagedBuildInfo info = ManagedBuildManager.createBuildInfo(project);
IProjectType type = ManagedBuildManager.getProjectType(pluginProjectTypeId);
Assert.assertNotNull("project type not found", type);
ManagedProject mProj = new ManagedProject(project, type);
info.setManagedProject(mProj);
IConfiguration cfgs[] = type.getConfigurations();
Assert.assertNotNull("configurations not found", cfgs);
Assert.assertTrue("no configurations found in the project type",cfgs.length>0);
for (IConfiguration configuration : cfgs) {
String id = ManagedBuildManager.calculateChildId(configuration.getId(), null);
Configuration config = new Configuration(mProj, (Configuration)configuration, id, false, true, false);
CConfigurationData data = config.getConfigurationData();
Assert.assertNotNull("data is null for created configuration", data);
ICConfigurationDescription cfgDes = des.createConfiguration(ManagedBuildManager.CFG_DATA_PROVIDER_ID, data);
}
Assert.assertEquals(2, des.getConfigurations().length);
}
// Persist the project
coreModel.setProjectDescription(project, des);
project.close(null);
}
{
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IWorkspaceDescription workspaceDesc = workspace.getDescription();
workspaceDesc.setAutoBuilding(false);
workspace.setDescription(workspaceDesc);
// Trying to induce an anomaly
for (int i=0;i<144;i++)
{
// Open project
IProject project = root.getProject(projectName);
project.open(null);
Assert.assertEquals(true, project.isOpen());
// Check project description
ICProjectDescription des = coreModel.getProjectDescription(project);
Assert.assertEquals(2, des.getConfigurations().length);
IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project);
// once in a while managedProject.getConfigurations() can return null
// inside buildInfo.getConfigurationNames() which results in NPE
String[] configurationNames = buildInfo.getConfigurationNames();
// this Assert triggers as well on occasion
Assert.assertNotNull("buildInfo.getConfigurationNames() returned null", configurationNames);
IConfiguration configurations[] = buildInfo.getManagedProject().getConfigurations();
// this condition is not supposed to be true
// since the project is supposed to have exactly 2 configurations
if (configurations.length != 2) {
String message = i + "-th round: Invalid number (not 2) of configurations loaded. ";
for (IConfiguration configuration : configurations) {
message = message + "["+configuration.getName()+"], ";
}
Assert.assertEquals(message, 2, configurations.length);
}
project.close(null);
}
}
}
}

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.managedbuilder.internal.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@ -39,15 +40,12 @@ import org.eclipse.core.runtime.PluginVersionIdentifier;
public class ManagedProject extends BuildObject implements IManagedProject, IBuildPropertiesRestriction, IBuildPropertyChangeListener {
private static final String EMPTY_STRING = new String();
private static final IConfiguration[] emptyConfigs = new IConfiguration[0];
// Parent and children
private IProjectType projectType;
private String projectTypeId;
private IResource owner;
// private List configList; // Configurations of this project type
private Map configMap;
private Map<String, Configuration> configMap = Collections.synchronizedMap(new LinkedHashMap<String, Configuration>());
// Miscellaneous
private boolean isDirty = false;
private boolean isValid = true;
@ -151,8 +149,7 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
}
if(vars != null){
for(Iterator iter = getConfigurationMap().values().iterator(); iter.hasNext(); ){
Configuration cfg = (Configuration)iter.next();
for (Configuration cfg : getConfigurationCollection()) {
((ToolChain)cfg.getToolChain()).addProjectVariables(vars);
}
}
@ -235,14 +232,10 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
serializeProjectInfo(element);
if(saveChildren){
Collection configElements = getConfigurationCollection();
Iterator iter = configElements.iterator();
while (iter.hasNext()) {
Configuration config = (Configuration) iter.next();
for (Configuration cfg : getConfigurationCollection()) {
ICStorageElement configElement = element.createChild(IConfiguration.CONFIGURATION_ELEMENT_NAME);
config.serialize(configElement);
cfg.serialize(configElement);
}
}
// Serialize my children
@ -312,21 +305,16 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
* @see org.eclipse.cdt.core.build.managed.IManagedProject#getConfiguration()
*/
public IConfiguration getConfiguration(String id) {
return (IConfiguration)getConfigurationMap().get(id);
return configMap.get(id);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.core.IManagedProject#getConfigurations()
*/
public IConfiguration[] getConfigurations() {
IConfiguration[] configs = new IConfiguration[getConfigurationCollection().size()];
Iterator iter = getConfigurationCollection().iterator();
int i = 0;
while (iter.hasNext()) {
Configuration config = (Configuration)iter.next();
configs[i++] = (IConfiguration)config;
synchronized (configMap) {
return configMap.values().toArray(new IConfiguration[configMap.size()]);
}
return configs;
}
/* (non-Javadoc)
@ -336,10 +324,10 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
final String removeId = id;
//handle the case of temporary configuration
if(getConfigurationMap().get(id) == null)
if(!configMap.containsKey(id))
return;
getConfigurationMap().remove(removeId);
configMap.remove(removeId);
//
// IWorkspaceRunnable remover = new IWorkspaceRunnable() {
// public void run(IProgressMonitor monitor) throws CoreException {
@ -402,37 +390,21 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
* @param Tool
*/
public void addConfiguration(Configuration configuration) {
if(!configuration.isTemporary()){
// getConfigurationList().add(configuration);
getConfigurationMap().put(configuration.getId(), configuration);
}
if(!configuration.isTemporary())
configMap.put(configuration.getId(), configuration);
}
/* (non-Javadoc)
/** (non-Javadoc)
* Safe accessor for the list of configurations.
*
* @return List containing the configurations
*/
private Collection getConfigurationCollection() {
return getConfigurationMap().values();
// if (configList == null) {
// configList = new ArrayList();
// }
// return configList;
private Collection<Configuration> getConfigurationCollection() {
synchronized (configMap) {
return new ArrayList<Configuration>(configMap.values());
}
}
/* (non-Javadoc)
* Safe accessor for the map of configuration ids to configurations
*
* @return
*/
public Map getConfigurationMap() {
if (configMap == null) {
configMap = new LinkedHashMap();
}
return configMap;
}
/*
* M O D E L A T T R I B U T E A C C E S S O R S
*/
@ -469,11 +441,8 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
}
// call resolve references on any children
Iterator configIter = getConfigurationCollection().iterator();
while (configIter.hasNext()) {
Configuration current = (Configuration)configIter.next();
current.resolveReferences();
}
for (Configuration cfg : getConfigurationCollection())
cfg.resolveReferences();
}
return true;
}
@ -495,11 +464,9 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
// Otherwise see if any configurations need saving
Iterator iter = getConfigurationCollection().iterator();
while (iter.hasNext()) {
Configuration current = (Configuration) iter.next();
if (current.isDirty()) return true;
}
for (IConfiguration cfg : getConfigurationCollection())
if (cfg.isDirty())
return true;
return isDirty;
}
@ -510,13 +477,9 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
public void setDirty(boolean isDirty) {
this.isDirty = isDirty;
// Propagate "false" to the children
if (!isDirty) {
Iterator iter = getConfigurationCollection().iterator();
while (iter.hasNext()) {
Configuration current = (Configuration) iter.next();
current.setDirty(false);
}
}
if (!isDirty)
for (IConfiguration cfg : getConfigurationCollection())
cfg.setDirty(false);
}
/* (non-Javadoc)
@ -651,30 +614,30 @@ public class ManagedProject extends BuildObject implements IManagedProject, IBui
}
public String[] getRequiredTypeIds() {
List result = new ArrayList();
List<String> result = new ArrayList<String>();
IConfiguration cfgs[] = getConfigurations();
for(int i = 0; i < cfgs.length; i++){
result.addAll(Arrays.asList(((Configuration)cfgs[i]).getRequiredTypeIds()));
}
return (String[])result.toArray(new String[result.size()]);
return result.toArray(new String[result.size()]);
}
public String[] getSupportedTypeIds() {
List result = new ArrayList();
List<String> result = new ArrayList<String>();
IConfiguration cfgs[] = getConfigurations();
for(int i = 0; i < cfgs.length; i++){
result.addAll(Arrays.asList(((Configuration)cfgs[i]).getSupportedTypeIds()));
}
return (String[])result.toArray(new String[result.size()]);
return result.toArray(new String[result.size()]);
}
public String[] getSupportedValueIds(String typeId) {
List result = new ArrayList();
List<String> result = new ArrayList<String>();
IConfiguration cfgs[] = getConfigurations();
for(int i = 0; i < cfgs.length; i++){
result.addAll(Arrays.asList(((Configuration)cfgs[i]).getSupportedValueIds(typeId)));
}
return (String[])result.toArray(new String[result.size()]);
return result.toArray(new String[result.size()]);
}
public boolean requiresType(String typeId) {