/******************************************************************************* * Copyright (c) 2004, 2012 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.performance; import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.SubContributionItem; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.PartSite; import org.eclipse.ui.internal.PluginActionContributionItem; import org.eclipse.ui.internal.PopupMenuExtender; import org.eclipse.ui.internal.WorkbenchWindow; import org.eclipse.ui.tests.harness.util.UITestCase; import org.eclipse.ui.tests.performance.ObjectContributionClasses.ICommon; /** * Tests that object contributions are enabled and shown correctly in pop-up * menus depending on the state of the workbench. This test relies on the * <code>plugin.xml</code> file containing certain values. Please see the * appropriate section in that file for more information about the initial * set-up. * * @since 3.0 */ public final class ObjectContributionTest extends UITestCase { /** * Constructs a new instance of <code>ObjectContributionTest</code> with * the name of the test. * * @param name * The name of the test; may be <code>null</code>. */ public ObjectContributionTest(final String name) { super(name); } /** * Tests whether the content-type object contribution works. This is testing * a use care familiar to Ant UI. The content-type scans an XML file to see * if its root element is <code><project></code>. * * @throws CoreException * If a problem occurs when creating the project or file, or if * the project can't be opened. */ public final void testObjectStateContentType() throws CoreException { // Create an XML file with <project> as its root element. final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject testProject = workspace.getRoot().getProject( "ObjectContributionTestProject"); testProject.create(null); testProject.open(null); final IFile xmlFile = testProject.getFile("ObjectContributionTest.xml"); final String contents = "<testObjectStateContentTypeElement></testObjectStateContentTypeElement>"; final ByteArrayInputStream inputStream = new ByteArrayInputStream( contents.getBytes()); xmlFile.create(inputStream, true, null); final ISelection selection = new StructuredSelection(xmlFile); assertPopupMenus("1", new String[] {"org.eclipse.ui.tests.testObjectStateContentType"}, selection, null, true); } /** * This tests backwards compatibility support for adaptable IResource objectContributions. This * allows IResource adaptable contributions without an adapter factory and using * the IContributorResourceAdapter factory. In addition, test the ResourceMapping adaptations. * * @since 3.1 */ public final void testContributorResourceAdapter() throws CoreException { final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject testProject = workspace.getRoot().getProject(ObjectContributionClasses.PROJECT_NAME); if(! testProject.exists()) { testProject.create(null); } if(! testProject.isOpen()) { testProject.open(null); } assertPopupMenus("1", new String[] {"IResource.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.CResource()}), IResource.class, true ); assertPopupMenus("2", new String[] {"IProject.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.CFile()}), null, false ); assertPopupMenus("3", new String[] {"IFile.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.CFile()}), IFile.class, true ); assertPopupMenus("4", new String[] {"IResource.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.CFile(), new ObjectContributionClasses.CResource()}), IResource.class, true ); assertPopupMenus("5", new String[] {"IFile.1", "IProject.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.CFile(), new ObjectContributionClasses.CResource()}), IResource.class, false ); assertPopupMenus("6", new String[] {"ResourceMapping.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.CFile(), new ObjectContributionClasses.CResource()}), ResourceMapping.class, true ); assertPopupMenus("7", new String[] {"ResourceMapping.1", "IResource.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.ModelElement()}), ResourceMapping.class, true ); // Ensure that the case where an object uses a contribution adapter that doesn't handle mappings // will still show the menus for resource mappings assertPopupMenus("8", new String[] {"ResourceMapping.1", "IResource.1"}, new StructuredSelection(new Object[] {new ObjectContributionClasses.CResourceOnly()}), ResourceMapping.class, true ); } /** * This tests adaptable contributions that are not IResource. * * @since 3.1 */ public final void testAdaptables() { assertPopupMenus("1", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.A()}), ICommon.class, true ); assertPopupMenus("2", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.A(), new ObjectContributionClasses.B()}), ICommon.class, true ); assertPopupMenus("3", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.A(), new ObjectContributionClasses.B(), new ObjectContributionClasses.C(), new ObjectContributionClasses.Common() }), ICommon.class, true ); assertPopupMenus("4", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.Common(), new ObjectContributionClasses.C(), new ObjectContributionClasses.B(), new ObjectContributionClasses.A() }), ICommon.class, true ); assertPopupMenus("5", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.Common(), new ObjectContributionClasses.C(), new ObjectContributionClasses.B(), new ObjectContributionClasses.C(), new ObjectContributionClasses.A(), new ObjectContributionClasses.Common() }), ICommon.class, true ); assertPopupMenus("6", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.C(), new ObjectContributionClasses.Common() }), ICommon.class, true ); assertPopupMenus("7", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new Object() }), ICommon.class, false ); assertPopupMenus("8", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.C(), new Object() }), ICommon.class, false ); assertPopupMenus("9", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.C(), new ObjectContributionClasses.A(), new Object() }), ICommon.class, false ); } /** * Ensure that there are no duplicate contributions. * * @since 3.1 */ public final void testDuplicateAdaptables() { assertPopupMenus("1", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.D()}), ICommon.class, true ); // repeat test on purpose to ensure no double call duplicates. assertPopupMenus("1", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.D()}), ICommon.class, true ); assertPopupMenus("2", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.D(), new ObjectContributionClasses.A() }), ICommon.class, true ); assertPopupMenus("3", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.A(), new ObjectContributionClasses.D() }), ICommon.class, true ); assertPopupMenus("4", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.Common(), new ObjectContributionClasses.D() }), ICommon.class, true ); assertPopupMenus("5", new String[] {"ICommon.1"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.D(), new ObjectContributionClasses.Common() }), ICommon.class, true ); } /** * Test non-adaptable contributions * * @since 3.1 */ public final void testNonAdaptableContributions() { assertPopupMenus("1", new String[] {"ICommon.2"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.A(), new ObjectContributionClasses.B()}), ICommon.class, false ); assertPopupMenus("2", new String[] {"ICommon.2"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.D(), new ObjectContributionClasses.C(), new ObjectContributionClasses.Common()}), ICommon.class, true ); assertPopupMenus("3", new String[] {"Common.2"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.D(), new ObjectContributionClasses.C(), new ObjectContributionClasses.A()}), ICommon.class, false ); assertPopupMenus("4", new String[] {"Common.2"}, new StructuredSelection(new Object[] { new ObjectContributionClasses.B(), new ObjectContributionClasses.C(), new ObjectContributionClasses.A()}), ICommon.class, false ); } /** * Helper class that will create a popup menu based on the given selection and * then ensure that the provided commandIds are added to the menu. * * @param commandIds the command ids that should appear in the menu * @param selection the selection on which to contribute object contributions */ public void assertPopupMenus(String name, String[] commandIds, final ISelection selection, Class selectionType, boolean existance) { ISelectionProvider selectionProvider = new ISelectionProvider() { @Override public void addSelectionChangedListener(ISelectionChangedListener listener) { } @Override public ISelection getSelection() { return selection; } @Override public void removeSelectionChangedListener(ISelectionChangedListener listener) { } @Override public void setSelection(ISelection selection) { } }; // The popup extender needs a part to notify actions of the active part final WorkbenchWindow window = (WorkbenchWindow) PlatformUI.getWorkbench().getActiveWorkbenchWindow(); final IWorkbenchPage page = window.getActivePage(); IWorkbenchPart part = page.getActivePartReference().getPart(true); // Create a fake PopupMenuExtender so we can get some data back. final MenuManager fakeMenuManager = new MenuManager(); fakeMenuManager.add(new GroupMarker( org.eclipse.ui.IWorkbenchActionConstants.MB_ADDITIONS)); final PopupMenuExtender extender = new PopupMenuExtender(null, fakeMenuManager, selectionProvider, part, ((PartSite) part.getSite()).getContext()); /* * Pretend to show the pop-up menu -- looking to motivate the extender * to fill the menu based on the selection provider. * * TODO This causes a big delay (in the order of a minute or more) while * trying to fill this menu. It seems to be loading a bunch of plug-ins, * and doing class loading. */ extender.menuAboutToShow(fakeMenuManager); extender.dispose(); // Check to see if the appropriate object contributions are present. final IContributionItem[] items = fakeMenuManager.getItems(); Set seenCommands = new HashSet(Arrays.asList(commandIds)); List commands = new ArrayList(Arrays.asList(commandIds)); for (int i = 0; i < items.length; i++) { IContributionItem contributionItem = items[i]; // Step 1: test the selection if (selectionType != null) { IContributionItem item = contributionItem; if (item instanceof SubContributionItem) { item = ((SubContributionItem) contributionItem).getInnerItem(); } if (item instanceof PluginActionContributionItem) { // Verify that the selection passed to the action has been // converted ISelection s = null; if (s instanceof IStructuredSelection) { for (Iterator it = ((IStructuredSelection) s).iterator(); it.hasNext();) { Object element = it.next(); assertTrue(name + " selection not converted", selectionType.isInstance(element)); } } } } // Step 2: remember that we saw this element String id = contributionItem.getId(); if(existance) { boolean removed = commands.remove(id); if(seenCommands.contains(id) && ! removed) { fail(name + " item duplicated in the context menu: " + id); } } else { assertTrue(name + " item should not be in the context menu", ! commands.contains(id)); } } if(existance && ! commands.isEmpty()) { fail(name + " Missing " + commands.toString() + " from context menu."); } } }