001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.tests.performance;
011:
012: import java.io.ByteArrayInputStream;
013: import java.util.ArrayList;
014: import java.util.Arrays;
015: import java.util.HashSet;
016: import java.util.Iterator;
017: import java.util.List;
018: import java.util.Set;
019:
020: import org.eclipse.core.resources.IFile;
021: import org.eclipse.core.resources.IProject;
022: import org.eclipse.core.resources.IResource;
023: import org.eclipse.core.resources.IWorkspace;
024: import org.eclipse.core.resources.ResourcesPlugin;
025: import org.eclipse.core.resources.mapping.ResourceMapping;
026: import org.eclipse.core.runtime.CoreException;
027: import org.eclipse.jface.action.GroupMarker;
028: import org.eclipse.jface.action.IContributionItem;
029: import org.eclipse.jface.action.MenuManager;
030: import org.eclipse.jface.action.SubContributionItem;
031: import org.eclipse.jface.viewers.ISelection;
032: import org.eclipse.jface.viewers.ISelectionChangedListener;
033: import org.eclipse.jface.viewers.ISelectionProvider;
034: import org.eclipse.jface.viewers.IStructuredSelection;
035: import org.eclipse.jface.viewers.StructuredSelection;
036: import org.eclipse.ui.IWorkbenchPage;
037: import org.eclipse.ui.IWorkbenchPart;
038: import org.eclipse.ui.PlatformUI;
039: import org.eclipse.ui.internal.PluginActionContributionItem;
040: import org.eclipse.ui.internal.PopupMenuExtender;
041: import org.eclipse.ui.internal.WorkbenchWindow;
042: import org.eclipse.ui.tests.harness.util.UITestCase;
043: import org.eclipse.ui.tests.performance.ObjectContributionClasses.ICommon;
044:
045: /**
046: * Tests that object contributions are enabled and shown correctly in pop-up
047: * menus depending on the state of the workbench. This test relies on the
048: * <code>plugin.xml</code> file containing certain values. Please see the
049: * appropriate section in that file for more information about the initial
050: * set-up.
051: *
052: * @since 3.0
053: */
054: public final class ObjectContributionTest extends UITestCase {
055:
056: /**
057: * Constructs a new instance of <code>ObjectContributionTest</code> with
058: * the name of the test.
059: *
060: * @param name
061: * The name of the test; may be <code>null</code>.
062: */
063: public ObjectContributionTest(final String name) {
064: super (name);
065: }
066:
067: /**
068: * Tests whether the content-type object contribution works. This is testing
069: * a use care familiar to Ant UI. The content-type scans an XML file to see
070: * if its root element is <code><project></code>.
071: *
072: * @throws CoreException
073: * If a problem occurs when creating the project or file, or if
074: * the project can't be opened.
075: */
076: public final void testObjectStateContentType() throws CoreException {
077: // Create an XML file with <project> as its root element.
078: final IWorkspace workspace = ResourcesPlugin.getWorkspace();
079: final IProject testProject = workspace.getRoot().getProject(
080: "ObjectContributionTestProject");
081: testProject.create(null);
082: testProject.open(null);
083: final IFile xmlFile = testProject
084: .getFile("ObjectContributionTest.xml");
085: final String contents = "<testObjectStateContentTypeElement></testObjectStateContentTypeElement>";
086: final ByteArrayInputStream inputStream = new ByteArrayInputStream(
087: contents.getBytes());
088: xmlFile.create(inputStream, true, null);
089: final ISelection selection = new StructuredSelection(xmlFile);
090: assertPopupMenus(
091: "1",
092: new String[] { "org.eclipse.ui.tests.testObjectStateContentType" },
093: selection, null, true);
094: }
095:
096: /**
097: * This tests backwards compatibility support for adaptable IResource objectContributions. This
098: * allows IResource adaptable contributions without an adapter factory and using
099: * the IContributorResourceAdapter factory. In addition, test the ResourceMapping adaptations.
100: *
101: * @since 3.1
102: */
103: public final void testContributorResourceAdapter()
104: throws CoreException {
105:
106: final IWorkspace workspace = ResourcesPlugin.getWorkspace();
107: final IProject testProject = workspace.getRoot().getProject(
108: ObjectContributionClasses.PROJECT_NAME);
109: if (!testProject.exists()) {
110: testProject.create(null);
111: }
112: if (!testProject.isOpen()) {
113: testProject.open(null);
114: }
115:
116: assertPopupMenus(
117: "1",
118: new String[] { "IResource.1" },
119: new StructuredSelection(
120: new Object[] { new ObjectContributionClasses.CResource() }),
121: IResource.class, true);
122: assertPopupMenus(
123: "2",
124: new String[] { "IProject.1" },
125: new StructuredSelection(
126: new Object[] { new ObjectContributionClasses.CFile() }),
127: null, false);
128: assertPopupMenus(
129: "3",
130: new String[] { "IFile.1" },
131: new StructuredSelection(
132: new Object[] { new ObjectContributionClasses.CFile() }),
133: IFile.class, true);
134: assertPopupMenus("4", new String[] { "IResource.1" },
135: new StructuredSelection(new Object[] {
136: new ObjectContributionClasses.CFile(),
137: new ObjectContributionClasses.CResource() }),
138: IResource.class, true);
139: assertPopupMenus("5", new String[] { "IFile.1", "IProject.1" },
140: new StructuredSelection(new Object[] {
141: new ObjectContributionClasses.CFile(),
142: new ObjectContributionClasses.CResource() }),
143: IResource.class, false);
144: assertPopupMenus("6", new String[] { "ResourceMapping.1" },
145: new StructuredSelection(new Object[] {
146: new ObjectContributionClasses.CFile(),
147: new ObjectContributionClasses.CResource() }),
148: ResourceMapping.class, true);
149: assertPopupMenus(
150: "7",
151: new String[] { "ResourceMapping.1", "IResource.1" },
152: new StructuredSelection(
153: new Object[] { new ObjectContributionClasses.ModelElement() }),
154: ResourceMapping.class, true);
155: // Ensure that the case where an object uses a contribution adapter that doesn't handle mappings
156: // will still show the menus for resource mappings
157: assertPopupMenus(
158: "8",
159: new String[] { "ResourceMapping.1", "IResource.1" },
160: new StructuredSelection(
161: new Object[] { new ObjectContributionClasses.CResourceOnly() }),
162: ResourceMapping.class, true);
163: }
164:
165: /**
166: * This tests adaptable contributions that are not IResource.
167: *
168: * @since 3.1
169: */
170: public final void testAdaptables() {
171: assertPopupMenus(
172: "1",
173: new String[] { "ICommon.1" },
174: new StructuredSelection(
175: new Object[] { new ObjectContributionClasses.A() }),
176: ICommon.class, true);
177: assertPopupMenus("2", new String[] { "ICommon.1" },
178: new StructuredSelection(new Object[] {
179: new ObjectContributionClasses.A(),
180: new ObjectContributionClasses.B() }),
181: ICommon.class, true);
182: assertPopupMenus("3", new String[] { "ICommon.1" },
183: new StructuredSelection(new Object[] {
184: new ObjectContributionClasses.A(),
185: new ObjectContributionClasses.B(),
186: new ObjectContributionClasses.C(),
187: new ObjectContributionClasses.Common() }),
188: ICommon.class, true);
189: assertPopupMenus("4", new String[] { "ICommon.1" },
190: new StructuredSelection(new Object[] {
191: new ObjectContributionClasses.Common(),
192: new ObjectContributionClasses.C(),
193: new ObjectContributionClasses.B(),
194: new ObjectContributionClasses.A() }),
195: ICommon.class, true);
196: assertPopupMenus("5", new String[] { "ICommon.1" },
197: new StructuredSelection(new Object[] {
198: new ObjectContributionClasses.Common(),
199: new ObjectContributionClasses.C(),
200: new ObjectContributionClasses.B(),
201: new ObjectContributionClasses.C(),
202: new ObjectContributionClasses.A(),
203: new ObjectContributionClasses.Common() }),
204: ICommon.class, true);
205: assertPopupMenus("6", new String[] { "ICommon.1" },
206: new StructuredSelection(new Object[] {
207: new ObjectContributionClasses.C(),
208: new ObjectContributionClasses.Common() }),
209: ICommon.class, true);
210: assertPopupMenus("7", new String[] { "ICommon.1" },
211: new StructuredSelection(new Object[] { new Object() }),
212: ICommon.class, false);
213: assertPopupMenus("8", new String[] { "ICommon.1" },
214: new StructuredSelection(
215: new Object[] {
216: new ObjectContributionClasses.C(),
217: new Object() }), ICommon.class, false);
218: assertPopupMenus("9", new String[] { "ICommon.1" },
219: new StructuredSelection(
220: new Object[] {
221: new ObjectContributionClasses.C(),
222: new ObjectContributionClasses.A(),
223: new Object() }), ICommon.class, false);
224: }
225:
226: /**
227: * Ensure that there are no duplicate contributions.
228: *
229: * @since 3.1
230: */
231: public final void testDuplicateAdaptables() {
232: assertPopupMenus(
233: "1",
234: new String[] { "ICommon.1" },
235: new StructuredSelection(
236: new Object[] { new ObjectContributionClasses.D() }),
237: ICommon.class, true);
238: // repeat test on purpose to ensure no double call duplicates.
239: assertPopupMenus(
240: "1",
241: new String[] { "ICommon.1" },
242: new StructuredSelection(
243: new Object[] { new ObjectContributionClasses.D() }),
244: ICommon.class, true);
245: assertPopupMenus("2", new String[] { "ICommon.1" },
246: new StructuredSelection(new Object[] {
247: new ObjectContributionClasses.D(),
248: new ObjectContributionClasses.A() }),
249: ICommon.class, true);
250: assertPopupMenus("3", new String[] { "ICommon.1" },
251: new StructuredSelection(new Object[] {
252: new ObjectContributionClasses.A(),
253: new ObjectContributionClasses.D() }),
254: ICommon.class, true);
255: assertPopupMenus("4", new String[] { "ICommon.1" },
256: new StructuredSelection(new Object[] {
257: new ObjectContributionClasses.Common(),
258: new ObjectContributionClasses.D() }),
259: ICommon.class, true);
260: assertPopupMenus("5", new String[] { "ICommon.1" },
261: new StructuredSelection(new Object[] {
262: new ObjectContributionClasses.D(),
263: new ObjectContributionClasses.Common() }),
264: ICommon.class, true);
265: }
266:
267: /**
268: * Test non-adaptable contributions
269: *
270: * @since 3.1
271: */
272: public final void testNonAdaptableContributions() {
273: assertPopupMenus("1", new String[] { "ICommon.2" },
274: new StructuredSelection(new Object[] {
275: new ObjectContributionClasses.A(),
276: new ObjectContributionClasses.B() }),
277: ICommon.class, false);
278: assertPopupMenus("2", new String[] { "ICommon.2" },
279: new StructuredSelection(new Object[] {
280: new ObjectContributionClasses.D(),
281: new ObjectContributionClasses.C(),
282: new ObjectContributionClasses.Common() }),
283: ICommon.class, true);
284: assertPopupMenus("3", new String[] { "Common.2" },
285: new StructuredSelection(new Object[] {
286: new ObjectContributionClasses.D(),
287: new ObjectContributionClasses.C(),
288: new ObjectContributionClasses.A() }),
289: ICommon.class, false);
290: assertPopupMenus("4", new String[] { "Common.2" },
291: new StructuredSelection(new Object[] {
292: new ObjectContributionClasses.B(),
293: new ObjectContributionClasses.C(),
294: new ObjectContributionClasses.A() }),
295: ICommon.class, false);
296: }
297:
298: /**
299: * Helper class that will create a popup menu based on the given selection and
300: * then ensure that the provided commandIds are added to the menu.
301: *
302: * @param commandIds the command ids that should appear in the menu
303: * @param selection the selection on which to contribute object contributions
304: */
305: public void assertPopupMenus(String name, String[] commandIds,
306: final ISelection selection, Class selectionType,
307: boolean existance) {
308: ISelectionProvider selectionProvider = new ISelectionProvider() {
309: public void addSelectionChangedListener(
310: ISelectionChangedListener listener) {
311: }
312:
313: public ISelection getSelection() {
314: return selection;
315: }
316:
317: public void removeSelectionChangedListener(
318: ISelectionChangedListener listener) {
319: }
320:
321: public void setSelection(ISelection selection) {
322: }
323: };
324:
325: // The popup extender needs a part to notify actions of the active part
326: final WorkbenchWindow window = (WorkbenchWindow) PlatformUI
327: .getWorkbench().getActiveWorkbenchWindow();
328: final IWorkbenchPage page = window.getActivePage();
329: IWorkbenchPart part = page.getActivePartReference().getPart(
330: true);
331:
332: // Create a fake PopupMenuExtender so we can get some data back.
333: final MenuManager fakeMenuManager = new MenuManager();
334: fakeMenuManager.add(new GroupMarker(
335: org.eclipse.ui.IWorkbenchActionConstants.MB_ADDITIONS));
336: final PopupMenuExtender extender = new PopupMenuExtender(null,
337: fakeMenuManager, selectionProvider, part);
338:
339: /*
340: * Pretend to show the pop-up menu -- looking to motivate the extender
341: * to fill the menu based on the selection provider.
342: *
343: * TODO This causes a big delay (in the order of a minute or more) while
344: * trying to fill this menu. It seems to be loading a bunch of plug-ins,
345: * and doing class loading.
346: */
347: extender.menuAboutToShow(fakeMenuManager);
348:
349: extender.dispose();
350:
351: // Check to see if the appropriate object contributions are present.
352: final IContributionItem[] items = fakeMenuManager.getItems();
353: Set seenCommands = new HashSet(Arrays.asList(commandIds));
354: List commands = new ArrayList(Arrays.asList(commandIds));
355: for (int i = 0; i < items.length; i++) {
356: IContributionItem contributionItem = items[i];
357: // Step 1: test the selection
358: if (selectionType != null) {
359: IContributionItem item = contributionItem;
360: if (item instanceof SubContributionItem) {
361: item = ((SubContributionItem) contributionItem)
362: .getInnerItem();
363: }
364: if (item instanceof PluginActionContributionItem) {
365: // Verify that the selection passed to the action has been
366: // converted
367: ISelection s = null;
368: if (s instanceof IStructuredSelection) {
369: for (Iterator it = ((IStructuredSelection) s)
370: .iterator(); it.hasNext();) {
371: Object element = it.next();
372: assertTrue(name
373: + " selection not converted",
374: selectionType.isInstance(element));
375: }
376: }
377: }
378: }
379: // Step 2: remember that we saw this element
380: String id = contributionItem.getId();
381: if (existance) {
382: boolean removed = commands.remove(id);
383: if (seenCommands.contains(id) && !removed) {
384: fail(name
385: + " item duplicated in the context menu: "
386: + id);
387: }
388: } else {
389: assertTrue(name
390: + " item should not be in the context menu",
391: !commands.contains(id));
392: }
393: }
394:
395: if (existance && !commands.isEmpty()) {
396: fail(name + " Missing " + commands.toString()
397: + " from context menu.");
398: }
399: }
400: }
|