/*******************************************************************************
 *  Copyright (c) 2011, 2015 IBM 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.core.resources.tests;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.resources.ExclusionInstance;
import org.eclipse.cdt.core.resources.ExclusionType;
import org.eclipse.cdt.core.resources.RefreshExclusion;
import org.eclipse.cdt.core.resources.RefreshScopeManager;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.WriteAccessException;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.internal.core.resources.ResourceExclusion;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * @author crecoskie
 *
 */
public class RefreshScopeTests extends TestCase {

	private IProject fProject;
	private IProject fGeneralProject;
	private IFolder fFolder1;
	private IFolder fFolder2;
	private IFolder fFolder3;
	private IFolder fFolder4;
	private IFolder fFolder5;
	private IFolder fFolder6;
	private String config1, config2;

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	@Override
	protected void setUp() throws Exception {

		// create project
		CTestPlugin.getWorkspace().run(new IWorkspaceRunnable() {
			@Override
			public void run(IProgressMonitor monitor) throws CoreException {
				ICProject cProject = CProjectHelper.createNewStyleCProject("testRefreshScope",
						IPDOMManager.ID_NO_INDEXER, false);
				fProject = cProject.getProject();

				IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
				fGeneralProject = root.getProject("testRefreshScopeGeneral");
				assertNotNull(fGeneralProject);

				if (!fGeneralProject.exists()) {
					fGeneralProject.create(null);
				} else {
					fGeneralProject.refreshLocal(IResource.DEPTH_INFINITE, null);
				}

				if (!fGeneralProject.isOpen()) {
					fGeneralProject.open(null);
				}
			}
		}, null);

		IWorkspaceRoot root = CTestPlugin.getWorkspace().getRoot();
		IProject project = root.getProject("testRefreshScope");

		config1 = "Debug";
		config2 = "Release";

		// create some folders
		// structure is:
		/*
		 * testRefreshScope
		 *    folder1
		 *    folder2
		 *    	folder 3
		 *    		folder 4
		 *    		folder 5
		 *    	folder 6
		 *
		 */
		final IFolder folder1 = project.getFolder("folder1");
		fFolder1 = folder1;
		final IFolder folder2 = project.getFolder("folder2");
		fFolder2 = folder2;
		final IFolder folder3 = folder2.getFolder("folder3");
		fFolder3 = folder3;
		final IFolder folder4 = folder3.getFolder("folder4");
		fFolder4 = folder4;
		final IFolder folder5 = folder3.getFolder("folder5");
		fFolder5 = folder5;
		final IFolder folder6 = folder2.getFolder("folder6");
		fFolder6 = folder6;

		CTestPlugin.getWorkspace().run(new IWorkspaceRunnable() {
			@Override
			public void run(IProgressMonitor monitor) throws CoreException {

				folder1.create(true, true, monitor);
				folder2.create(true, true, monitor);
				folder3.create(true, true, monitor);
				folder4.create(true, true, monitor);
				folder5.create(true, true, monitor);
				folder6.create(true, true, monitor);
			}
		}, null);

	}

	/* (non-Javadoc)
	 * @see junit.framework.TestCase#tearDown()
	 */
	@Override
	protected void tearDown() throws Exception {
		fProject.delete(true, true, null);
	}

	public void testAddDeleteResource() throws CoreException {

		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		// TEST 1:
		// add resource "folder1" under config1.
		manager.addResourceToRefresh(fProject, config1, fFolder1);
		// now, check that it was added.
		List<IResource> config1_resources = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(config1_resources.size(), 2);
		assertEquals(config1_resources.contains(fProject), true);
		assertEquals(config1_resources.contains(fFolder1), true);

		// TEST 2:
		// add resource "folder2" under config1
		manager.addResourceToRefresh(fProject, config1, fFolder2);
		// now check to see that it and "folder1" are still there.
		config1_resources = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(config1_resources.size(), 3); // 3 because by default the project is always there.
		assertEquals(config1_resources.contains(fProject), true);
		assertEquals(config1_resources.contains(fFolder1), true);
		assertEquals(config1_resources.contains(fFolder2), true);

		// make sure it wasn't added under "Release", which should be empty now, excpet for the default project resource.
		List<IResource> config2_resources = manager.getResourcesToRefresh(fProject, config2);
		assertEquals(config2_resources.size(), 1);
		assertEquals(config2_resources.contains(fProject), true);

		// and add one under config 2.
		manager.addResourceToRefresh(fProject, config2, fFolder1);
		config2_resources = manager.getResourcesToRefresh(fProject, config2);
		assertEquals(config2_resources.size(), 2);
		assertEquals(config2_resources.contains(fProject), true);
		assertEquals(config2_resources.contains(fFolder1), true);

		// TEST 3:
		// first try deleting a resource that was never added... folder5
		manager.deleteResourceToRefresh(fProject, config1, fFolder5);
		List<IResource> config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(config1_resourcesAfterDelete.size(), 3);
		assertEquals(config1_resources.contains(fProject), true);
		assertEquals(config1_resources.contains(fFolder1), true);
		assertEquals(config1_resources.contains(fFolder2), true);

		// ditto for config2, but this time we did add the resource, to make sure fFolder1 wasn't added.
		manager.deleteResourceToRefresh(fProject, config2, fFolder5);
		List<IResource> config2_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config2);
		assertEquals(config2_resourcesAfterDelete.size(), 2);
		assertEquals(config2_resources.contains(fProject), true);
		assertEquals(config2_resources.contains(fFolder1), true);

		// TEST 4:
		// now delete the resources from the manager one by one
		manager.deleteResourceToRefresh(fProject, config1, config1_resources.get(config1_resources.indexOf(fFolder2)));
		config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(config1_resourcesAfterDelete.size(), 2);
		assertEquals(config1_resourcesAfterDelete.contains(fProject), true);
		assertEquals(config1_resourcesAfterDelete.contains(fFolder1), true);

		manager.deleteResourceToRefresh(fProject, config1, config1_resources.get(config1_resources.indexOf(fFolder1)));
		config1_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(config1_resourcesAfterDelete.size(), 1);
		assertEquals(config1_resourcesAfterDelete.contains(fProject), true);

		// and ditto for config2
		manager.deleteResourceToRefresh(fProject, config2, config2_resources.get(config2_resources.indexOf(fFolder1)));
		config2_resourcesAfterDelete = manager.getResourcesToRefresh(fProject, config2);
		assertEquals(config2_resourcesAfterDelete.size(), 1);
		assertEquals(config2_resourcesAfterDelete.contains(fProject), true);
	}

	public void testSetResourcesToExclusionsMapRefresh() {
		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		HashMap<IResource, List<RefreshExclusion>> config1_resourceMap = new HashMap<>();
		config1_resourceMap.put(fFolder1, new LinkedList<RefreshExclusion>());
		config1_resourceMap.put(fFolder2, new LinkedList<RefreshExclusion>());
		manager.setResourcesToExclusionsMap(fProject, config1, config1_resourceMap);

		List<IResource> config1_resourcesAfterSet = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(config1_resourcesAfterSet.size(), 2);
		assertEquals(config1_resourcesAfterSet.contains(fFolder1), true);
		assertEquals(config1_resourcesAfterSet.contains(fFolder2), true);

		manager.clearResourcesToRefresh(fProject);

	}

	public void testAddRemoveExclusion() {
		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		IResource config1_resource = fProject;

		manager.addResourceToRefresh(fProject, config1, config1_resource);
		RefreshExclusion config1_exclusion1 = new TestExclusion();
		manager.addExclusion(fProject, config1, config1_resource, config1_exclusion1);
		RefreshExclusion config1_exclusion2 = new TestExclusion();
		manager.addExclusion(fProject, config1, config1_resource, config1_exclusion2);

		// make sure the exclusions are there
		List<RefreshExclusion> exclusionsList = manager.getExclusions(fProject, config1, config1_resource);
		RefreshExclusion[] exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]);
		assertEquals(exclusionsArray.length, 2);
		assertEquals(exclusionsArray[0], config1_exclusion1);
		assertEquals(exclusionsArray[1], config1_exclusion2);

		// remove the exclusions one by one
		manager.removeExclusion(fProject, config1, config1_resource, config1_exclusion2);
		exclusionsList = manager.getExclusions(fProject, config1, config1_resource);
		exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]);
		assertEquals(exclusionsArray.length, 1);
		assertEquals(exclusionsArray[0], config1_exclusion1);

		manager.removeExclusion(fProject, config1, config1_resource, config1_exclusion1);
		exclusionsList = manager.getExclusions(fProject, config1, config1_resource);
		exclusionsArray = exclusionsList.toArray(new RefreshExclusion[0]);
		assertEquals(exclusionsArray.length, 0);

	}

	public void testPersistAndLoad() {
		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		IResource config1_resource = fProject;
		IResource config2_resource = fFolder1;

		//add a resource and two exclusions for config1.
		manager.addResourceToRefresh(fProject, config1, config1_resource);
		RefreshExclusion config1_exclusion1 = new TestExclusion();
		manager.addExclusion(fProject, config1, config1_resource, config1_exclusion1);
		RefreshExclusion config1_exclusion2 = new TestExclusion();
		manager.addExclusion(fProject, config1, config1_resource, config1_exclusion2);

		// add a nested exclusion to the first exclusion
		RefreshExclusion config1_exclusion3 = new TestExclusion();
		config1_exclusion1.addNestedExclusion(config1_exclusion3);

		// add an instance to the second exclusion
		ExclusionInstance config1_instance = new ExclusionInstance();
		config1_instance.setDisplayString("foo");
		config1_instance.setResource(fFolder2);
		config1_instance.setExclusionType(ExclusionType.RESOURCE);
		config1_instance.setParentExclusion(config1_exclusion2);
		config1_exclusion2.addExclusionInstance(config1_instance);

		//add a resource and two exclusions for config2.
		manager.addResourceToRefresh(fProject, config2, config2_resource);
		RefreshExclusion config2_exclusion1 = new TestExclusion();
		manager.addExclusion(fProject, config2, config2_resource, config2_exclusion1);
		RefreshExclusion config2_exclusion2 = new TestExclusion();
		manager.addExclusion(fProject, config2, config2_resource, config2_exclusion2);

		// add a nested exclusion to the first exclusion
		RefreshExclusion config2_exclusion3 = new TestExclusion();
		config2_exclusion1.addNestedExclusion(config2_exclusion3);

		// add an instance to the second exclusion
		ExclusionInstance config2_instance = new ExclusionInstance();
		config2_instance.setDisplayString("foo");
		config2_instance.setResource(fFolder2);
		config2_instance.setExclusionType(ExclusionType.RESOURCE);
		config2_instance.setParentExclusion(config2_exclusion2);
		config2_exclusion2.addExclusionInstance(config1_instance);

		ICProjectDescription projectDescription = CCorePlugin.getDefault().getProjectDescription(fProject, true);

		try {
			manager.persistSettings(projectDescription);
			CCorePlugin.getDefault().setProjectDescription(fProject, projectDescription);
		} catch (CoreException e) {
			fail();
		}

		// now clear all the settings out of the manager
		manager.clearAllData();

		// now load the settings
		try {
			manager.loadSettings();
		} catch (CoreException e) {
			fail();
		}

		// make sure we got the same stuff we saved for config1

		// the project should be set to refresh its root
		List<IResource> config1_resources = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(config1_resources.size(), 1);
		assertEquals(config1_resources.toArray(new IResource[0])[0], config1_resource);

		// there should be 2 top-level exclusions
		List<RefreshExclusion> config1_exclusions = manager.getExclusions(fProject, config1, config1_resource);
		assertEquals(2, config1_exclusions.size());
		RefreshExclusion[] config1_exclusionsArray = config1_exclusions.toArray(new RefreshExclusion[0]);

		// both exclusions should have parent resource set to the project
		assertEquals(config1_resource, config1_exclusionsArray[0].getParentResource());
		assertEquals(config1_resource, config1_exclusionsArray[1].getParentResource());

		// the first exclusion should have one nested exclusion
		List<RefreshExclusion> config1_nestedExclusions1 = config1_exclusionsArray[0].getNestedExclusions();
		assertEquals(config1_nestedExclusions1.size(), 1);
		RefreshExclusion[] config1_nestedExclusionsArray = config1_nestedExclusions1.toArray(new RefreshExclusion[0]);
		// the nested exclusion should have its parent exclusion set properly
		assertEquals(config1_nestedExclusionsArray[0].getParentExclusion(), config1_exclusionsArray[0]);

		// the second exclusion should have no nested exclusions
		List<RefreshExclusion> config1_nestedExclusions2 = config1_exclusionsArray[1].getNestedExclusions();
		assertEquals(config1_nestedExclusions2.size(), 0);

		// the second exclusion should have an instance
		List<ExclusionInstance> config1_instances = config1_exclusionsArray[1].getExclusionInstances();
		assertEquals(1, config1_instances.size());
		ExclusionInstance[] config1_instancesArray = config1_instances.toArray(new ExclusionInstance[0]);
		ExclusionInstance config1_loadedInstance = config1_instancesArray[0];

		// check the contents of the instance
		assertEquals("foo", config1_loadedInstance.getDisplayString());
		assertEquals(fFolder2, config1_loadedInstance.getResource());
		assertEquals(ExclusionType.RESOURCE, config1_loadedInstance.getExclusionType());

		// clear data for config1
		manager.deleteResourceToRefresh(fProject, config1, config1_resource);

		// make sure we got the same stuff we saved for config2
		// the project should be set to refresh its root
		List<IResource> config2_resources = manager.getResourcesToRefresh(fProject, config2);
		assertEquals(config2_resources.size(), 2);
		assertEquals(config2_resources.contains(config2_resource), true);

		// there should be 2 top-level exclusions
		List<RefreshExclusion> config2_exclusions = manager.getExclusions(fProject, config2, config2_resource);
		assertEquals(2, config2_exclusions.size());
		RefreshExclusion[] config2_exclusionsArray = config2_exclusions.toArray(new RefreshExclusion[0]);

		// both exclusions should have parent resource set to the project
		assertEquals(config2_resource, config2_exclusionsArray[0].getParentResource());
		assertEquals(config2_resource, config2_exclusionsArray[1].getParentResource());

		// the first exclusion should have one nested exclusion
		List<RefreshExclusion> config2_nestedExclusions1 = config2_exclusionsArray[0].getNestedExclusions();
		assertEquals(config2_nestedExclusions1.size(), 1);
		RefreshExclusion[] config2_nestedExclusionsArray = config2_nestedExclusions1.toArray(new RefreshExclusion[0]);
		// the nested exclusion should have its parent exclusion set properly
		assertEquals(config2_nestedExclusionsArray[0].getParentExclusion(), config2_exclusionsArray[0]);

		// the second exclusion should have no nested exclusions
		List<RefreshExclusion> config2_nestedExclusions2 = config2_exclusionsArray[1].getNestedExclusions();
		assertEquals(config2_nestedExclusions2.size(), 0);

		// the second exclusion should have an instance
		List<ExclusionInstance> config2_instances = config2_exclusionsArray[1].getExclusionInstances();
		assertEquals(1, config2_instances.size());
		ExclusionInstance[] config2_instancesArray = config2_instances.toArray(new ExclusionInstance[0]);
		ExclusionInstance config2_loadedInstance = config2_instancesArray[0];

		// check the contents of the instance
		assertEquals("foo", config2_loadedInstance.getDisplayString());
		assertEquals(fFolder2, config2_loadedInstance.getResource());
		assertEquals(ExclusionType.RESOURCE, config2_loadedInstance.getExclusionType());

		// cleanup
		manager.clearAllData();
	}

	public void testResourceExclusion() {
		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		IResource config1_resource = fProject;

		String conf_name = getCurrentConfigName();

		manager.addResourceToRefresh(fProject, conf_name, config1_resource);

		// create a series of nested exclusions that include/exclude certain folders
		// will be included/excluded as follows
		/*
		 * testRefreshScope - include
		 *    folder1 - exclude
		 *    folder2 - exclude, except,
		 *    	folder 3 - include
		 *    		folder 4 - exclude
		 *    		folder 5 - include
		 *    	folder 6 - exclude
		 *
		 */

		ResourceExclusion exclusion1 = new ResourceExclusion();
		ExclusionInstance instance1 = new ExclusionInstance();
		instance1.setResource(fFolder1);
		exclusion1.addExclusionInstance(instance1);
		ExclusionInstance instance2 = new ExclusionInstance();
		instance2.setResource(fFolder2);
		exclusion1.addExclusionInstance(instance2);
		manager.addExclusion(fProject, conf_name, config1_resource, exclusion1);

		ResourceExclusion exclusion2 = new ResourceExclusion();
		ExclusionInstance instance3 = new ExclusionInstance();
		instance3.setResource(fFolder3);
		exclusion2.addExclusionInstance(instance3);
		exclusion1.addNestedExclusion(exclusion2);

		ResourceExclusion exclusion3 = new ResourceExclusion();
		ExclusionInstance instance4 = new ExclusionInstance();
		instance4.setResource(fFolder4);
		exclusion3.addExclusionInstance(instance4);
		exclusion2.addNestedExclusion(exclusion3);

		// now check and see if the right folders are included/excluded
		assertEquals(true, manager.shouldResourceBeRefreshed(conf_name, config1_resource));
		assertEquals(false, manager.shouldResourceBeRefreshed(conf_name, fFolder1));
		assertEquals(false, manager.shouldResourceBeRefreshed(conf_name, fFolder2));
		assertEquals(true, manager.shouldResourceBeRefreshed(conf_name, fFolder3));
		assertEquals(false, manager.shouldResourceBeRefreshed(conf_name, fFolder4));
		assertEquals(true, manager.shouldResourceBeRefreshed(conf_name, fFolder5));
		assertEquals(false, manager.shouldResourceBeRefreshed(conf_name, fFolder6));

		// now let's create a bunch of files in these directories using java.io.File (so that we don't get
		// resource deltas happening), and refresh the project according to the policy.  We should only see the files
		// in the same folders above when consulting the resource system
		IPath path = fProject.getLocation();
		createTestFile(path);

		path = fFolder1.getLocation();
		createTestFile(path);

		path = fFolder2.getLocation();
		createTestFile(path);

		path = fFolder3.getLocation();
		createTestFile(path);

		path = fFolder4.getLocation();
		createTestFile(path);

		path = fFolder5.getLocation();
		createTestFile(path);

		path = fFolder6.getLocation();
		createTestFile(path);

		// now refresh
		IWorkspaceRunnable runnable = manager.getRefreshRunnable(fProject, conf_name);
		try {
			ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
		} catch (CoreException e) {
			fail();
		}

		// check if the proper resources exist in the workspace
		IResource resource = fProject.getFile("foo.cpp");
		assertEquals(true, resource.exists());
		resource = fFolder1.getFile("foo.cpp");
		assertEquals(false, resource.exists());
		resource = fFolder2.getFile("foo.cpp");
		assertEquals(false, resource.exists());
		resource = fFolder3.getFile("foo.cpp");
		assertEquals(true, resource.exists());
		resource = fFolder4.getFile("foo.cpp");
		assertEquals(false, resource.exists());
		resource = fFolder5.getFile("foo.cpp");
		assertEquals(true, resource.exists());
		resource = fFolder6.getFile("foo.cpp");
		assertEquals(false, resource.exists());

		manager.clearAllData();

	}

	private void createTestFile(IPath path) {
		path = path.append("foo.cpp");
		File file = new File(path.toOSString());
		try {
			file.createNewFile();
		} catch (IOException e) {
			fail();
		}

	}

	public void testDefaults() {
		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		// by default, a project should refresh its root
		List<IResource> resourcesToRefresh = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(1, resourcesToRefresh.size());
		assertEquals(resourcesToRefresh.contains(fProject), true);

		// there should be no exclusions
		List<RefreshExclusion> exclusions = manager.getExclusions(fProject, config1, fProject);
		assertEquals(0, exclusions.size());

		ICProjectDescription projectDescription = CCorePlugin.getDefault().getProjectDescription(fProject);

		// now try persisting the data and loading it
		try {
			manager.persistSettings(projectDescription);
		} catch (CoreException e) {
			fail();
		}

		manager.clearAllData();

		try {
			manager.loadSettings();
		} catch (CoreException e) {
			fail();
		}

		// test the defaults again
		// by default, a project should refresh its root
		resourcesToRefresh = manager.getResourcesToRefresh(fProject, config1);
		assertEquals(1, resourcesToRefresh.size());
		assertEquals(resourcesToRefresh.contains(fProject), true);

		// there should be no exclusions
		exclusions = manager.getExclusions(fProject, config1, fProject);
		assertEquals(0, exclusions.size());

	}

	public void closeProject(ICProjectDescription projDesc) {

		try {
			// save the project description
			CCorePlugin.getDefault().setProjectDescription(fProject, projDesc);
			fProject.close(null);
		} catch (CoreException e1) {
			fail();
		}
	}

	public void openProject() {
		try {
			fProject.open(null);
		} catch (CoreException e) {
			fail();
		}
	}

	public String getCurrentConfigName() {
		CProjectDescriptionManager descriptionManager = CProjectDescriptionManager.getInstance();
		ICProjectDescription projectDescription = descriptionManager.getProjectDescription(fProject, false);
		ICConfigurationDescription conf = projectDescription.getActiveConfiguration();
		return conf.getName();
	}

	public void testEmptyRefreshScopeCloseAndReopen() {

		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		String config_name = getCurrentConfigName();

		// get the resources.  since we are not loading ... the project should auto-magically be added by default.
		List<IResource> config_resources = manager.getResourcesToRefresh(fProject, config_name);
		assertEquals(1, config_resources.size());
		assertEquals(true, config_resources.contains(fProject));

		// now delete it.
		manager.deleteResourceToRefresh(fProject, config_name, fProject);

		// and make sure it is empty.
		config_resources = manager.getResourcesToRefresh(fProject, config_name);
		assertEquals(0, config_resources.size());

		// write the persistent data.
		ICProjectDescription projectDescription = CCorePlugin.getDefault().getProjectDescription(fProject);
		try {
			manager.persistSettings(projectDescription);
		} catch (CoreException e) {
			fail();
		}

		// close and reopen
		closeProject(projectDescription);
		openProject();

		// now verify that there are no resources.
		HashMap<String, HashMap<IResource, List<RefreshExclusion>>> config_map = manager
				.getConfigurationToResourcesMap(fProject);
		assertEquals(1, config_map.size());
		config_resources = manager.getResourcesToRefresh(fProject, config_name);
		assertEquals(0, config_resources.size());
	}

	public void testAddEmptyConfiguration() {
		final String CFG_NAME = "empty_config";

		CoreModel model = CoreModel.getDefault();
		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		CProjectDescriptionManager descriptionManager = CProjectDescriptionManager.getInstance();
		ICProjectDescription projectDescription = descriptionManager.getProjectDescription(fProject, false);
		ICConfigurationDescription base = projectDescription.getActiveConfiguration();

		ICProjectDescription propertyProjectDescription = CoreModel.getDefault().getProjectDescription(fProject);
		ICConfigurationDescription propertyDefaultConfigurationDescription = propertyProjectDescription
				.getConfigurations()[0];
		try {
			projectDescription.setReadOnly(false, true);
			ICConfigurationDescription newCfg = projectDescription.createConfiguration(CFG_NAME + ".id", CFG_NAME,
					propertyDefaultConfigurationDescription);
		} catch (WriteAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		List<IResource> empty_config_resources = manager.getResourcesToRefresh(fProject, CFG_NAME);
		assertEquals(1, empty_config_resources.size());
		assertEquals(true, empty_config_resources.contains(fProject));

	}

	public void testNullProjectDescription_bug387428() {
		final String CFG_NAME = "empty_config";

		CProjectDescriptionManager descriptionManager = CProjectDescriptionManager.getInstance();
		ICProjectDescription projectDescription = descriptionManager.getProjectDescription(fGeneralProject, false);
		assertNull(projectDescription);

		RefreshScopeManager manager = RefreshScopeManager.getInstance();
		manager.clearAllData();

		List<IResource> empty_config_resources = manager.getResourcesToRefresh(fGeneralProject, CFG_NAME);
		assertEquals(1, empty_config_resources.size());
		assertEquals(true, empty_config_resources.contains(fGeneralProject));
	}

	public static Test suite() {
		return new TestSuite(RefreshScopeTests.class);
	}

}
