Bug 166231
[launching] history not updated properly

AND

Bug 74480
[launching] Simplify the launch experience for less technical users of Eclipse
diff --git a/org.eclipse.jdt.debug.tests/testprograms/LaunchHistoryTest.java b/org.eclipse.jdt.debug.tests/testprograms/LaunchHistoryTest.java
new file mode 100644
index 0000000..3de6040
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/LaunchHistoryTest.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+public class LaunchHistoryTest {
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) {
+
+	}
+
+}
diff --git a/org.eclipse.jdt.debug.tests/testprograms/LaunchHistoryTest2.java b/org.eclipse.jdt.debug.tests/testprograms/LaunchHistoryTest2.java
new file mode 100644
index 0000000..dc1cbba
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/LaunchHistoryTest2.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+public class LaunchHistoryTest2 {
+
+	/**
+	 * @param args
+	 */
+	public static void main(String[] args) {
+
+	}
+
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
index e2c26e1..0bb9494 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java
@@ -1213,7 +1213,7 @@
 	 * Terminates the given debug target and removes its launch.
 	 * 
 	 * NOTE: all breakpoints are removed, all threads are resumed, and then
-	 * the target is terminated. This avoids defunct processes on linux.
+	 * the target is terminated. This avoids defunct processes on Linux.
 	 */
 	protected void terminateAndRemove(IJavaDebugTarget debugTarget) {
 	    ILaunch launch = debugTarget.getLaunch();
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index 084e39a..364db60 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -66,6 +66,7 @@
 import org.eclipse.jdt.debug.tests.launching.ContributedTabTests;
 import org.eclipse.jdt.debug.tests.launching.LaunchConfigurationTests;
 import org.eclipse.jdt.debug.tests.launching.LaunchDelegateTests;
+import org.eclipse.jdt.debug.tests.launching.LaunchHistoryTests;
 import org.eclipse.jdt.debug.tests.launching.LaunchModeTests;
 import org.eclipse.jdt.debug.tests.launching.LaunchShortcutTests;
 import org.eclipse.jdt.debug.tests.launching.LaunchTests;
@@ -125,6 +126,7 @@
 		addTest(new TestSuite(TabGroupWrapperTests.class));
 		addTest(new TestSuite(MigrationDelegateTests.class));
 		addTest(new TestSuite(RefreshTabTests.class));
+		addTest(new TestSuite(LaunchHistoryTests.class));
 		
 	//Breakpoints tests
 		addTest(new TestSuite(DeferredBreakpointTests.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
index d3ff4a0..c24c5d5 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
@@ -174,6 +174,10 @@
         createLaunchConfiguration("VariableDetails");
         createLaunchConfiguration("org.eclipse.debug.tests.targets.ArrayDetailTests");
         createLaunchConfiguration("ArrayDetailTestsDef");
+        
+        //launch history tests
+        createLaunchConfiguration("LaunchHistoryTest");
+        createLaunchConfiguration("LaunchHistoryTest2");
     }
 
     /**
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/launching/LaunchHistoryTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/launching/LaunchHistoryTests.java
new file mode 100644
index 0000000..171f9b4
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/launching/LaunchHistoryTests.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.debug.tests.launching;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchHistory;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+
+/**
+ * Test the utilization of launch histories: sizing, ordering, completeness and correctness
+ * 
+ * @see org.eclipse.debug.internal.ui.launchConfigurations.LaunchHistory
+ * @see org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager
+ * @see org.eclipse.debug.internal.ui.ILaunchHistoryChangedListener
+ * @see org.eclipse.debug.ui.actions.AbstractLaunchHistoryAction
+ * 
+ * @since 3.3
+ */
+public class LaunchHistoryTests extends AbstractDebugTest {
+
+	/**
+	 * Constructor
+	 * @param name
+	 */
+	public LaunchHistoryTests(String name) {
+		super(name);
+	}
+	
+	/**
+	 * Returns the run launch history
+	 * @return
+	 */
+	private LaunchHistory getRunLaunchHistory() {
+		return getLaunchConfigurationManager().getLaunchHistory(IDebugUIConstants.ID_RUN_LAUNCH_GROUP);
+	}
+	
+	/**
+	 * Returns the maximum allowed size of the launch histories
+	 * @return the maximum size of the launch histories
+	 */
+	private int getMaxHistorySize() {
+		return DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugUIConstants.PREF_MAX_HISTORY_SIZE);
+	}
+	
+	/**
+	 * Sets the maximum size of the launch history to the specified value
+	 * @param value the new maximum size for launch histories
+	 */
+	private void setMaxHistorySize(int value) {
+		DebugUIPlugin.getDefault().getPreferenceStore().setValue(IDebugUIConstants.PREF_MAX_HISTORY_SIZE, value);
+	}
+	
+	/**
+	 * Returns the debug launch history
+	 * @return
+	 */
+	private LaunchHistory getDebugLaunchHistory() {
+		return getLaunchConfigurationManager().getLaunchHistory(IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP);
+	}
+	
+	/**
+	 * This method tests that an item added to the history is added to the head of
+	 * history.
+	 */
+	public void testHistoryAddition() {
+		LaunchHistory runhistory = getRunLaunchHistory();
+		assertNotNull("The run launch history should not be null", runhistory);
+		try {
+			ILaunchConfiguration config = getLaunchConfiguration("LaunchHistoryTest");
+			assertNotNull("LaunchHistoryTest launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("The run history should contain the LaunchHistoryTest config", runhistory.contains(config));
+			assertEquals("The most recent launch should be LaunchHistoryTest", runhistory.getRecentLaunch(), config);
+		}
+		catch(CoreException ce) {DebugUIPlugin.log(ce);}
+	}
+	
+	/**
+	 * As both the run and the debug launch histories will accept a java application
+	 * launch config, both launch histories should contain the test launch configuration
+	 * and it should be the recent launch for both of them
+	 */
+	public void testHistoriesInSync() {
+		LaunchHistory runhistory = getRunLaunchHistory();
+		assertNotNull("The run launch history should not be null", runhistory);
+		LaunchHistory debughistory = getDebugLaunchHistory();
+		assertNotNull("the debug launch history should not be null", debughistory);
+		try {
+			ILaunchConfiguration config = getLaunchConfiguration("LaunchHistoryTest");
+			assertNotNull("LaunchHistoryTest launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("the run history should contain LaunchHistoryTest", runhistory.contains(config));
+			assertEquals("the run recent launch should be LaunchHistoryTest", runhistory.getRecentLaunch(), config);
+			assertTrue("the debug history should contain LaunchHistoryTest", debughistory.contains(config));
+			assertEquals("the debug recent launch should be LaunchHistoryTest", debughistory.getRecentLaunch(), config);
+		}
+		catch(CoreException ce) {DebugUIPlugin.log(ce);}
+	}
+	
+	/**
+	 * If we launch config A, then config B, and then config A again, A should be the most recent launch
+	 */
+	public void testHistoryReodering() {
+		LaunchHistory runhistory = getRunLaunchHistory();
+		assertNotNull("The run launch history should not be null", runhistory);
+		try {
+			ILaunchConfiguration config = getLaunchConfiguration("LaunchHistoryTest");
+			assertNotNull("LaunchHistoryTest launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("The run history should contain the LaunchHistoryTest config", runhistory.contains(config));
+			assertEquals("The most recent launch should be LaunchHistoryTest", runhistory.getRecentLaunch(), config);
+			config = getLaunchConfiguration("LaunchHistoryTest2");
+			assertNotNull("LaunchHistoryTest2 launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("The run history should contain the LaunchHistoryTest2 config", runhistory.contains(config));
+			assertEquals("The most recent launch should be LaunchHistoryTest2", runhistory.getRecentLaunch(), config);
+			config = getLaunchConfiguration("LaunchHistoryTest");
+			assertNotNull("LaunchHistoryTest launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("The run history should contain the LaunchHistoryTest config", runhistory.contains(config));
+			assertEquals("The most recent launch should be LaunchHistoryTest", runhistory.getRecentLaunch(), config);
+		}
+		catch(CoreException ce) {DebugUIPlugin.log(ce);}
+	}
+	
+	/**
+	 * If we rename a launch configuration it should not effect the launch history if the renamed configuration 
+	 * is present in the history.
+	 */
+	public void testRenameConfigHistoryUpdate() {
+		LaunchHistory runhistory = getRunLaunchHistory();
+		assertNotNull("The run launch history should not be null", runhistory);
+		try {
+			ILaunchConfiguration config = getLaunchConfiguration("LaunchHistoryTest");
+			assertNotNull("LaunchHistoryTest launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("The run history should contain the LaunchHistoryTest config", runhistory.contains(config));
+			assertEquals("The most recent launch should be LaunchHistoryTest", runhistory.getRecentLaunch(), config);
+			ILaunchConfigurationWorkingCopy copy = config.getWorkingCopy();
+			copy.rename("RenamedLaunchHistoryItem");
+			config = copy.doSave();
+			assertEquals("the renamed config should still be the first on in the history", runhistory.getRecentLaunch(), config);
+			
+			//rename the configuration back to what it was
+			copy = config.getWorkingCopy();
+			copy.rename("LaunchHistoryTest");
+			config = copy.doSave();
+		}
+		catch(CoreException ce) {DebugUIPlugin.log(ce);}
+	}
+	
+	/**
+	 * If we delete a launch configuration and the configuration is present in the launch history, it should be removed
+	 * from the history and the history should be shifted up one place. 
+	 */
+	public void testDeleteLaunchConfigurationHistoryUpdate() {
+		LaunchHistory runhistory = getRunLaunchHistory();
+		assertNotNull("The run launch history should not be null", runhistory);
+		try {
+			ILaunchConfiguration config = getLaunchConfiguration("LaunchHistoryTest");
+			assertNotNull("LaunchHistoryTest launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("The run history should contain the LaunchHistoryTest config", runhistory.contains(config));
+			assertEquals("The most recent launch should be LaunchHistoryTest", runhistory.getRecentLaunch(), config);
+			config = getLaunchConfiguration("LaunchHistoryTest2");
+			assertNotNull("LaunchHistoryTest2 launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("The run history should contain the LaunchHistoryTest2 config", runhistory.contains(config));
+			assertEquals("The most recent launch should be LaunchHistoryTest2", runhistory.getRecentLaunch(), config);
+			config.delete();
+			config = getLaunchConfiguration("LaunchHistoryTest");
+			assertEquals("the run history should have LaunchHistoryTest as the recent launch after delete", runhistory.getRecentLaunch(), config);
+			
+			//recreate the LaunchHistoryTest2 launch config in case it is needed elsewhere
+			createLaunchConfiguration("LaunchHistoryTest2");
+		}
+		catch(CoreException ce) {DebugUIPlugin.log(ce);}
+		catch(Exception e) {DebugUIPlugin.log(e);}
+	}
+	
+	/**
+	 * Tests that setting the size of the launch history appropriately changes what will be returned
+	 * when the history is queried for it contents
+	 */
+	public void testLaunchHistorySize() {
+		LaunchHistory runhistory = getRunLaunchHistory();
+		assertNotNull("The run launch history should not be null", runhistory);
+		try {
+			int oldsize = getMaxHistorySize();
+			setMaxHistorySize(2);
+			assertTrue("the maximum history size should be 2", getMaxHistorySize() == 2);
+			ILaunchConfiguration config = getLaunchConfiguration("LaunchHistoryTest");
+			assertNotNull("LaunchHistoryTest launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			config = getLaunchConfiguration("LaunchHistoryTest2");
+			assertNotNull("LaunchHistoryTest2 launch config should not be null", config);
+			config.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
+			assertTrue("there should only be two items in the history", runhistory.getHistory().length == getMaxHistorySize());
+			assertTrue("the complete launch history should be greater than or equal to the history size", runhistory.getCompleteLaunchHistory().length >= runhistory.getHistory().length);
+			
+			//reset the history size
+			setMaxHistorySize(oldsize);
+		}
+		catch(CoreException ce){DebugUIPlugin.log(ce);}
+	}
+}