/*******************************************************************************
 * Copyright (c) 2000, 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.ui.tests.api;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.SaveableHelper;
import org.eclipse.ui.internal.WorkbenchPage;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.registry.IActionSetDescriptor;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.tests.PerspectiveState;
import org.eclipse.ui.tests.harness.util.CallHistory;
import org.eclipse.ui.tests.harness.util.EmptyPerspective;
import org.eclipse.ui.tests.harness.util.FileUtil;
import org.eclipse.ui.tests.harness.util.UITestCase;

public class IWorkbenchPageTest extends UITestCase {

	private IWorkbenchPage fActivePage;

	private IWorkbenchWindow fWin;

	private IProject proj;

	public IWorkbenchPageTest(String testName) {
		super(testName);
	}

	protected void doSetUp() throws Exception {
		super.doSetUp();
		fWin = openTestWindow();
		fActivePage = fWin.getActivePage();
	}

	protected void doTearDown() throws Exception {
		super.doTearDown();
		if (proj != null) {
			FileUtil.deleteProject(proj);
			proj = null;
		}
	}

	/**
	 * Tests the new working set API.
	 * 
	 * @since 3.2
	 */
	public void testWorkingSets1() {
		IWorkbenchPage page = fActivePage;
		IWorkingSet[] sets = page.getWorkingSets();
		assertNotNull(sets);
		assertEquals(0, sets.length);

		IWorkingSetManager manager = page.getWorkbenchWindow().getWorkbench()
				.getWorkingSetManager();

		IWorkingSet set1 = null, set2 = null;
		try {
			set1 = manager.createWorkingSet("w1", new IAdaptable[0]);
			manager.addWorkingSet(set1);
			set2 = manager.createWorkingSet("w2", new IAdaptable[0]);
			manager.addWorkingSet(set2);

			page.setWorkingSets(new IWorkingSet[] { set1 });
			sets = page.getWorkingSets();

			assertNotNull(sets);
			assertEquals(1, sets.length);
			assertEquals(set1, sets[0]);

			page.setWorkingSets(new IWorkingSet[0]);
			sets = page.getWorkingSets();
			assertNotNull(sets);
			assertEquals(0, sets.length);

			page.setWorkingSets(new IWorkingSet[] { set1, set2 });
			sets = page.getWorkingSets();

			assertNotNull(sets);
			assertEquals(2, sets.length);
			Set realSet = new HashSet(Arrays.asList(sets));
			assertTrue(realSet.contains(set1));
			assertTrue(realSet.contains(set2));

			page.setWorkingSets(new IWorkingSet[0]);
			sets = page.getWorkingSets();
			assertNotNull(sets);
			assertEquals(0, sets.length);
		} finally {
			if (set1 != null)
				manager.removeWorkingSet(set1);
			if (set2 != null)
				manager.removeWorkingSet(set2);
		}
	}

	/**
	 * Tests the new working set API.
	 * 
	 * @since 3.2
	 */
	public void testWorkingSets2() {
		fActivePage.setWorkingSets(null);
		IWorkingSet[] sets = fActivePage.getWorkingSets();
		assertNotNull(sets);
		assertEquals(0, sets.length);
	}

	/**
	 * Tests the working set listeners.
	 * 
	 * @since 3.2
	 */
	public void testWorkingSets3() {
		IWorkingSetManager manager = fActivePage.getWorkbenchWindow()
				.getWorkbench().getWorkingSetManager();

		IWorkingSet set1 = null;
		final IWorkingSet[][] sets = new IWorkingSet[1][];
		sets[0] = new IWorkingSet[0];
		IPropertyChangeListener listener = new IPropertyChangeListener() {

			public void propertyChange(PropertyChangeEvent event) {
				IWorkingSet[] oldSets = (IWorkingSet[]) event.getOldValue();
				assertTrue(Arrays.equals(sets[0], oldSets));
				sets[0] = (IWorkingSet[]) event.getNewValue();
			}
		};
		try {
			set1 = manager.createWorkingSet("w1", new IAdaptable[0]);
			manager.addWorkingSet(set1);

			fActivePage.addPropertyChangeListener(listener);

			fActivePage.setWorkingSets(new IWorkingSet[] { set1 });
			fActivePage.setWorkingSets(new IWorkingSet[] {});
			fActivePage.setWorkingSets(new IWorkingSet[] { set1 });

			sets[0] = fActivePage.getWorkingSets();

			assertNotNull(sets[0]);
			assertEquals(1, sets[0].length);
			assertEquals(set1, sets[0][0]);

		} finally {
			fActivePage.removePropertyChangeListener(listener);
			if (set1 != null)
				manager.removeWorkingSet(set1);
		}
	}

	/**
	 * Test the VIEW_VISIBLE parameter for showView, opening the view in the
	 * stack that does not contain the active view. Ensures that the created
	 * view is not the active part but is the top part in its stack.
	 */
	public void testView_VISIBLE2() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		try {
			page.setPerspective(WorkbenchPlugin.getDefault()
					.getPerspectiveRegistry().findPerspectiveWithId(
							"org.eclipse.ui.tests.api.ViewPerspective"));

			// create a part to be active
			IViewPart activePart = page.showView(MockViewPart.ID3);

			IViewPart createdPart = page.showView(MockViewPart.ID2, null,
					IWorkbenchPage.VIEW_VISIBLE);

			IViewPart[] stack = page.getViewStack(createdPart);
			assertEquals(2, stack.length);

			assertEquals(createdPart, stack[0]);
			assertEquals(page.findView(MockViewPart.ID), stack[1]);

			assertTrue(page.isPartVisible(createdPart));

			assertEquals(activePart, page.getActivePart());
		} catch (PartInitException e) {
			fail(e.getMessage());
		}
	}

	/**
	 * openEditor(IEditorInput input, String editorId, boolean activate)
	 */
	public void testOpenEditor4() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		final String id = MockEditorPart.ID1;
		IEditorInput input = new FileEditorInput(FileUtil.createFile(
				"test.mock1", proj));
		MockPartListener listener = new MockPartListener();
		fActivePage.addPartListener(listener);
		CallHistory callTrace = listener.getCallHistory();

		/*
		 * javadoc: The editor type is determined by mapping editorId to an
		 * editor extension registered with the workbench. javadoc: If activate ==
		 * true the editor will be activated
		 */
		// open an editor with activation
		// Start with a view active in order to verify that the editor gets
		// activated
		fActivePage.showView(IPageLayout.ID_PROBLEM_VIEW, null,
				IWorkbenchPage.VIEW_ACTIVATE);
		callTrace.clear();
		IEditorPart editor = IDE.openEditor(fActivePage, input, id, true);
		assertEquals(editor.getEditorInput(), input);
		assertEquals(editor.getSite().getId(), id);
		assertEquals(hasEditor(editor), true);
		assertEquals(fActivePage.getActiveEditor(), editor);
		assertEquals(callTrace.contains("partActivated"), true);

		// we need another editor so that the editor under test can receive
		// events.
		// otherwise, events will be ignored.
		IEditorPart extra = IDE.openEditor(fActivePage, FileUtil.createFile(
				"aaaaa", proj));

		// close the first editor after the second has opened; necessary for
		// test to work with fix to PR 7743
		fActivePage.closeEditor(editor, false);

		// Start with a view active in order to verify that the editor does not
		// get activated
		// (note: regardless of the activate=false flag, the editor would always
		// be activated
		// if it is being opened in the same stack as the active editor. Making
		// a view active
		// initially tests the function of the activate flag)
		fActivePage.showView(IPageLayout.ID_PROBLEM_VIEW, null,
				IWorkbenchPage.VIEW_ACTIVATE);
		callTrace.clear();
		// open an editor without activation
		editor = IDE.openEditor(fActivePage, input, id, false);

		assertEquals(editor.getEditorInput(), input);
		assertEquals(editor.getSite().getId(), id);
		assertEquals(hasEditor(editor), true);
		assertEquals(callTrace.contains("partActivated"), false);
		assertEquals(callTrace.contains("partBroughtToTop"), true);

		fActivePage.activate(extra);

		/*
		 * javadoc: If this page already has an editor open on the target object
		 * that editor is brought to the front
		 */
		// open the editor under test second time without activation
		fActivePage.showView(IPageLayout.ID_PROBLEM_VIEW, null,
				IWorkbenchPage.VIEW_ACTIVATE);
		callTrace.clear();
		assertEquals(IDE.openEditor(fActivePage, input, id, false), editor);
		assertEquals(callTrace.contains("partBroughtToTop"), true);
		assertEquals(callTrace.contains("partActivated"), false);

		// activate the other editor
		fActivePage.activate(extra);

		/*
		 * javadoc: If activate == true the editor will be activated
		 */
		// open the editor under test second time with activation
		fActivePage.showView(IPageLayout.ID_PROBLEM_VIEW, null,
				IWorkbenchPage.VIEW_ACTIVATE);
		callTrace.clear();
		assertEquals(IDE.openEditor(fActivePage, input, id, true), editor);
		assertEquals(callTrace.contains("partBroughtToTop"), true);
		assertEquals(callTrace.contains("partActivated"), true);

		/*
		 * javadoc: If activate == false but another editor in the same stack
		 * was active, the new editor will be activated regardless.
		 */
		// Close the old editor
		fActivePage.closeEditor(editor, false);
		// Ensure another editor in the stack is active
		fActivePage.activate(extra);
		callTrace.clear();
		// Verify that the editor is still activated
		IDE.openEditor(fActivePage, input, id, false);
		assertEquals(callTrace.contains("partBroughtToTop"), true);
		assertEquals(callTrace.contains("partActivated"), true);
	}

	/**
	 * tests both of the following: setEditorAreaVisible() isEditorAreaVisible()
	 */
	public void testGet_SetEditorAreaVisible() throws Throwable {
		fActivePage.setEditorAreaVisible(true);
		assertTrue(fActivePage.isEditorAreaVisible() == true);

		fActivePage.setEditorAreaVisible(false);
		assertTrue(fActivePage.isEditorAreaVisible() == false);
	}

	/**
	 * openEditor(IWorkbenchPage page, IFile input)
	 */
	public void testOpenEditor() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");

		/*
		 * javadoc: 1. The workbench editor registry is consulted to determine
		 * if an editor extension has been registered for the file type. If so,
		 * an instance of the editor extension is opened on the file
		 */
		IFile file = FileUtil.createFile("test.mock1", proj);
		IEditorPart editor = IDE.openEditor(fActivePage, file);

		boolean foundEditor = hasEditor(editor);
		assertEquals(foundEditor, true);
		assertEquals(fActivePage.getActiveEditor(), editor);
		assertEquals(editor.getSite().getId(), fWorkbench.getEditorRegistry()
				.getDefaultEditor(file.getName()).getId());

		/*
		 * javadoc: 2. Next, the native operating system will be consulted to
		 * determine if a native editor exists for the file type. If so, a new
		 * process is started and the native editor is opened on the file.
		 */
		// can not be tested
		/*
		 * javadoc: 3. If all else fails the file will be opened in a default
		 * text editor.
		 */

		file = FileUtil.createFile("a.null and void", proj);
		editor = IDE.openEditor(fActivePage, file);
		if (editor != null) {//If it opened an external editor skip it (Vista issue)
			assertEquals(hasEditor(editor), true);
			assertEquals(fActivePage.getActiveEditor(), editor);
			assertEquals(editor.getSite().getId(),
					"org.eclipse.ui.DefaultTextEditor");

			// open another editor to take the focus away from the first editor
			IDE
					.openEditor(fActivePage, FileUtil.createFile("test.mock2",
							proj));

			/*
			 * javadoc: If this page already has an editor open on the target
			 * object that editor is activated
			 */
			// open the editor second time.
			assertEquals(editor, IDE.openEditor(fActivePage, file));
			assertEquals(editor, fActivePage.getActiveEditor());
		}
	}

	/**
	 * openEditor(IWorkbenchPage page, IFile input, String editorID)
	 */
	public void testOpenEditor2() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		final IFile file = FileUtil.createFile("asfasdasdf", proj);
		final String id = MockEditorPart.ID1;

		/*
		 * javadoc: The editor type is determined by mapping editorId to an
		 * editor extension registered with the workbench.
		 */
		IEditorPart editor = IDE.openEditor(fActivePage, file, id);
		assertEquals(editor.getSite().getId(), id);
		assertEquals(hasEditor(editor), true);
		assertEquals(fActivePage.getActiveEditor(), editor);

		// open another editor to take the focus away from the first editor
		IDE.openEditor(fActivePage, FileUtil.createFile("test.mock2", proj));

		/*
		 * javadoc: If this page already has an editor open on the target object
		 * that editor is activated
		 */
		// open the first editor second time.
		assertEquals(IDE.openEditor(fActivePage, file, id), editor);
		assertEquals(fActivePage.getActiveEditor(), editor);
	}

	/**
	 * openEditor(IEditorInput input,String editorId)
	 */
	public void testOpenEditor3() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		final String id = MockEditorPart.ID1;
		IEditorInput input = new FileEditorInput(FileUtil.createFile(
				"test.mock1", proj));

		/*
		 * javadoc: The editor type is determined by mapping editorId to an
		 * editor extension registered with the workbench
		 */
		IEditorPart editor = IDE.openEditor(fActivePage, input, id);
		assertEquals(editor.getEditorInput(), input);
		assertEquals(editor.getSite().getId(), id);
		assertEquals(hasEditor(editor), true);
		assertEquals(fActivePage.getActiveEditor(), editor);

		// open another editor to take the focus away from the first editor
		IDE.openEditor(fActivePage, FileUtil.createFile("test.mock2", proj));

		/*
		 * javadoc: If this page already has an editor open on the target object
		 * that editor is activated
		 */
		// open the first editor second time.
		assertEquals(IDE.openEditor(fActivePage, input, id), editor);
		assertEquals(fActivePage.getActiveEditor(), editor);
	}

	/**
	 * openEditor(IMarker marker)
	 */
	public void testOpenEditor5() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		IMarker marker = FileUtil.createFile("aa.mock2", proj).createMarker(
				IMarker.TASK);
		CallHistory callTrace;

		/*
		 * javadoc: the cursor and selection state of the editor is then updated
		 * from information recorded in the marker.
		 */
		// open the registered editor for the marker resource
		IEditorPart editor = IDE.openEditor(fActivePage, marker);
		callTrace = ((MockEditorPart) editor).getCallHistory();
		assertEquals(editor.getSite().getId(), MockEditorPart.ID2);
		assertEquals(hasEditor(editor), true);
		assertEquals(fActivePage.getActiveEditor(), editor);
		assertEquals(callTrace.contains("gotoMarker"), true);
		fActivePage.closeEditor(editor, false);

		/*
		 * javadoc: If the marker contains an EDITOR_ID_ATTR attribute the
		 * attribute value will be used to determine the editor type to be
		 * opened
		 */
		marker.setAttribute(IDE.EDITOR_ID_ATTR, MockEditorPart.ID1);
		editor = IDE.openEditor(fActivePage, marker);
		callTrace = ((MockEditorPart) editor).getCallHistory();
		assertEquals(editor.getSite().getId(), MockEditorPart.ID1);
		assertEquals(hasEditor(editor), true);
		assertEquals(fActivePage.getActiveEditor(), editor);
		assertEquals(callTrace.contains("gotoMarker"), true);
		// do not close the editor this time

		/*
		 * javdoc: If this page already has an editor open on the target object
		 * that editor is activated
		 */
		callTrace.clear();
		assertEquals(IDE.openEditor(fActivePage, marker), editor);
		assertEquals(fActivePage.getActiveEditor(), editor);
		assertEquals(callTrace.contains("gotoMarker"), true);
		fActivePage.closeEditor(editor, false);
	}

	/**
	 * openEditor(IMarker marker, boolean activate)
	 */
	public void testOpenEditor6() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		IMarker marker = FileUtil.createFile("aa.mock2", proj).createMarker(
				IMarker.TASK);
		MockPartListener listener = new MockPartListener();
		fActivePage.addPartListener(listener);
		CallHistory listenerCall = listener.getCallHistory();
		CallHistory editorCall;

		// we need another editor so that the editor under test can receive
		// events.
		// otherwise, events will be ignored.
		IEditorPart extra = IDE.openEditor(fActivePage, FileUtil.createFile(
				"aaaaa", proj));

		/*
		 * javadoc: If activate == true the editor will be activated
		 */
		// open the registered editor for the marker resource with activation
		IEditorPart editor = IDE.openEditor(fActivePage, marker, true);
		editorCall = ((MockEditorPart) editor).getCallHistory();
		assertEquals(editor.getSite().getId(), MockEditorPart.ID2);
		assertEquals(hasEditor(editor), true);
		assertEquals(fActivePage.getActiveEditor(), editor);

		/*
		 * javadoc: the cursor and selection state of the editor is then updated
		 * from information recorded in the marker.
		 */
		assertEquals(editorCall.contains("gotoMarker"), true);
		fActivePage.closeEditor(editor, false);

		fActivePage.activate(extra);

		// open the registered editor for the marker resource without activation
		fActivePage.showView(IPageLayout.ID_PROBLEM_VIEW, null,
				IWorkbenchPage.VIEW_ACTIVATE);
		listenerCall.clear();
		editor = IDE.openEditor(fActivePage, marker, false);
		editorCall = ((MockEditorPart) editor).getCallHistory();
		assertEquals(editor.getSite().getId(), MockEditorPart.ID2);
		assertEquals(hasEditor(editor), true);
		assertEquals(listenerCall.contains("partBroughtToTop"), true);
		assertEquals(listenerCall.contains("partActivated"), false);
		assertEquals(editorCall.contains("gotoMarker"), true);
		fActivePage.closeEditor(editor, false);

		/*
		 * javadoc: If the marker contains an EDITOR_ID_ATTR attribute the
		 * attribute value will be used to determine the editor type to be
		 * opened
		 */
		String id = MockEditorPart.ID1;
		marker.setAttribute(IDE.EDITOR_ID_ATTR, id);

		// open an editor with activation
		listenerCall.clear();

		editor = IDE.openEditor(fActivePage, marker, true);
		editorCall = ((MockEditorPart) editor).getCallHistory();
		assertEquals(editor.getSite().getId(), id);
		assertEquals(hasEditor(editor), true);
		assertEquals(fActivePage.getActiveEditor(), editor);
		assertEquals(editorCall.contains("gotoMarker"), true);
		fActivePage.closeEditor(editor, false);

		fActivePage.activate(extra);

		// open an editor without activation
		fActivePage.showView(IPageLayout.ID_PROBLEM_VIEW, null,
				IWorkbenchPage.VIEW_ACTIVATE);
		listenerCall.clear();
		editor = IDE.openEditor(fActivePage, marker, false);
		editorCall = ((MockEditorPart) editor).getCallHistory();
		assertEquals(editor.getSite().getId(), id);
		assertEquals(hasEditor(editor), true);
		assertEquals(editorCall.contains("gotoMarker"), true);
		assertEquals(listenerCall.contains("partActivated"), false);
		assertEquals(listenerCall.contains("partBroughtToTop"), true);
		// do not close the editor this time

		fActivePage.activate(extra);
		/*
		 * javadoc: If this page already has an editor open on the target object
		 * that editor is brought to front Note: we need to make a non-editor
		 * active first or bringing the editor to front would activate it
		 */
		// open the editor second time without activation
		fActivePage.showView(IPageLayout.ID_PROBLEM_VIEW, null,
				IWorkbenchPage.VIEW_ACTIVATE);
		listenerCall.clear();
		assertEquals(IDE.openEditor(fActivePage, marker, false), editor);
		assertEquals(listenerCall.contains("partBroughtToTop"), true);
		assertEquals(listenerCall.contains("partActivated"), false);

		fActivePage.activate(extra);

		/*
		 * javdoc: If activate == true the editor will be activated
		 */
		// open the editor second time with activation
		listenerCall.clear();
		assertEquals(IDE.openEditor(fActivePage, marker, true), editor);
		assertEquals(editorCall.contains("gotoMarker"), true);
		assertEquals(listenerCall.contains("partBroughtToTop"), true);
		assertEquals(listenerCall.contains("partActivated"), true);

		/*
		 * javadoc: If activate == false but another editor in the same stack
		 * was active, the new editor will be activated regardless.
		 */
		// Close the old editor
		fActivePage.closeEditor(editor, false);
		// Ensure another editor in the stack is active
		fActivePage.activate(extra);
		listenerCall.clear();
		// Verify that the editor is still activated
		IDE.openEditor(fActivePage, marker, false);
		assertEquals(listenerCall.contains("partBroughtToTop"), true);
		assertEquals(listenerCall.contains("partActivated"), true);
	}

	public void testGetPerspective() throws Throwable {
		assertNotNull(fActivePage.getPerspective());

		IWorkbenchPage page = fWin.openPage(EmptyPerspective.PERSP_ID,
				getPageInput());
		assertEquals(EmptyPerspective.PERSP_ID, page.getPerspective().getId());
	}

	public void testSetPerspective() throws Throwable {
		IPerspectiveDescriptor per = PlatformUI.getWorkbench()
				.getPerspectiveRegistry().findPerspectiveWithId(
						EmptyPerspective.PERSP_ID);
		fActivePage.setPerspective(per);
		assertEquals(per, fActivePage.getPerspective());
	}

	public void testGetLabel() {
		assertNotNull(fActivePage.getLabel());
	}

	public void testGetInput() throws Throwable {
		IAdaptable input = getPageInput();
		IWorkbenchPage page = fWin.openPage(input);
		assertEquals(input, page.getInput());
	}

	public void testActivate() throws Throwable {
		MockViewPart part = (MockViewPart) fActivePage
				.showView(MockViewPart.ID);
		MockViewPart part2 = (MockViewPart) fActivePage
				.showView(MockViewPart.ID2);

		MockPartListener listener = new MockPartListener();
		fActivePage.addPartListener(listener);
		fActivePage.activate(part);

		CallHistory callTrace;

		callTrace = part2.getCallHistory();
		callTrace.clear();
		fActivePage.activate(part2);
		assertTrue(callTrace.contains("setFocus"));
		assertTrue(listener.getCallHistory().contains("partActivated"));

		callTrace = part.getCallHistory();
		callTrace.clear();
		fActivePage.activate(part);
		assertTrue(callTrace.contains("setFocus"));
		assertTrue(listener.getCallHistory().contains("partActivated"));
	}

	public void testBringToTop() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		IEditorPart part = IDE.openEditor(fActivePage, FileUtil.createFile(
				"a.mock1", proj));
		IEditorPart part2 = IDE.openEditor(fActivePage, FileUtil.createFile(
				"b.mock1", proj));

		MockPartListener listener = new MockPartListener();
		fActivePage.addPartListener(listener);
		CallHistory callTrace = listener.getCallHistory();

		// at this point, part2 is active
		fActivePage.bringToTop(part);
		assertEquals(callTrace.contains("partBroughtToTop"), true);

		callTrace.clear();
		fActivePage.bringToTop(part2);
		assertEquals(callTrace.contains("partBroughtToTop"), true);
	}

	public void testGetWorkbenchWindow() {
		/*
		 * Commented out because until test case can be updated to work with new
		 * window/page/perspective implementation
		 * 
		 * assertEquals(fActivePage.getWorkbenchWindow(), fWin); IWorkbenchPage
		 * page = openTestPage(fWin); assertEquals(page.getWorkbenchWindow(),
		 * fWin);
		 */
	}

	public void testShowView() throws Throwable {
		/*
		 * javadoc: Shows a view in this page and give it focus
		 */
		MockViewPart view = (MockViewPart) fActivePage
				.showView(MockViewPart.ID);
		assertNotNull(view);
		assertTrue(view.getCallHistory().verifyOrder(
				new String[] { "init", "createPartControl", "setFocus" }));

		fActivePage.showView(MockViewPart.ID2);

		/*
		 * javadoc: If the view is already visible, it is given focus
		 */
		CallHistory callTrace = view.getCallHistory();
		callTrace.clear();
		assertEquals(fActivePage.showView(MockViewPart.ID), view);
		assertEquals(callTrace.contains("setFocus"), true);
	}

	/**
	 * Tests showing multi-instance views (docked normally).
	 */
	public void testShowViewMult() throws Throwable {
		/*
		 * javadoc: Shows the view identified by the given view id and secondary
		 * id in this page and gives it focus. This allows multiple instances of
		 * a particular view to be created. They are disambiguated using the
		 * secondary id.
		 */
		MockViewPart view = (MockViewPart) fActivePage
				.showView(MockViewPart.IDMULT);
		assertNotNull(view);
		assertTrue(view.getCallHistory().verifyOrder(
				new String[] { "init", "createPartControl", "setFocus" }));
		MockViewPart view2 = (MockViewPart) fActivePage.showView(
				MockViewPart.IDMULT, "2", IWorkbenchPage.VIEW_ACTIVATE);
		assertNotNull(view2);
		assertTrue(view2.getCallHistory().verifyOrder(
				new String[] { "init", "createPartControl", "setFocus" }));
		assertTrue(!view.equals(view2));
		MockViewPart view3 = (MockViewPart) fActivePage.showView(
				MockViewPart.IDMULT, "3", IWorkbenchPage.VIEW_ACTIVATE);
		assertNotNull(view3);
		assertTrue(view3.getCallHistory().verifyOrder(
				new String[] { "init", "createPartControl", "setFocus" }));
		assertTrue(!view.equals(view3));
		assertTrue(!view2.equals(view3));

		/*
		 * javadoc: If there is a view identified by the given view id and
		 * secondary id already open in this page, it is given focus.
		 */
		CallHistory callTrace = view.getCallHistory();
		callTrace.clear();
		assertEquals(fActivePage.showView(MockViewPart.IDMULT), view);
		assertEquals(callTrace.contains("setFocus"), true);
		CallHistory callTrace2 = view2.getCallHistory();
		callTrace.clear();
		callTrace2.clear();
		assertEquals(fActivePage.showView(MockViewPart.IDMULT, "2",
				IWorkbenchPage.VIEW_ACTIVATE), view2);
		assertEquals(callTrace2.contains("setFocus"), true);
		assertEquals(callTrace.contains("setFocus"), false);
		CallHistory callTrace3 = view3.getCallHistory();
		callTrace.clear();
		callTrace2.clear();
		callTrace3.clear();
		assertEquals(fActivePage.showView(MockViewPart.IDMULT, "3",
				IWorkbenchPage.VIEW_ACTIVATE), view3);
		assertEquals(callTrace3.contains("setFocus"), true);
		assertEquals(callTrace.contains("setFocus"), false);
		assertEquals(callTrace2.contains("setFocus"), false);

		/*
		 * javadoc: If a secondary id is given, the view must allow multiple
		 * instances by having specified allowMultiple="true" in its extension.
		 */
		boolean exceptionThrown = false;
		try {
			fActivePage.showView(MockViewPart.ID, "2",
					IWorkbenchPage.VIEW_ACTIVATE);
		} catch (PartInitException e) {
			assertEquals(e.getMessage().indexOf("mult") != -1, true);
			exceptionThrown = true;
		}
		assertEquals(exceptionThrown, true);
	}

	/**
	 * Tests showing multi-instance views (as fast views). This is a regression
	 * test for bug 76669 - [Perspectives] NullPointerException in
	 * Perspective.getFastViewWidthRatio()
	 */
	public void testShowViewMultFast() throws Throwable {
		/*
		 * javadoc: Shows the view identified by the given view id and secondary
		 * id in this page and gives it focus. This allows multiple instances of
		 * a particular view to be created. They are disambiguated using the
		 * secondary id.
		 */
		MockViewPart view = (MockViewPart) fActivePage
				.showView(MockViewPart.IDMULT);
		assertNotNull(view);
		assertTrue(view.getCallHistory().verifyOrder(
				new String[] { "init", "createPartControl", "setFocus" }));
		MockViewPart view2 = (MockViewPart) fActivePage.showView(
				MockViewPart.IDMULT, "2", IWorkbenchPage.VIEW_ACTIVATE);
		assertNotNull(view2);
		assertTrue(view2.getCallHistory().verifyOrder(
				new String[] { "init", "createPartControl", "setFocus" }));
		assertTrue(!view.equals(view2));

		WorkbenchPage page = (WorkbenchPage) fActivePage;
		IViewReference ref = (IViewReference) page.getReference(view);
		IViewReference ref2 = (IViewReference) page.getReference(view2);
		page.addFastView(ref);
		page.addFastView(ref2);

		page.activate(view);
		assertEquals(view, page.getActivePart());

		page.activate(view2);
		assertEquals(view2, page.getActivePart());
	}

	/**
	 * Tests saving the page state when there is a fast view that is also a
	 * multi-instance view. This is a regression test for bug 76669 -
	 * [Perspectives] NullPointerException in
	 * Perspective.getFastViewWidthRatio()
	 */
	public void testBug76669() throws Throwable {
		MockViewPart view = (MockViewPart) fActivePage
				.showView(MockViewPart.IDMULT);
		MockViewPart view2 = (MockViewPart) fActivePage.showView(
				MockViewPart.IDMULT, "2", IWorkbenchPage.VIEW_ACTIVATE);

		WorkbenchPage page = (WorkbenchPage) fActivePage;
		IViewReference ref = (IViewReference) page.getReference(view);
		IViewReference ref2 = (IViewReference) page.getReference(view2);
		page.addFastView(ref);
		page.addFastView(ref2);

		IMemento memento = XMLMemento.createWriteRoot("page");
		page.saveState(memento);
		IMemento persps = memento.getChild("perspectives");
		IMemento persp = persps.getChildren("perspective")[0];
		IMemento[] fastViews = persp.getChild("fastViews").getChildren("view");
		assertEquals(2, fastViews.length);
	}

	public void testFindView() throws Throwable {
		String id = MockViewPart.ID3;
		// id of valid, but not open view
		assertNull(fActivePage.findView(id));

		IViewPart view = fActivePage.showView(id);
		assertEquals(fActivePage.findView(id), view);

		// close view
		fActivePage.hideView(view);
		assertNull(fActivePage.findView(id));
	}

	public void testFindViewReference() throws Throwable {
		fActivePage.getWorkbenchWindow().getWorkbench().showPerspective(
				SessionPerspective.ID, fActivePage.getWorkbenchWindow());
		assertNull(fActivePage.findViewReference(MockViewPart.ID4));

		fActivePage.showView(MockViewPart.ID4);
		assertNotNull(fActivePage.findViewReference(MockViewPart.ID4));
	}

	public void testGetViews() throws Throwable {
		int totalBefore = fActivePage.getViewReferences().length;

		IViewPart view = fActivePage.showView(MockViewPart.ID2);
		assertEquals(hasView(view), true);
		assertEquals(fActivePage.getViewReferences().length, totalBefore + 1);

		fActivePage.hideView(view);
		assertEquals(hasView(view), false);
		assertEquals(fActivePage.getViewReferences().length, totalBefore);
	}

	public void testHideViewWithPart() throws Throwable {
		// test that nothing bad happens with a null parameter
		try {
			fActivePage.hideView((IViewPart) null);
		} catch (RuntimeException e) {
			fail(e.getMessage());
		}

		IViewPart view = fActivePage.showView(MockViewPart.ID3);

		fActivePage.hideView(view);
		CallHistory callTrace = ((MockViewPart) view).getCallHistory();
		assertTrue(callTrace.contains("dispose"));
	}

	public void testHideViewWithReference() throws Throwable {
		// test that nothing bad happens with a null parameter
		try {
			fActivePage.hideView((IViewReference) null);
		} catch (RuntimeException e) {
			fail(e.getMessage());
		}

		IViewPart view = fActivePage.showView(MockViewPart.ID4);
		IViewReference ref = fActivePage.findViewReference(MockViewPart.ID4);
		fActivePage.hideView(ref);
		CallHistory callTrace = ((MockViewPart) view).getCallHistory();
		assertTrue(callTrace.contains("dispose"));

	}

	public void testHideSaveableView() throws Throwable {
		String viewId = SaveableMockViewPart.ID;
		SaveableMockViewPart view = (SaveableMockViewPart) fActivePage
				.showView(viewId);
		fActivePage.hideView(view);
		CallHistory callTrace = view.getCallHistory();
		assertTrue(callTrace.contains("isDirty"));
		assertTrue(callTrace.contains("dispose"));
		assertEquals(fActivePage.findView(viewId), null);

		try {
			SaveableHelper.testSetAutomatedResponse(1); // No
			view = (SaveableMockViewPart) fActivePage.showView(viewId);
			view.setDirty(true);
			fActivePage.hideView(view);
			callTrace = view.getCallHistory();
			assertTrue(callTrace.contains("isDirty"));
			assertFalse(callTrace.contains("doSave"));
			assertTrue(callTrace.contains("dispose"));
			assertEquals(fActivePage.findView(viewId), null);

			SaveableHelper.testSetAutomatedResponse(2); // Cancel
			view = (SaveableMockViewPart) fActivePage.showView(viewId);
			view.setDirty(true);
			fActivePage.hideView(view);
			callTrace = view.getCallHistory();
			assertTrue(callTrace.contains("isDirty"));
			assertFalse(callTrace.contains("doSave"));
			assertFalse(callTrace.contains("dispose"));
			assertEquals(fActivePage.findView(viewId), view);

			SaveableHelper.testSetAutomatedResponse(0); // Yes
			view = (SaveableMockViewPart) fActivePage.showView(viewId);
			view.setDirty(true);
			fActivePage.hideView(view);
			callTrace = view.getCallHistory();
			assertTrue(callTrace.contains("isDirty"));
			assertTrue(callTrace.contains("doSave"));
			assertTrue(callTrace.contains("dispose"));
			assertEquals(fActivePage.findView(viewId), null);

			// don't leave the view showing, or the UI will block on window
			// close
		} finally {
			SaveableHelper.testSetAutomatedResponse(-1); // restore default
			// (prompt)
		}
	}

	/**
	 * Tests that a close will fall back to the default if the view returns
	 * ISaveable2.DEFAULT.
	 * 
	 * @throws Throwable
	 */
	public void testCloseWithSaveNeeded() throws Throwable {
		String viewId = UserSaveableMockViewPart.ID;
		UserSaveableMockViewPart view = (UserSaveableMockViewPart) fActivePage
				.showView(viewId);
		fActivePage.hideView(view);

		UserSaveableMockViewPart view2 = null;

		CallHistory callTrace = view.getCallHistory();
		assertTrue(callTrace.contains("isDirty"));
		assertTrue(callTrace.contains("dispose"));
		assertEquals(fActivePage.findView(UserSaveableMockViewPart.ID), null);

		try {
			SaveableHelper.testSetAutomatedResponse(3); // DEFAULT
			view = (UserSaveableMockViewPart) fActivePage.showView(viewId);
			view.setDirty(true);
			view2 = (UserSaveableMockViewPart) fActivePage.showView(viewId,
					"2", IWorkbenchPage.VIEW_ACTIVATE);
			assertNotNull(view2);
			view2.setDirty(true);

			WorkbenchPage page = (WorkbenchPage) fActivePage;
			page.getEditorManager().saveAll(true, false, false);

			assertFalse(view.isDirty());
			assertFalse(view2.isDirty());

			callTrace = view.getCallHistory();
			fActivePage.hideView(view);
			fActivePage.hideView(view2);

			assertTrue(callTrace.contains("isDirty"));
			assertTrue(callTrace.contains("doSave"));
			assertEquals(fActivePage.findView(viewId), null);

			// don't leave the view showing, or the UI will block on window
			// close
		} finally {
			SaveableHelper
					.testSetAutomatedResponse(SaveableHelper.USER_RESPONSE); // restore
			// default
			// (prompt)
		}
	}

	/**
	 * Tests that a close will fall back to the default if the view returns
	 * ISaveable2.DEFAULT.
	 * 
	 * @throws Throwable
	 */
	public void testSaveEffectsSharedModel() throws Throwable {
		String viewId = UserSaveableSharedViewPart.ID;
		UserSaveableSharedViewPart view = null;

		UserSaveableSharedViewPart view2 = null;

		assertEquals(fActivePage.findView(UserSaveableSharedViewPart.ID), null);

		try {
			SaveableHelper.testSetAutomatedResponse(3); // DEFAULT
			UserSaveableSharedViewPart.SharedModel model = new UserSaveableSharedViewPart.SharedModel();
			view = (UserSaveableSharedViewPart) fActivePage.showView(viewId);
			view.setSharedModel(model);

			view2 = (UserSaveableSharedViewPart) fActivePage.showView(viewId,
					"2", IWorkbenchPage.VIEW_ACTIVATE);
			assertNotNull(view2);
			view2.setSharedModel(model);

			WorkbenchPage page = (WorkbenchPage) fActivePage;
			page.getEditorManager().saveAll(true, false, false);

			assertFalse(view.isDirty());
			assertFalse(view2.isDirty());

			CallHistory callTrace = view.getCallHistory();
			CallHistory call2 = view2.getCallHistory();

			assertTrue(callTrace.contains("isDirty"));
			assertTrue(call2.contains("isDirty"));
			assertTrue("At least one should call doSave", callTrace
					.contains("doSave")
					|| call2.contains("doSave"));
			assertFalse("Both should not call doSave", callTrace
					.contains("doSave")
					&& call2.contains("doSave"));

			// don't leave the view showing, or the UI will block on window
			// close
		} finally {
			SaveableHelper
					.testSetAutomatedResponse(SaveableHelper.USER_RESPONSE); // restore
			// default
			// (prompt)
			fActivePage.hideView(view);
			fActivePage.hideView(view2);
		}
	}

	public void testClose() throws Throwable {
		IWorkbenchPage page = openTestPage(fWin);

		proj = FileUtil.createProject("testOpenEditor");
		final IFile file = FileUtil.createFile("aaa.mock1", proj);
		IEditorPart editor = IDE.openEditor(page, file);
		CallHistory callTrace = ((MockEditorPart) editor).getCallHistory();
		callTrace.clear();

		/*
		 * javadoc: If the page has open editors with unsaved content and save
		 * is true, the user will be given the opportunity to save them
		 */
		assertEquals(page.close(), true);
		assertEquals(callTrace
				.verifyOrder(new String[] { "isDirty", "dispose" }), true);
		assertEquals(fWin.getActivePage(), fActivePage);
	}

	public void testCloseEditor() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		final IFile file = FileUtil.createFile("test.mock1", proj);
		IEditorPart editor;
		CallHistory callTrace;
		MockEditorPart mock;

		/*
		 * javadoc: Parameters: save - true to save the editor contents if
		 * required (recommended)
		 */
		// create a clean editor that needs to be saved on closing
		editor = IDE.openEditor(fActivePage, file);
		mock = (MockEditorPart) editor;
		mock.setSaveNeeded(true);
		callTrace = mock.getCallHistory();
		callTrace.clear();
		// close the editor with save confirmation
		assertEquals(fActivePage.closeEditor(editor, true), true);
		assertEquals(callTrace
				.verifyOrder(new String[] { "isDirty", "dispose" }), true);

		/*
		 * javadoc: If the editor has unsaved content and save is true, the user
		 * will be given the opportunity to save it.
		 */
		// can't be tested
		/*
		 * javadoc: Parameters: save - false to discard any unsaved changes
		 */
		// create a dirty editor
		editor = IDE.openEditor(fActivePage, file);
		mock = (MockEditorPart) editor;
		mock.setDirty(true);
		mock.setSaveNeeded(true);
		callTrace = mock.getCallHistory();
		callTrace.clear();
		// close the editor and discard changes
		assertEquals(fActivePage.closeEditor(editor, false), true);
		assertEquals(callTrace.contains("isSaveOnCloseNeeded"), false);
		/*
		 * It is possible that some action may query the isDirty value of the
		 * editor to update its enabled state. There is nothing wrong in doing
		 * that, so do not test for no isDirty call here.
		 * 
		 * assertEquals(callTrace.contains( "isDirty"), false);
		 */
		assertEquals(callTrace.contains("doSave"), false);
		assertEquals(callTrace.contains("dispose"), true);
	}

	public void testCloseEditors() throws Throwable {
		int total = 5;
		final IFile[] files = new IFile[total];
		IEditorPart[] editors = new IEditorPart[total];
		IEditorReference[] editorRefs = new IEditorReference[total];
		CallHistory[] callTraces = new CallHistory[total];
		MockEditorPart[] mocks = new MockEditorPart[total];

		proj = FileUtil.createProject("testCloseEditors");
		for (int i = 0; i < total; i++)
			files[i] = FileUtil.createFile(i + ".mock2", proj);

		/*
		 * javadoc: If the page has open editors with unsaved content and save
		 * is true, the user will be given the opportunity to save them.
		 */
		// close all clean editors with confirmation
		for (int i = 0; i < total; i++) {
			editors[i] = IDE.openEditor(fActivePage, files[i]);
			callTraces[i] = ((MockEditorPart) editors[i]).getCallHistory();
		}

		editorRefs = fActivePage.getEditorReferences();
		assertEquals(fActivePage.closeEditors(editorRefs, true), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), false);
			callTraces[i].clear();
		}

		// close all dirty editors with confirmation
		// can't be tested

		// close all dirty editors discarding them
		for (int i = 0; i < total; i++) {
			editors[i] = IDE.openEditor(fActivePage, files[i]);
			mocks[i] = (MockEditorPart) editors[i];
			mocks[i].setDirty(true);
			callTraces[i] = mocks[i].getCallHistory();
		}
		editorRefs = fActivePage.getEditorReferences();
		assertEquals(fActivePage.closeEditors(editorRefs, false), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("doSave"), false);
		}

		// close empty array of editors
		total = 1;
		for (int i = 0; i < total; i++) {
			editors[i] = IDE.openEditor(fActivePage, files[i]);
			mocks[i] = (MockEditorPart) editors[i];
			mocks[i].setDirty(true);
			callTraces[i] = mocks[i].getCallHistory();
		}
		// empty array test
		editorRefs = new IEditorReference[0];
		assertEquals(fActivePage.closeEditors(editorRefs, true), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), false);
			callTraces[i].clear();
		}

		// close the last remaining editor, with save=false
		editorRefs = fActivePage.getEditorReferences();
		fActivePage.closeEditors(editorRefs, false);
	}

	public void testCloseAllEditors() throws Throwable {
		int total = 5;
		final IFile[] files = new IFile[total];
		IEditorPart[] editors = new IEditorPart[total];
		CallHistory[] callTraces = new CallHistory[total];
		MockEditorPart[] mocks = new MockEditorPart[total];

		proj = FileUtil.createProject("testOpenEditor");
		for (int i = 0; i < total; i++)
			files[i] = FileUtil.createFile(i + ".mock2", proj);

		/*
		 * javadoc: If the page has open editors with unsaved content and save
		 * is true, the user will be given the opportunity to save them.
		 */
		// close all clean editors with confirmation
		for (int i = 0; i < total; i++) {
			editors[i] = IDE.openEditor(fActivePage, files[i]);
			callTraces[i] = ((MockEditorPart) editors[i]).getCallHistory();
		}
		assertEquals(fActivePage.closeAllEditors(true), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), false);
			callTraces[i].clear();
		}

		// close all dirty editors with confirmation
		// can't be tested

		// close all dirty editors discarding them
		for (int i = 0; i < total; i++) {
			editors[i] = IDE.openEditor(fActivePage, files[i]);
			mocks[i] = (MockEditorPart) editors[i];
			mocks[i].setDirty(true);
			callTraces[i] = mocks[i].getCallHistory();
		}
		assertEquals(fActivePage.closeAllEditors(false), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("doSave"), false);
		}
	}

	public void testSaveEditor() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		final IFile file = FileUtil.createFile("test.mock1", proj);
		IEditorPart editor;
		CallHistory callTrace;
		MockEditorPart mock;

		// create a clean editor
		editor = IDE.openEditor(fActivePage, file);
		mock = (MockEditorPart) editor;
		callTrace = mock.getCallHistory();
		callTrace.clear();

		/*
		 * javadoc: Saves the contents of the given editor if dirty. If not,
		 * this method returns without effect
		 */
		// save the clean editor with confirmation
		assertEquals(fActivePage.saveEditor(editor, true), true);
		assertEquals(callTrace.contains("isDirty"), true);
		assertEquals(callTrace.contains("doSave"), false);

		/*
		 * javadoc: If confirm is true the user is prompted to confirm the
		 * command.
		 */
		// can't be tested
		/*
		 * javadoc: Otherwise, the save happens without prompt.
		 */
		// save the clean editor without confirmation
		assertEquals(fActivePage.saveEditor(editor, false), true);
		assertEquals(callTrace.contains("isDirty"), true);
		assertEquals(callTrace.contains("doSave"), false);

		// save the dirty editor without confirmation
		mock.setDirty(true);
		callTrace.clear();
		assertEquals(fActivePage.saveEditor(editor, false), true);
		assertEquals(callTrace
				.verifyOrder(new String[] { "isDirty", "doSave" }), true);
	}

	public void testIDESaveAllEditors() throws Throwable {
		int total = 3;

		final IFile[] files = new IFile[total];
		IEditorPart[] editors = new IEditorPart[total];
		CallHistory[] callTraces = new CallHistory[total];
		MockEditorPart[] mocks = new MockEditorPart[total];

		proj = FileUtil.createProject("testOpenEditor");
		for (int i = 0; i < total; i++) {
			files[i] = FileUtil.createFile(i + ".mock2", proj);
			editors[i] = IDE.openEditor(fActivePage, files[i]);
			mocks[i] = (MockEditorPart) editors[i];
			callTraces[i] = mocks[i].getCallHistory();
		}

		/*
		 * javadoc: If there are no dirty editors this method returns without
		 * effect. javadoc: If confirm is true the user is prompted to confirm
		 * the command
		 */
		// save all clean editors with confirmation
		assertEquals(IDE.saveAllEditors(new IResource[] { proj }, true), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), false);
			callTraces[i].clear();
		}

		// save all dirty editors with confirmation can't be tested

		/*
		 * javadoc: Parameters: confirm - false to save unsaved changes without
		 * asking
		 */
		// save all clean editors without confirmation
		assertEquals(IDE.saveAllEditors(new IResource[] { proj }, false), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), false);
			callTraces[i].clear();
		}

		// save all dirty editors with resource that IS NOT a parent
		// of the contents of the dirty editors without confirmation, this
		// should not
		// save any as they are not parented by the resource provided
		for (int i = 0; i < total; i++)
			mocks[i].setDirty(true);

		IResource emptyProj = FileUtil
				.createProject("testOpenEditorEmptyProject");
		assertEquals(IDE.saveAllEditors(new IResource[] { emptyProj }, false),
				true);
		for (int i = 0; i < total; i++) {
			// the editors were not in the empty project hence still dirty
			assertEquals(mocks[i].isDirty(), true);
			callTraces[i].clear();
		}

		// save all dirty editors with resource that IS a parent
		// of the contents of the editors without confirmation, this should
		// save them as they are parented by the resource provided
		assertEquals(IDE.saveAllEditors(new IResource[] { proj }, false), true);
		for (int i = 0; i < total; i++) {
			// the editors were not in the empty project hence still dirty
			assertEquals(mocks[i].isDirty(), false);
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), true);
			callTraces[i].clear();
		}

		// save all dirty editors with resource that IS NOT a parent
		// of the contents of the dirty editors without confirmation, this
		// should not
		// save any as they are not parented by the resource provided
		for (int i = 0; i < total; i++)
			mocks[i].setDirty(true);
		assertEquals(IDE.saveAllEditors(new IResource[] {}, false), true);
		for (int i = 0; i < total; i++) {
			// the editors were not in the empty project hence still dirty
			assertEquals(mocks[i].isDirty(), true);
			callTraces[i].clear();
		}

		// clear the dirty state so the tearDown does not open a confirm dialog.
		for (int i = 0; i < total; i++)
			mocks[i].setDirty(false);
	}

	public void testSaveAllEditors() throws Throwable {
		int total = 3;

		final IFile[] files = new IFile[total];
		IEditorPart[] editors = new IEditorPart[total];
		CallHistory[] callTraces = new CallHistory[total];
		MockEditorPart[] mocks = new MockEditorPart[total];

		proj = FileUtil.createProject("testOpenEditor");
		for (int i = 0; i < total; i++) {
			files[i] = FileUtil.createFile(i + ".mock2", proj);
			editors[i] = IDE.openEditor(fActivePage, files[i]);
			mocks[i] = (MockEditorPart) editors[i];
			callTraces[i] = mocks[i].getCallHistory();
		}

		/*
		 * javadoc: If there are no dirty editors this method returns without
		 * effect. javadoc: If confirm is true the user is prompted to confirm
		 * the command
		 */
		// save all clean editors with confirmation
		assertEquals(fActivePage.saveAllEditors(true), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), false);
			callTraces[i].clear();
		}

		// save all dirty editors with confirmation can't be tested

		/*
		 * javadoc: Parameters: confirm - false to save unsaved changes without
		 * asking
		 */
		// save all clean editors without confirmation
		assertEquals(fActivePage.saveAllEditors(false), true);
		for (int i = 0; i < total; i++) {
			assertEquals(callTraces[i].contains("isDirty"), true);
			assertEquals(callTraces[i].contains("doSave"), false);
			callTraces[i].clear();
		}

		// save all dirty editors without confirmation
		for (int i = 0; i < total; i++)
			mocks[i].setDirty(true);
		assertEquals(fActivePage.saveAllEditors(false), true);
		for (int i = 0; i < total; i++)
			assertEquals(callTraces[i].verifyOrder(new String[] { "isDirty",
					"doSave" }), true);
	}

	public void testGetEditors() throws Throwable {
		proj = FileUtil.createProject("testOpenEditor");
		int totalBefore = fActivePage.getEditorReferences().length;
		int num = 3;
		IEditorPart[] editors = new IEditorPart[num];

		for (int i = 0; i < num; i++) {
			editors[i] = IDE.openEditor(fActivePage, FileUtil.createFile(i
					+ ".mock2", proj));
			assertEquals(hasEditor(editors[i]), true);
		}
		assertEquals(fActivePage.getEditorReferences().length, totalBefore
				+ num);

		fActivePage.closeEditor(editors[0], false);
		assertEquals(hasEditor(editors[0]), false);
		assertEquals(fActivePage.getEditorReferences().length, totalBefore
				+ num - 1);

		fActivePage.closeAllEditors(false);
		assertEquals(fActivePage.getEditorReferences().length, 0);
	}

	public void testShowActionSet() {
		String id = MockActionDelegate.ACTION_SET_ID;
		WorkbenchPage page = (WorkbenchPage) fActivePage;

		int totalBefore = page.getActionSets().length;
		fActivePage.showActionSet(id);

		IActionSetDescriptor[] sets = ((WorkbenchPage) fActivePage)
				.getActionSets();
		boolean found = false;
		for (int i = 0; i < sets.length; i++)
			if (id.equals(sets[i].getId()))
				found = true;
		assertEquals(found, true);

		// check that the method does not add an invalid action set to itself
		id = IConstants.FakeID;
		fActivePage.showActionSet(id);

		sets = ((WorkbenchPage) fActivePage).getActionSets();
		found = false;
		for (int i = 0; i < sets.length; i++)
			if (id.equals(sets[i].getId()))
				found = true;
		assertEquals(found, false);
		assertEquals(page.getActionSets().length, totalBefore + 1);
	}

	public void testHideActionSet() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		int totalBefore = page.getActionSets().length;

		String id = MockWorkbenchWindowActionDelegate.SET_ID;
		fActivePage.showActionSet(id);
		assertEquals(page.getActionSets().length, totalBefore + 1);

		fActivePage.hideActionSet(id);
		assertEquals(page.getActionSets().length, totalBefore);

		IActionSetDescriptor[] sets = page.getActionSets();
		boolean found = false;
		for (int i = 0; i < sets.length; i++)
			if (id.equals(sets[i].getId()))
				found = true;
		assertEquals(found, false);
	}

	/**
	 * Return whether or not the editor exists in the current page.
	 * 
	 * @param editor
	 * @return boolean
	 */
	private boolean hasEditor(IEditorPart editor) {
		IEditorReference[] references = fActivePage.getEditorReferences();
		for (int i = 0; i < references.length; i++) {
			if (references[i].getEditor(false).equals(editor))
				return true;
		}
		return false;
	}

	/**
	 * Return whether or not the view exists in the current page.
	 * 
	 * @param editor
	 * @return boolean
	 */
	private boolean hasView(IViewPart view) {
		IViewReference[] references = fActivePage.getViewReferences();
		for (int i = 0; i < references.length; i++) {
			if (references[i].getView(false).equals(view))
				return true;
		}
		return false;
	}

	public void testStackOrder() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		try {
			IViewPart part1 = page.showView(MockViewPart.ID);
			IViewPart part2 = page.showView(MockViewPart.ID2);
			IViewPart part3 = page.showView(MockViewPart.ID3);
			IViewPart part4 = page.showView(MockViewPart.ID4);

			IViewPart[] stack = page.getViewStack(part1);
			assertTrue(stack.length == 4);
			assertTrue(stack[0] == part4);
			assertTrue(stack[1] == part3);
			assertTrue(stack[2] == part2);
			assertTrue(stack[3] == part1);

			page.activate(part2);
			stack = page.getViewStack(part1);
			assertTrue(stack.length == 4);
			assertTrue(stack[0] == part2);
			assertTrue(stack[1] == part4);
			assertTrue(stack[2] == part3);
			assertTrue(stack[3] == part1);

			page.activate(part1);
			stack = page.getViewStack(part1);
			assertTrue(stack.length == 4);
			assertTrue(stack[0] == part1);
			assertTrue(stack[1] == part2);
			assertTrue(stack[2] == part4);
			assertTrue(stack[3] == part3);

			page.activate(part3);
			stack = page.getViewStack(part1);
			assertTrue(stack.length == 4);
			assertTrue(stack[0] == part3);
			assertTrue(stack[1] == part1);
			assertTrue(stack[2] == part2);
			assertTrue(stack[3] == part4);
		} catch (PartInitException e) {
			fail(e.getMessage());
		}
	}

	/**
	 * Test the VIEW_CREATE parameter for showView. Ensures that the created
	 * view is not the active part.
	 * 
	 */
	public void testView_CREATE1() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		try {

			page.setPerspective(WorkbenchPlugin.getDefault()
					.getPerspectiveRegistry().findPerspectiveWithId(
							"org.eclipse.ui.tests.api.ViewPerspective"));

			// create a part to be active
			IViewPart activePart = page.showView(MockViewPart.ID);
			IViewPart createdPart = page.showView(MockViewPart.ID2, null,
					IWorkbenchPage.VIEW_CREATE);

			IViewPart[] stack = page.getViewStack(activePart);
			assertEquals(2, stack.length);

			assertEquals(activePart, stack[0]);
			assertEquals(createdPart, stack[1]);

			assertFalse(page.isPartVisible(createdPart));

			assertEquals(activePart, page.getActivePart());
		} catch (PartInitException e) {
			fail(e.getMessage());
		}
	}

	/**
	 * Test the VIEW_CREATE parameter for showView. Ensures that the created
	 * view is not the active part and is not visible
	 */
	public void testView_CREATE2() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		try {

			page.setPerspective(WorkbenchPlugin.getDefault()
					.getPerspectiveRegistry().findPerspectiveWithId(
							"org.eclipse.ui.tests.api.ViewPerspective"));

			// create a part to be active
			IViewPart activePart = page.showView(MockViewPart.ID3);
			IViewPart createdPart = page.showView(MockViewPart.ID2, null,
					IWorkbenchPage.VIEW_CREATE);

			IViewPart[] stack = page.getViewStack(createdPart);
			assertEquals(2, stack.length);

			assertEquals(page.findView(MockViewPart.ID), stack[0]);
			assertEquals(createdPart, stack[1]);

			assertFalse(page.isPartVisible(createdPart));

			assertEquals(activePart, page.getActivePart());
		} catch (PartInitException e) {
			fail(e.getMessage());
		}
	}

	/**
	 * Test the VIEW_CREATE parameter for showView. Ensures that the created
	 * view is not the active part and is visible.
	 */
	public void testView_CREATE3() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		try {

			page.setPerspective(WorkbenchPlugin.getDefault()
					.getPerspectiveRegistry().findPerspectiveWithId(
							"org.eclipse.ui.tests.api.ViewPerspective"));

			// create a part to be active
			IViewPart activePart = page.showView(MockViewPart.ID3);
			IViewPart createdPart = page.showView(MockViewPart.ID4, null,
					IWorkbenchPage.VIEW_CREATE);

			IViewPart[] stack = page.getViewStack(createdPart);
			assertEquals(1, stack.length);

			assertEquals(createdPart, stack[0]);

			assertTrue(page.isPartVisible(createdPart));

			assertEquals(activePart, page.getActivePart());
		} catch (PartInitException e) {
			fail(e.getMessage());
		}
	}

	/**
	 * Test the VIEW_VISIBLE parameter for showView, opening the view in the
	 * stack containing the active view. Ensures that the created view is not
	 * the active part and is not visible.
	 */
	public void testView_VISIBLE1() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		try {
			page.setPerspective(WorkbenchPlugin.getDefault()
					.getPerspectiveRegistry().findPerspectiveWithId(
							"org.eclipse.ui.tests.api.ViewPerspective"));

			// create a part to be active
			IViewPart activePart = page.showView(MockViewPart.ID);
			IViewPart createdPart = page.showView(MockViewPart.ID2, null,
					IWorkbenchPage.VIEW_VISIBLE);
			IViewPart[] stack = page.getViewStack(activePart);
			assertEquals(2, stack.length);

			assertEquals(activePart, stack[0]);
			assertEquals(createdPart, stack[1]);

			assertFalse(page.isPartVisible(createdPart));

			assertEquals(activePart, page.getActivePart());
		} catch (PartInitException e) {
			fail(e.getMessage());
		}
	}

	/**
	 * Test the VIEW_VISIBLE parameter for showView, opening the view in its own
	 * stack. Ensures that the created view is not active part but is the top
	 * part in its stack.
	 */
	public void testView_VISIBLE3() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;
		try {
			page.setPerspective(WorkbenchPlugin.getDefault()
					.getPerspectiveRegistry().findPerspectiveWithId(
							"org.eclipse.ui.tests.api.ViewPerspective"));

			// create a part to be active
			IViewPart activePart = page.showView(MockViewPart.ID3);

			IViewPart createdPart = page.showView(MockViewPart.ID4, null,
					IWorkbenchPage.VIEW_VISIBLE);
			IViewPart[] stack = page.getViewStack(createdPart);
			assertEquals(1, stack.length);

			assertEquals(createdPart, stack[0]);

			assertTrue(page.isPartVisible(createdPart));

			assertEquals(activePart, page.getActivePart());
		} catch (PartInitException e) {
			fail(e.getMessage());
		}
	}

	/**
	 * Test opening a perspective with a fast view.
	 */
	public void testOpenPerspectiveWithFastView() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;

		try {
			fWin.getWorkbench().showPerspective(
					PerspectiveWithFastView.PERSP_ID, fWin);
		} catch (WorkbenchException e) {
			fail("Unexpected WorkbenchException: " + e);
		}

		assertEquals(page.getFastViews().length, 1);
		assertEquals(page.getFastViews()[0].getId(),
				"org.eclipse.ui.views.ResourceNavigator");
		assertEquals(page.getViewReferences().length, 1);
		assertTrue(page.getViewReferences()[0].isFastView());
		
		IPerspectiveDescriptor persp = page.getPerspective();
		
		ICommandService commandService = (ICommandService) fWorkbench.getService(ICommandService.class);
		Command command = commandService.getCommand("org.eclipse.ui.window.closePerspective");
		
		HashMap parameters = new HashMap();
		parameters.put("org.eclipse.ui.window.closePerspective.perspectiveId", persp.getId());
		
		ParameterizedCommand pCommand = ParameterizedCommand.generateCommand(command, parameters);
		
		IHandlerService handlerService = (IHandlerService) fWorkbench
				.getService(IHandlerService.class);
		try {
			handlerService.executeCommand(pCommand, null);
		} catch (ExecutionException e1) {
		} catch (NotDefinedException e1) {
		} catch (NotEnabledException e1) {
		} catch (NotHandledException e1) {
		}

	}

	/**
	 * Test opening a perspective with placeholders for multi instance views.
	 * The placeholders are added at top level (not in any folder).
	 * 
	 * @since 3.1
	 */
	public void testOpenPerspectiveWithMultiViewPlaceholdersAtTopLevel() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;

		try {
			fWin.getWorkbench().showPerspective(
					PerspectiveWithMultiViewPlaceholdersAtTopLevel.PERSP_ID,
					fWin);
		} catch (WorkbenchException e) {
			fail("Unexpected WorkbenchException: " + e);
		}

		PerspectiveState state = new PerspectiveState(page);
		ArrayList partIds = state.getPartIds(null);
		assertTrue(partIds.contains("*"));
		assertTrue(partIds.contains(MockViewPart.IDMULT));
		assertTrue(partIds.contains(MockViewPart.IDMULT + ":secondaryId"));
		assertTrue(partIds.contains(MockViewPart.IDMULT + ":*"));
	}

	/**
	 * Test opening a perspective with placeholders for multi instance views.
	 * The placeholders are added in a placeholder folder. This is a regression
	 * test for bug 72383 [Perspectives] Placeholder folder error with multiple
	 * instance views
	 * 
	 * @since 3.1
	 */
	public void testOpenPerspectiveWithMultiViewPlaceholdersInPlaceholderFolder() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;

		try {
			fWin
					.getWorkbench()
					.showPerspective(
							PerspectiveWithMultiViewPlaceholdersInPlaceholderFolder.PERSP_ID,
							fWin);
		} catch (WorkbenchException e) {
			fail("Unexpected WorkbenchException: " + e);
		}

		PerspectiveState state = new PerspectiveState(page);
		ArrayList partIds = state.getPartIds("placeholderFolder");
		assertTrue(partIds.contains("*"));
		assertTrue(partIds.contains(MockViewPart.IDMULT));
		assertTrue(partIds.contains(MockViewPart.IDMULT + ":secondaryId"));
		assertTrue(partIds.contains(MockViewPart.IDMULT + ":*"));
	}

	/**
	 * Test opening a perspective with placeholders for multi instance views.
	 * The placeholders are added at top level (not in any folder).
	 * 
	 * @since 3.1
	 */
	public void testOpenPerspectiveWithMultiViewPlaceholdersInFolder() {
		WorkbenchPage page = (WorkbenchPage) fActivePage;

		try {
			fWin
					.getWorkbench()
					.showPerspective(
							PerspectiveWithMultiViewPlaceholdersInFolder.PERSP_ID,
							fWin);
		} catch (WorkbenchException e) {
			fail("Unexpected WorkbenchException: " + e);
		}

		PerspectiveState state = new PerspectiveState(page);
		ArrayList partIds = state.getPartIds("folder");
		assertTrue(partIds.contains("*"));
		assertTrue(partIds.contains(MockViewPart.IDMULT));
		assertTrue(partIds.contains(MockViewPart.IDMULT + ":secondaryId"));
		assertTrue(partIds.contains(MockViewPart.IDMULT + ":*"));
	}

	/**
	 * Tests the getNewWizardShortcuts() method.
	 * 
	 * @since 3.1
	 */
	public void testGetNewWizardShortcuts() {
		String[] shortcuts = fActivePage.getNewWizardShortcuts();
		assertNotNull(shortcuts);
		assertEquals(0, shortcuts.length);

		IWorkbenchWindow win = openTestWindow(IDE.RESOURCE_PERSPECTIVE_ID);
		IWorkbenchPage page = win.getActivePage();
		shortcuts = page.getNewWizardShortcuts();
		List shortcutList = Arrays.asList(shortcuts);
		assertTrue(shortcutList.contains("org.eclipse.ui.wizards.new.folder"));
		assertTrue(shortcutList.contains("org.eclipse.ui.wizards.new.file"));
	}

	/**
	 * Tests the getShowViewShortcuts() method.
	 * 
	 * @since 3.1
	 */
	public void testGetShowViewShortcuts() {
		String[] shortcuts = fActivePage.getShowViewShortcuts();
		assertNotNull(shortcuts);
		assertEquals(0, shortcuts.length);

		IWorkbenchWindow win = openTestWindow(IDE.RESOURCE_PERSPECTIVE_ID);
		IWorkbenchPage page = win.getActivePage();
		shortcuts = page.getShowViewShortcuts();
		List shortcutList = Arrays.asList(shortcuts);
		assertTrue(shortcutList.contains(IPageLayout.ID_RES_NAV));
		assertTrue(shortcutList.contains(IPageLayout.ID_OUTLINE));
		assertTrue(shortcutList.contains(IPageLayout.ID_PROP_SHEET));
		assertTrue(shortcutList.contains(IPageLayout.ID_PROBLEM_VIEW));
	}

	/**
	 * Tests the getPerspectiveShortcuts() method.
	 * 
	 * @since 3.1
	 */
	public void testGetPerspectiveShortcuts() {
		String[] shortcuts = fActivePage.getPerspectiveShortcuts();
		assertNotNull(shortcuts);
		assertEquals(0, shortcuts.length);
		// not much of a test
	}

	/**
	 * Tests the getOpenPerspectives() method.
	 * 
	 * @since 3.1
	 */
	public void testGetOpenPerspectives() {
		IPerspectiveDescriptor[] openPersps = fActivePage.getOpenPerspectives();
		assertEquals(1, openPersps.length);
		assertEquals(EmptyPerspective.PERSP_ID, openPersps[0].getId());

		IPerspectiveRegistry reg = fWorkbench.getPerspectiveRegistry();
		IPerspectiveDescriptor resourcePersp = reg
				.findPerspectiveWithId(IDE.RESOURCE_PERSPECTIVE_ID);
		fActivePage.setPerspective(resourcePersp);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(2, openPersps.length);
		assertEquals(EmptyPerspective.PERSP_ID, openPersps[0].getId());
		assertEquals(IDE.RESOURCE_PERSPECTIVE_ID, openPersps[1].getId());

		IPerspectiveDescriptor emptyPersp = reg
				.findPerspectiveWithId(EmptyPerspective.PERSP_ID);
		fActivePage.setPerspective(emptyPersp);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(2, openPersps.length);
		assertEquals(EmptyPerspective.PERSP_ID, openPersps[0].getId());
		assertEquals(IDE.RESOURCE_PERSPECTIVE_ID, openPersps[1].getId());

		fActivePage.closeAllPerspectives(false, false);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(0, openPersps.length);

		fActivePage.close();
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(0, openPersps.length);
	}

	/**
	 * Tests the getSortedPerspectives() method.
	 * 
	 * @since 3.1
	 */
	public void testGetSortedPerspectives() {
		IPerspectiveDescriptor[] openPersps = fActivePage
				.getSortedPerspectives();
		assertEquals(1, openPersps.length);
		assertEquals(EmptyPerspective.PERSP_ID, openPersps[0].getId());

		IPerspectiveRegistry reg = fWorkbench.getPerspectiveRegistry();
		IPerspectiveDescriptor resourcePersp = reg
				.findPerspectiveWithId(IDE.RESOURCE_PERSPECTIVE_ID);
		fActivePage.setPerspective(resourcePersp);
		openPersps = fActivePage.getSortedPerspectives();
		assertEquals(2, openPersps.length);
		assertEquals(EmptyPerspective.PERSP_ID, openPersps[0].getId());
		assertEquals(IDE.RESOURCE_PERSPECTIVE_ID, openPersps[1].getId());

		IPerspectiveDescriptor emptyPersp = reg
				.findPerspectiveWithId(EmptyPerspective.PERSP_ID);
		fActivePage.setPerspective(emptyPersp);
		openPersps = fActivePage.getSortedPerspectives();
		assertEquals(2, openPersps.length);
		assertEquals(IDE.RESOURCE_PERSPECTIVE_ID, openPersps[0].getId());
		assertEquals(EmptyPerspective.PERSP_ID, openPersps[1].getId());

		fActivePage.closeAllPerspectives(false, false);
		openPersps = fActivePage.getSortedPerspectives();
		assertEquals(0, openPersps.length);

		fActivePage.close();
		openPersps = fActivePage.getSortedPerspectives();
		assertEquals(0, openPersps.length);
	}

	/**
	 * Tests the closePerspective method.
	 * 
	 * @since 3.1
	 */
	public void testClosePerspective() {
		// TODO: Need to test variants with saveEditors==true

		IPerspectiveRegistry reg = fWorkbench.getPerspectiveRegistry();
		IPerspectiveDescriptor emptyPersp = reg
				.findPerspectiveWithId(EmptyPerspective.PERSP_ID);
		IPerspectiveDescriptor resourcePersp = reg
				.findPerspectiveWithId(IDE.RESOURCE_PERSPECTIVE_ID);

		fActivePage.setPerspective(resourcePersp);
		IPerspectiveDescriptor[] openPersps = fActivePage.getOpenPerspectives();
		assertEquals(2, openPersps.length);

		fActivePage.closePerspective(resourcePersp, false, false);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(1, openPersps.length);
		assertEquals(EmptyPerspective.PERSP_ID, openPersps[0].getId());

		fActivePage.closePerspective(emptyPersp, false, false);
		assertEquals(fActivePage, fWin.getActivePage()); // page not closed
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(0, openPersps.length);

		fActivePage.setPerspective(emptyPersp);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(1, openPersps.length);

		fActivePage.closePerspective(emptyPersp, false, true);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(0, openPersps.length);
		assertNull(fWin.getActivePage()); // page closed
	}

	/**
	 * Tests the closeAllPerspectives method.
	 * 
	 * @since 3.1
	 */
	public void testCloseAllPerspectives() {
		// TODO: Need to test variants with saveEditors==true

		IPerspectiveRegistry reg = fWorkbench.getPerspectiveRegistry();
		IPerspectiveDescriptor emptyPersp = reg
				.findPerspectiveWithId(EmptyPerspective.PERSP_ID);
		IPerspectiveDescriptor resourcePersp = reg
				.findPerspectiveWithId(IDE.RESOURCE_PERSPECTIVE_ID);

		fActivePage.setPerspective(resourcePersp);
		IPerspectiveDescriptor[] openPersps = fActivePage.getOpenPerspectives();
		assertEquals(2, openPersps.length);

		fActivePage.closeAllPerspectives(false, false);
		assertEquals(fActivePage, fWin.getActivePage()); // page not closed
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(0, openPersps.length);

		fActivePage.setPerspective(emptyPersp);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(1, openPersps.length);

		fActivePage.closeAllPerspectives(false, true);
		openPersps = fActivePage.getOpenPerspectives();
		assertEquals(0, openPersps.length);
		assertNull(fWin.getActivePage()); // page closed
	}

	/**
	 * Regression test for Bug 76285 [Presentations] Folder tab does not
	 * indicate current view. Tests that, when switching between perspectives,
	 * the remembered old part correctly handles multi-view instances.
	 */
	public void testBug76285() {
		IWorkbenchPage page = fActivePage;
		IPerspectiveDescriptor originalPersp = page.getPerspective();
		IPerspectiveDescriptor resourcePersp = PlatformUI.getWorkbench()
				.getPerspectiveRegistry().findPerspectiveWithId(
						IDE.RESOURCE_PERSPECTIVE_ID);
		// test requires switching between two different perspectives
		assertNotSame(originalPersp, resourcePersp);

		int n = 5;
		IViewPart[] views = new IViewPart[n];
		for (int i = 0; i < n; ++i) {
			try {
				views[i] = page.showView(MockViewPart.IDMULT, Integer
						.toString(i), IWorkbenchPage.VIEW_CREATE);
			} catch (PartInitException e) {
				fail(e.getMessage());
			}
		}
		assertEquals(5, page.getViews().length);
		for (int i = 0; i < n; ++i) {
			page.activate(views[i]);
			page.setPerspective(resourcePersp);
			assertFalse(page.getActivePart() instanceof MockViewPart);
			page.setPerspective(originalPersp);
			assertEquals(views[i], page.getActivePart());
		}
	}

	/**
	 * Tests that IShowEditorInput.showEditorInput is called when a matching
	 * editor is found during openEditor, and is not called when a new editor is
	 * opened.
	 * 
	 * @since 3.1
	 */
	public void testShowEditorInput() throws Exception {
		IWorkbenchPage page = fActivePage;
		proj = FileUtil.createProject("testShowEditorInput");
		IFile file = FileUtil.createFile("a.mock1", proj);
		MockEditorPart part1 = (MockEditorPart) IDE.openEditor(page, file);
		assertFalse(part1.getCallHistory().contains("showEditorInput"));

		MockEditorPart part2 = (MockEditorPart) IDE.openEditor(page, file);
		assertTrue(part1 == part2);
		assertTrue(part2.getCallHistory().contains("showEditorInput"));
	}

	/**
	 * Tests that the openEditor and findEditor variants that accepts match
	 * flags work as expected.
	 * 
	 * @since 3.2
	 */
	public void testOpenAndFindEditorWithMatchFlags() throws Exception {
		IWorkbenchPage page = fActivePage;
		proj = FileUtil.createProject("testOpenEditorMatchFlags");
		IFile file1 = FileUtil.createFile("a.mock1", proj);
		IFile file2 = FileUtil.createFile("a.mock2", proj);
		FileEditorInput input1 = new FileEditorInput(file1);
		FileEditorInput input2 = new FileEditorInput(file2);
		String id1 = MockEditorPart.ID1;
		String id2 = MockEditorPart.ID2;

		// first editor (no match)
		MockEditorPart part1 = (MockEditorPart) page.openEditor(input1, id1,
				true, IWorkbenchPage.MATCH_INPUT);
		assertNotNull(part1);

		// same input, same id, matching input (should match part1)
		MockEditorPart part2 = (MockEditorPart) page.openEditor(input1, id1,
				true, IWorkbenchPage.MATCH_INPUT);
		assertTrue(part1 == part2);

		// same input, different id, matching input (should match part1)
		MockEditorPart part3 = (MockEditorPart) page.openEditor(input1, id2,
				true, IWorkbenchPage.MATCH_INPUT);
		assertTrue(part1 == part3);

		// same input, different id, matching input and id (no match)
		MockEditorPart part4 = (MockEditorPart) page.openEditor(input1, id2,
				true, IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID);
		assertNotNull(part4);
		assertTrue(part4 != part1);

		// same input, same id, matching nothing (no match)
		MockEditorPart part5 = (MockEditorPart) page.openEditor(input1, id1,
				true, IWorkbenchPage.MATCH_NONE);
		assertNotNull(part5);
		assertTrue(part5 != part1);
		assertTrue(part5 != part4);

		// different input, same id, matching id (should match part5 instead of
		// part1, because it was active)
		MockEditorPart part6 = (MockEditorPart) page.openEditor(input2, id1,
				true, IWorkbenchPage.MATCH_ID);
		assertTrue(part6 == part5);

		// different input, different id, matching input and id (no match)
		MockEditorPart part7 = (MockEditorPart) page.openEditor(input2, id2,
				true, IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID);
		assertNotNull(part7);
		assertTrue(part7 != part1);
		assertTrue(part7 != part4);
		assertTrue(part7 != part5);

		// At this point, there are 4 editors open:
		// part1 (input1, id1), part4 (input1, id2), part5 (input1, id1), and
		// part7 (input2, id2).
		// with part7 active.

		// find with MATCH_NONE is always empty
		IEditorReference[] refs = page.findEditors(input1, id1,
				IWorkbenchPage.MATCH_NONE);
		assertEquals(0, refs.length);

		// find input1 with MATCH_INPUT finds 3 editors: part1, part4 and part5
		// (in order)
		refs = page.findEditors(input1, null, IWorkbenchPage.MATCH_INPUT);
		assertEquals(3, refs.length);
		assertEquals(part1, refs[0].getPart(true));
		assertEquals(part4, refs[1].getPart(true));
		assertEquals(part5, refs[2].getPart(true));

		// find input2 with MATCH_INPUT finds 1 editor: part7
		refs = page.findEditors(input2, null, IWorkbenchPage.MATCH_INPUT);
		assertEquals(1, refs.length);
		assertEquals(part7, refs[0].getPart(true));

		// find id1 with MATCH_ID finds 2 editors: part1 and part5 (in order)
		refs = page.findEditors(null, id1, IWorkbenchPage.MATCH_ID);
		assertEquals(2, refs.length);
		assertEquals(part1, refs[0].getPart(true));
		assertEquals(part5, refs[1].getPart(true));

		// find id2 with MATCH_ID finds 2 editors: part4 and part7 (with part7
		// first because it was active)
		refs = page.findEditors(null, id2, IWorkbenchPage.MATCH_ID);
		assertEquals(2, refs.length);
		assertEquals(part7, refs[0].getPart(true));
		assertEquals(part4, refs[1].getPart(true));

		// find input1 and id1 with MATCH_INPUT and MATCH_ID finds 2 editors:
		// part1 and part5 (in order)
		refs = page.findEditors(input1, id1, IWorkbenchPage.MATCH_INPUT
				| IWorkbenchPage.MATCH_ID);
		assertEquals(2, refs.length);
		assertEquals(part1, refs[0].getPart(true));
		assertEquals(part5, refs[1].getPart(true));

		// find input1 and id2 with MATCH_INPUT and MATCH_ID finds 1 editors:
		// part4
		refs = page.findEditors(input1, id2, IWorkbenchPage.MATCH_INPUT
				| IWorkbenchPage.MATCH_ID);
		assertEquals(1, refs.length);
		assertEquals(part4, refs[0].getPart(true));
	}
}
