diff options
author | Pawel Piech | 2009-09-10 22:26:24 +0000 |
---|---|---|
committer | Pawel Piech | 2009-09-10 22:26:24 +0000 |
commit | b5e7db3dad4fd30322b6cec01d8c1e2ab4bec533 (patch) | |
tree | ff8266b53f4c399c1eade9aa2050bb1aab1aff94 | |
parent | d019cb75c4a5a3ff01d6ade429cc010f8f55992c (diff) | |
download | eclipse.platform.debug-b5e7db3dad4fd30322b6cec01d8c1e2ab4bec533.tar.gz eclipse.platform.debug-b5e7db3dad4fd30322b6cec01d8c1e2ab4bec533.tar.xz eclipse.platform.debug-b5e7db3dad4fd30322b6cec01d8c1e2ab4bec533.zip |
Bug 289157 - Add flexible hierarchy viewer tests to the org.eclipse.debug.tests plugin
28 files changed, 2689 insertions, 3 deletions
diff --git a/org.eclipse.debug.tests/.classpath b/org.eclipse.debug.tests/.classpath new file mode 100644 index 000000000..64c5e31b7 --- /dev/null +++ b/org.eclipse.debug.tests/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/org.eclipse.debug.tests/.project b/org.eclipse.debug.tests/.project new file mode 100644 index 000000000..a6fb25e05 --- /dev/null +++ b/org.eclipse.debug.tests/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.debug.tests</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/org.eclipse.debug.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.debug.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..e233c29f2 --- /dev/null +++ b/org.eclipse.debug.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,99 @@ +#Thu Sep 10 14:55:24 PDT 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=disabled +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=ignore +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=error +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled +org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL,HIGH,HIGH +org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX,EXPERIMENTAL,CONTEXTLAUNCHING +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error diff --git a/org.eclipse.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.debug.tests/META-INF/MANIFEST.MF new file mode 100644 index 000000000..6a8765f01 --- /dev/null +++ b/org.eclipse.debug.tests/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.debug.tests;singleton:=true +Bundle-Version: 3.6.0.qualifier +Bundle-Activator: org.eclipse.debug.tests.TestsPlugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.debug.ui;bundle-version="3.6.0", + org.junit;bundle-version="3.8.2" +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-Vendor: %providerName diff --git a/org.eclipse.debug.tests/build.properties b/org.eclipse.debug.tests/build.properties new file mode 100644 index 000000000..34d2e4d2d --- /dev/null +++ b/org.eclipse.debug.tests/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/org.eclipse.debug.tests/plugin.properties b/org.eclipse.debug.tests/plugin.properties new file mode 100755 index 000000000..7db3e66ef --- /dev/null +++ b/org.eclipse.debug.tests/plugin.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2000, 2005 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 implementation +############################################################################### + +pluginName=Debug Test Plugin +providerName=Eclipse.org diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/CheckTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/CheckTests.java new file mode 100644 index 000000000..1d0816d3e --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/CheckTests.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import junit.framework.TestCase; + +import org.eclipe.debug.tests.viewer.model.TestModel.TestElement; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Tests which verify the check box support. This test is very similar to the + * content test except that the extending class should create a viewer with + * the SWT.CHECK style enabled. <br> + * Most of the check box verification is performed in the test model. + * + * @since 3.6 + */ +abstract public class CheckTests extends TestCase { + Display fDisplay; + Shell fShell; + ITreeModelViewer fViewer; + TestModelUpdatesListener fListener; + + public CheckTests(String name) { + super(name); + } + + /** + * @throws java.lang.Exception + */ + protected void setUp() throws Exception { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + + fViewer = createViewer(fDisplay, fShell); + + fListener = new TestModelUpdatesListener(false, false); + fViewer.addViewerUpdateListener(fListener); + fViewer.addLabelUpdateListener(fListener); + fViewer.addModelChangedListener(fListener); + + fShell.open (); + } + + abstract protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell); + + /** + * @throws java.lang.Exception + */ + protected void tearDown() throws Exception { + fViewer.removeLabelUpdateListener(fListener); + fViewer.removeViewerUpdateListener(fListener); + fViewer.removeModelChangedListener(fListener); + + // Close the shell and exit. + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + + public void testSimpleSingleLevel() { + // Create the model with test data + TestModel model = TestModel.simpleSingleLevel(); + + // Make sure that all elements are expanded + fViewer.setAutoExpandLevel(-1); + + // Create the agent which forces the tree to populate + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + // Create the listener which determines when the view is finished updating. + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the viewer input (and trigger updates). + fViewer.setInput(model.getRootElement()); + + // Wait for the updates to complete. + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + model.validateData(fViewer, TreePath.EMPTY); + } + + public void testSimpleMultiLevel() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleMultiLevel(); + fViewer.setAutoExpandLevel(-1); + + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + fViewer.setInput(model.getRootElement()); + + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + model.validateData(fViewer, TreePath.EMPTY); + } + + // TODO: no idea how to trigger a toggle event on an item +// public void testCheckReceiver() { +// // Initial setup +// TestModel model = TestModel.simpleSingleLevel(); +// fViewer.setAutoExpandLevel(-1); +// //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); +// fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); +// fViewer.setInput(model.getRootElement()); +// +// // Wait for the updates to complete and validate. +// while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); +// model.validateData(fViewer, TreePath.EMPTY); +// +// InternalTreeModelViewer treeViewer = ((InternalTreeModelViewer)fViewer); +// TreePath elementPath = model.findElement("1"); +// TestElement element = model.getElement(elementPath); +// boolean initialCheckState = element.getChecked(); +// Event event = new Event(); +// event.item = treeViewer.findItem(elementPath); +// event.detail = SWT.CHECK; +// event.display = fDisplay; +// event.type = SWT.Selection; +// event.widget = treeViewer.getControl(); +// fDisplay.post(event); +// +// while (fDisplay.readAndDispatch ()); +// +// Assert.assertTrue(element.getChecked() != initialCheckState); +// } + + public void testUpdateCheck() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + TestElement element = model.getRootElement().getChildren()[0]; + + TreePath elementPath = new TreePath(new Object[] { element }); + ModelDelta delta = model.setElementChecked(elementPath, false, false); + + fListener.reset(elementPath, element, -1, true, false); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.LABEL_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ContentTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ContentTests.java new file mode 100644 index 000000000..559940ebc --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/ContentTests.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import junit.framework.TestCase; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Tests that verify that the viewer property retrieves all the content + * from the model. + * + * @since 3.6 + */ +abstract public class ContentTests extends TestCase { + + Display fDisplay; + Shell fShell; + ITreeModelViewer fViewer; + TestModelUpdatesListener fListener; + + public ContentTests(String name) { + super(name); + } + + /** + * @throws java.lang.Exception + */ + protected void setUp() throws Exception { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + + fViewer = createViewer(fDisplay, fShell); + + fListener = new TestModelUpdatesListener(false, false); + fViewer.addViewerUpdateListener(fListener); + fViewer.addLabelUpdateListener(fListener); + fViewer.addModelChangedListener(fListener); + + fShell.open (); + } + + abstract protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell); + + /** + * @throws java.lang.Exception + */ + protected void tearDown() throws Exception { + fViewer.removeLabelUpdateListener(fListener); + fViewer.removeViewerUpdateListener(fListener); + fViewer.removeModelChangedListener(fListener); + + // Close the shell and exit. + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + + public void testSimpleSingleLevel() { + // Create the model with test data + TestModel model = TestModel.simpleSingleLevel(); + + // Make sure that all elements are expanded + fViewer.setAutoExpandLevel(-1); + + // Create the agent which forces the tree to populate + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + // Create the listener which determines when the view is finished updating. + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the viewer input (and trigger updates). + fViewer.setInput(model.getRootElement()); + + // Wait for the updates to complete. + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + model.validateData(fViewer, TreePath.EMPTY); + } + + public void testSimpleMultiLevel() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleMultiLevel(); + fViewer.setAutoExpandLevel(-1); + + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + fViewer.setInput(model.getRootElement()); + + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + model.validateData(fViewer, TreePath.EMPTY); + } + +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java new file mode 100644 index 000000000..87c326548 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/DeltaTests.java @@ -0,0 +1,308 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import java.util.Arrays; +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.eclipe.debug.tests.viewer.model.TestModel.TestElement; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Tests to verify that the viewer property retrieves and processes the + * model deltas generated by the test model. + */ +abstract public class DeltaTests extends TestCase { + Display fDisplay; + Shell fShell; + ITreeModelViewer fViewer; + TestModelUpdatesListener fListener; + + public DeltaTests(String name) { + super(name); + } + + /** + * @throws java.lang.Exception + */ + protected void setUp() throws Exception { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + + fViewer = createViewer(fDisplay, fShell); + + fListener = new TestModelUpdatesListener(false, false); + fViewer.addViewerUpdateListener(fListener); + fViewer.addLabelUpdateListener(fListener); + fViewer.addModelChangedListener(fListener); + + fShell.open (); + } + + abstract protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell); + + /** + * @throws java.lang.Exception + */ + protected void tearDown() throws Exception { + fViewer.removeLabelUpdateListener(fListener); + fViewer.removeViewerUpdateListener(fListener); + fViewer.removeModelChangedListener(fListener); + + // Close the shell and exit. + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + + public void testUpdateLabel() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + TestElement element = model.getRootElement().getChildren()[0]; + TreePath elementPath = new TreePath(new Object[] { element }); + ModelDelta delta = model.appendElementLabel(elementPath, "-modified"); + + fListener.reset(elementPath, element, -1, true, false); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.LABEL_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + public void testRefreshStruct() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + TestElement element = model.getRootElement().getChildren()[0]; + TreePath elementPath = new TreePath(new Object[] { element }); + TestElement[] newChildren = new TestElement[] { + model.new TestElement("1.1", new TestElement[0]), + model.new TestElement("1.2", new TestElement[0]), + model.new TestElement("1.3", new TestElement[0]), + }; + ModelDelta delta = model.setElementChildren(elementPath, newChildren); + + fListener.reset(elementPath, element, -1, true, false); + model.postDelta(delta); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + public void testInsertElement() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + TestElement element = model.new TestElement("7", new TestElement[0]); + TreePath elementPath = new TreePath(new Object[] { element }); + ModelDelta delta = model.insertElementChild(TreePath.EMPTY, 6, element); + + // Insert causes the update of element's data, label and children. + // TODO: update of element's data after insert seems redundant + // but it's probably not a big inefficiency + fListener.reset(); + fListener.addChildreUpdate(TreePath.EMPTY, 6); + fListener.addHasChildrenUpdate(elementPath); + fListener.addLabelUpdate(elementPath); + // TODO: redundant updates on insert! + fListener.setFailOnRedundantUpdates(false); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.ALL_UPDATES_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + public void testAddElement() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + TestElement element = model.new TestElement("7", new TestElement[0]); + TreePath elementPath = new TreePath(new Object[] { element }); + ModelDelta delta = model.addElementChild(TreePath.EMPTY, 6, element); + + // Add causes the update of parent child count and element's children. + fListener.reset(elementPath, element, -1, true, false); + fListener.addChildreUpdate(TreePath.EMPTY, 6); + // TODO: redundant updates on add! + fListener.setFailOnRedundantUpdates(false); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.ALL_UPDATES_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + + public void testRemoveElement() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + ModelDelta delta = model.removeElementChild(TreePath.EMPTY, 5); + + // Remove delta should generate no new updates, but we still need to wait for the event to + // be processed. + fListener.reset(); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + public void testExpandAndSelect() { + TestModel model = TestModel.simpleMultiLevel(); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), 1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY, true); + + // Create the delta + fListener.reset(); + // TODO Investigate: there seem to be unnecessary updates being issued + // by the viewer. These include the updates that are commented out: + // For now disable checking for extra updates. + fListener.setFailOnRedundantUpdates(false); + TestElement element = model.getRootElement(); + TreePath path_root = TreePath.EMPTY; + ModelDelta delta= new ModelDelta(model.getRootElement(), -1, IModelDelta.EXPAND, element.getChildren().length); + ModelDelta deltaRoot = delta; + element = element.getChildren()[2]; + TreePath path_root_3 = path_root.createChildPath(element); + delta = delta.addNode(element, 2, IModelDelta.EXPAND, element.fChildren.length); + fListener.addChildreUpdate(path_root_3, 0); + TreePath path_root_3_1 = path_root_3.createChildPath(element.getChildren()[0]); + fListener.addHasChildrenUpdate(path_root_3_1); + fListener.addLabelUpdate(path_root_3_1); + TreePath path_root_3_3 = path_root_3.createChildPath(element.getChildren()[2]); + fListener.addHasChildrenUpdate(path_root_3_3); + fListener.addLabelUpdate(path_root_3_3); + //TODO unnecessary update: fListener.addChildreUpdate(path1, 1); + fListener.addChildreUpdate(path_root_3, 2); + element = element.getChildren()[1]; + TreePath path_root_3_2 = path_root_3.createChildPath(element); + delta = delta.addNode(element, 1, IModelDelta.EXPAND, element.fChildren.length); + fListener.addLabelUpdate(path_root_3_2); + TreePath path_root_3_2_1 = path_root_3_2.createChildPath(element.getChildren()[0]); + fListener.addHasChildrenUpdate(path_root_3_2_1); + fListener.addLabelUpdate(path_root_3_2_1); + TreePath path_root_3_2_3 = path_root_3_2.createChildPath(element.getChildren()[2]); + fListener.addHasChildrenUpdate(path_root_3_2_3); + fListener.addLabelUpdate(path_root_3_2_3); + // TODO unnecessary update: fListener.addChildreCountUpdate(path2); + fListener.addChildreUpdate(path_root_3_2, 0); + // TODO unnecessary update: fListener.addChildreUpdate(path2, 1); + fListener.addChildreUpdate(path_root_3_2, 2); + element = element.getChildren()[1]; + TreePath path_root_3_2_2 = path_root_3_2.createChildPath(element); + delta = delta.addNode(element, 1, IModelDelta.SELECT, element.fChildren.length); + fListener.addLabelUpdate(path_root_3_2_2); + fListener.addHasChildrenUpdate(path_root_3_2_2); + + // Validate the expansion state BEFORE posting the delta. + + ITreeModelContentProviderTarget contentProviderViewer = (ITreeModelContentProviderTarget)fViewer; + Assert.assertFalse(contentProviderViewer.getExpandedState(path_root_3)); + Assert.assertFalse(contentProviderViewer.getExpandedState(path_root_3_2)); + Assert.assertFalse(contentProviderViewer.getExpandedState(path_root_3_2_2)); + + model.postDelta(deltaRoot); + while (!fListener.isFinished(TestModelUpdatesListener.ALL_UPDATES_COMPLETE | TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY, true); + + // Validate the expansion state AFTER posting the delta. + Assert.assertTrue(contentProviderViewer.getExpandedState(path_root_3)); + Assert.assertTrue(contentProviderViewer.getExpandedState(path_root_3_2)); + Assert.assertFalse(contentProviderViewer.getExpandedState(path_root_3_2_2)); + + // Verify selection + ISelection selection = fViewer.getSelection(); + if (selection instanceof ITreeSelection) { + List selectionPathsList = Arrays.asList( ((ITreeSelection)selection).getPaths() ); + Assert.assertTrue(selectionPathsList.contains(path_root_3_2_2)); + } else { + Assert.fail("Not a tree selection"); + } + } + + +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerCheckTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerCheckTests.java new file mode 100644 index 000000000..7cb15a0ee --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerCheckTests.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class JFaceViewerCheckTests extends CheckTests { + + public JFaceViewerCheckTests(String name) { + super(name); + } + + protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) { + return new TreeModelViewer(fShell, SWT.VIRTUAL | SWT.CHECK, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerContentTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerContentTests.java new file mode 100644 index 000000000..10213a3a3 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerContentTests.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class JFaceViewerContentTests extends ContentTests { + + public JFaceViewerContentTests(String name) { + super(name); + } + + protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) { + return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java new file mode 100644 index 000000000..f50a0587f --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerDeltaTests.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class JFaceViewerDeltaTests extends DeltaTests { + + public JFaceViewerDeltaTests(String name) { + super(name); + } + + protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) { + return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerSelectionTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerSelectionTests.java new file mode 100644 index 000000000..6cde1fbfc --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerSelectionTests.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class JFaceViewerSelectionTests extends SelectionTests { + + public JFaceViewerSelectionTests(String name) { + super(name); + } + + protected ITreeModelViewer createViewer(Display display, Shell shell) { + return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerStateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerStateTests.java new file mode 100644 index 000000000..a462f01d0 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerStateTests.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class JFaceViewerStateTests extends StateTests { + + public JFaceViewerStateTests(String name) { + super(name); + } + + protected ITreeModelViewer createViewer(Display display, Shell shell) { + return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerUpdateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerUpdateTests.java new file mode 100644 index 000000000..983b8d77f --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/JFaceViewerUpdateTests.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class JFaceViewerUpdateTests extends UpdateTests { + + public JFaceViewerUpdateTests(String name) { + super(name); + } + + protected ITreeModelViewer createViewer(Display display, Shell shell) { + return new TreeModelViewer(fShell, SWT.VIRTUAL, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/SelectionTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/SelectionTests.java new file mode 100644 index 000000000..aa1155466 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/SelectionTests.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Tests to verify that the viewer properly handles selection changes. + */ +abstract public class SelectionTests extends TestCase { + Display fDisplay; + Shell fShell; + ITreeModelViewer fViewer; + TestModelUpdatesListener fListener; + + public SelectionTests(String name) { + super(name); + } + + /** + * @throws java.lang.Exception + */ + protected void setUp() throws Exception { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + + fViewer = createViewer(fDisplay, fShell); + + fListener = new TestModelUpdatesListener(false, false); + fViewer.addViewerUpdateListener(fListener); + fViewer.addLabelUpdateListener(fListener); + fViewer.addModelChangedListener(fListener); + + fShell.open (); + } + + abstract protected ITreeModelViewer createViewer(Display display, Shell shell); + + /** + * @throws java.lang.Exception + */ + protected void tearDown() throws Exception { + fViewer.removeLabelUpdateListener(fListener); + fViewer.removeViewerUpdateListener(fListener); + fViewer.removeModelChangedListener(fListener); + + // Close the shell and exit. + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + + private static class SelectionListener implements ISelectionChangedListener { + private List fEvents = new ArrayList(1); + + public void selectionChanged(SelectionChangedEvent event) { + fEvents.add(event); + } + } + + private TestModel makeMultiLevelModel() { + TestModel model = TestModel.simpleMultiLevel(); + fViewer.setAutoExpandLevel(-1); + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + return model; + } + + /** + * In this test: + * - set selection to an element deep in the model + * - verify that selection chagned listener is called + * - verify that the selection is in the viewer is correct + */ + public void testSimpleSetSelection() { + // Create the model and populate the view. + TestModel model = makeMultiLevelModel(); + + // Create a selection object to the deepest part of the tree. + SelectionListener listener = new SelectionListener(); + fViewer.addSelectionChangedListener(listener); + + // Set the selection and verify that the listener is called. + TreeSelection selection = new TreeSelection(model.findElement("3.3.3")); + fViewer.setSelection(selection, true, false); + assertTrue(listener.fEvents.size() == 1); + + // Check that the new selection is what was requested. + ISelection viewerSelection = fViewer.getSelection(); + assertEquals(selection, viewerSelection); + } + + /** + * In this test: + * - set a seleciton to an element + * - then remove that element + * - update the view with remove delta + * -> The selection should be re-set to empty. + */ + public void testSelectRemove() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + // Create the model and populate the view. + TestModel model = makeMultiLevelModel(); + + // Create a selection object to the deepest part of the tree. + TreePath elementPath = model.findElement("3.3.3"); + TreeSelection selection = new TreeSelection(elementPath); + + // Set the selection. + fViewer.setSelection(selection, true, false); + + // Remove the element + TreePath removePath = model.findElement("3"); + TreePath parentPath = removePath.getParentPath(); + int removeIndex = model.getElement(parentPath).indexOf( model.getElement(removePath) ); + ModelDelta delta = model.removeElementChild(removePath.getParentPath(), removeIndex); + + // Configure a selection listener + SelectionListener listener = new SelectionListener(); + fViewer.addSelectionChangedListener(listener); + + // Reset the listener and update the viewer. With a remove + // delta only wait for the delta to be processed. + fListener.reset(); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + // Check to make sure the selection was made + //assertTrue(listener.fEvents.size() == 1); + + // Check that the new selection is empty + ISelection viewerSelection = fViewer.getSelection(); + assertTrue(viewerSelection.isEmpty()); + } + + + /** + * In this test: + * - set a selection to an element + * - then remove that element + * - then refresh the view. + * -> The selection should be re-set to empty. + */ + public void testSelectRemoveRefreshStruct() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + // Create the model and populate the view. + TestModel model = makeMultiLevelModel(); + + // Create a selection object to the deepest part of the tree. + TreePath elementPath = model.findElement("3.3.3"); + TreeSelection selection = new TreeSelection(elementPath); + + // Set the selection. + fViewer.setSelection(selection, true, false); + + // Remove the element + TreePath removePath = model.findElement("3"); + TreePath parentPath = removePath.getParentPath(); + int removeIndex = model.getElement(parentPath).indexOf( model.getElement(removePath) ); + model.removeElementChild(removePath.getParentPath(), removeIndex); + + // Configure a selection listener + SelectionListener listener = new SelectionListener(); + fViewer.addSelectionChangedListener(listener); + + // Reset the listener to ignore redundant updates. When elements are removed + // the viewer may still request updates for those elements. + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false); + + // Refresh the viewer + model.postDelta( new ModelDelta(model.getRootElement(), IModelDelta.CONTENT) ); + while (!fListener.isFinished(TestModelUpdatesListener.ALL_UPDATES_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + // Check to make sure the selection was made + // Commented out until JFace bug 219887 is fixed. + //assertTrue(listener.fEvents.size() == 1); + + // Check that the new selection is empty + ISelection viewerSelection = fViewer.getSelection(); + assertTrue(viewerSelection.isEmpty()); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java new file mode 100644 index 000000000..f98c77a40 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/StateTests.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.eclipe.debug.tests.viewer.model.TestModel.TestElement; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Tests to verify that the viewer can save and restore correctly the expansion + * state of elements. + * + * @since 3.6 + */ +abstract public class StateTests extends TestCase { + Display fDisplay; + Shell fShell; + ITreeModelViewer fViewer; + TestModelUpdatesListener fListener; + + public StateTests(String name) { + super(name); + } + + /** + * @throws java.lang.Exception + */ + protected void setUp() throws Exception { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + + fViewer = createViewer(fDisplay, fShell); + + fListener = new TestModelUpdatesListener(false, false); + fViewer.addViewerUpdateListener(fListener); + fViewer.addLabelUpdateListener(fListener); + fViewer.addModelChangedListener(fListener); + + fShell.open (); + } + + abstract protected ITreeModelViewer createViewer(Display display, Shell shell); + + /** + * @throws java.lang.Exception + */ + protected void tearDown() throws Exception { + fViewer.removeLabelUpdateListener(fListener); + fViewer.removeViewerUpdateListener(fListener); + fViewer.removeModelChangedListener(fListener); + + // Close the shell and exit. + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + + public void testUpdateViewer() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleMultiLevel(); + + // Create the listener + fListener.reset(); + fListener.addChildreUpdate(TreePath.EMPTY, 0); + fListener.addChildreUpdate(TreePath.EMPTY, 1); + fListener.addChildreUpdate(TreePath.EMPTY, 2); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY, true); + + // Create the update delta + TestElement element = model.getRootElement(); + TreePath path0 = TreePath.EMPTY; + ModelDelta delta = new ModelDelta(model.getRootElement(), -1, IModelDelta.EXPAND, element.getChildren().length); + ModelDelta updateDelta = delta; + element = element.getChildren()[2]; + TreePath path1 = path0.createChildPath(element); + delta = delta.addNode(element, 2, IModelDelta.EXPAND, element.fChildren.length); + element = element.getChildren()[1]; + TreePath path2 = path1.createChildPath(element); + delta = delta.addNode(element, 1, IModelDelta.EXPAND, element.fChildren.length); + element = element.getChildren()[1]; + TreePath path3 = path2.createChildPath(element); + delta = delta.addNode(element, 1, IModelDelta.SELECT); + + fListener.reset(); + fViewer.updateViewer(updateDelta); + + fListener.reset(); + fListener.setFailOnRedundantUpdates(false); + fListener.addChildreUpdate(path0, 2); + fListener.addHasChildrenUpdate(path1); + fListener.addChildreCountUpdate(path1); + fListener.addLabelUpdate(path1); + fListener.addChildreUpdate(path1, 1); + fListener.addHasChildrenUpdate(path2); + fListener.addChildreCountUpdate(path2); + fListener.addLabelUpdate(path2); + fListener.addHasChildrenUpdate(path2); + fListener.addChildreCountUpdate(path2); + fListener.addChildreUpdate(path2, 1); + fListener.addHasChildrenUpdate(path3); + fListener.addLabelUpdate(path3); + + while (!fListener.isFinished(TestModelUpdatesListener.CONTENT_UPDATES_COMPLETE | TestModelUpdatesListener.LABEL_UPDATES)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + // Extract the new state from viewer + ModelDelta savedDelta = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE); + fViewer.saveElementState(path0, savedDelta); + + Assert.assertTrue( deltaMatches(updateDelta, savedDelta) ); + } + + boolean deltaMatches(ModelDelta requested, ModelDelta received) { + if ( requested.getElement().equals(received.getElement()) && + requested.getFlags() == received.getFlags() && + ( requested.getChildCount() == -1 || requested.getChildCount() == received.getChildCount() )&& + ( requested.getIndex() == -1 || requested.getIndex() == received.getIndex()) && + ((requested.getReplacementElement() != null && requested.getReplacementElement().equals(received.getReplacementElement())) || + (requested.getReplacementElement() == null && received.getReplacementElement() == null)) && + requested.getChildDeltas().length == received.getChildDeltas().length) + { + for (int i = 0; i < requested.getChildDeltas().length; i++) { + ModelDelta requestedChildDelta = (ModelDelta)requested.getChildDeltas()[i]; + ModelDelta receivedChildDelta = received.getChildDelta(requestedChildDelta.getElement()); + if ( receivedChildDelta == null || !deltaMatches(requestedChildDelta, receivedChildDelta) ) { + return false; + } + } + return true; + } + return false; + } + +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java new file mode 100644 index 000000000..e84a35014 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModel.java @@ -0,0 +1,455 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import java.util.Arrays; + +import junit.framework.Assert; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy; +import org.eclipse.jface.viewers.TreePath; + +/** + * Test model for the use in unit tests. This test model contains a set of + * elements in a tree structure. It contains utility methods for modifying the + * model and for verifying that the viewer content matches the model. + * + * @since 3.6 + */ +public class TestModel implements IElementContentProvider, IElementLabelProvider, IModelProxyFactory /*, IElementCheckReceiver */ { + + public class TestElement extends PlatformObject { + private final String fID; + TestElement[] fChildren; + String fLabelAppendix = ""; + boolean fExpanded; + boolean fChecked; + boolean fGrayed; + + public TestElement(String text, TestElement[] children) { + this (text, false, false, children); + } + + public TestElement(String text, boolean checked, boolean grayed, TestElement[] children) { + fID = text; + fChildren = children; + fChecked = checked; + fGrayed = grayed; + } + + public Object getAdapter(Class adapter) { + if (adapter.isInstance(TestModel.this)) { + return TestModel.this; + } + return null; + } + + public void setLabelAppendix(String appendix) { + fLabelAppendix = appendix; + } + + public String getLabel() { + return fID + fLabelAppendix; + } + + public TestElement[] getChildren() { + return fChildren; + } + + public boolean isExpanded() { + return fExpanded; + } + + public boolean getGrayed() { + return fGrayed; + } + + public boolean getChecked() { + return fChecked; + } + + public void setChecked(boolean checked, boolean grayed) { + fChecked = checked; + fGrayed = grayed; + } + + public boolean equals(Object obj) { + return obj instanceof TestElement && fID.equals(((TestElement)obj).fID); + } + + public int hashCode() { + return fID.hashCode(); + } + + public String toString() { + return getLabel(); + } + + public int indexOf(TestElement child) { + return Arrays.asList(fChildren).indexOf(child); + } + } + + private class ModelProxy extends AbstractModelProxy {} + + private TestElement fRoot; + private ModelProxy fModelProxy; + + /** + * Constructor private. Use static factory methods instead. + */ + private TestModel() {} + + public TestElement getRootElement() { + return fRoot; + } + + public int getModelDepth() { + return getDepth(getRootElement(), 0); + } + + private int getDepth(TestElement element, int atDepth) { + TestElement[] children = element.getChildren(); + if (children.length == 0) { + return atDepth; + } + int depth = atDepth + 1; + for (int i = 0; i < children.length; i++) { + depth = Math.max(depth, getDepth(children[i], atDepth + 1)); + } + + return depth; + } + + public void update(IHasChildrenUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + TestElement element = (TestElement)updates[i].getElement(); + updates[i].setHasChilren(element.getChildren().length > 0); + updates[i].done(); + } + } + + public void update(IChildrenCountUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + TestElement element = (TestElement)updates[i].getElement(); + updates[i].setChildCount(element.getChildren().length); + updates[i].done(); + } + } + + public void update(IChildrenUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + TestElement element = (TestElement)updates[i].getElement(); + int endOffset = updates[i].getOffset() + updates[i].getLength(); + for (int j = updates[i].getOffset(); j < endOffset; j++) { + if (j < element.getChildren().length) { + updates[i].setChild(element.getChildren()[j], j); + } + } + updates[i].done(); + } + } + + public void update(ILabelUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + TestElement element = (TestElement)updates[i].getElement(); + updates[i].setLabel(element.fID, 0); +// TODO: wait for bug 286310 +// if (updates[i] instanceof ICheckUpdate && +// Boolean.TRUE.equals(updates[i].getPresentationContext().getProperty(ICheckUpdate.PROP_CHECK))) +// { +// ((ICheckUpdate)updates[i]).setChecked(element.getChecked(), element.getGrayed()); +// } + updates[i].done(); + } + } + + public void elementChecked(IPresentationContext context, Object viewerInput, TreePath path, boolean checked) { + TestElement element = getElement(path); + Assert.assertFalse(element.getGrayed()); + element.setChecked(checked, false); + } + + public IModelProxy createModelProxy(Object element, IPresentationContext context) { + fModelProxy = new ModelProxy(); + return fModelProxy; + } + + public TestElement getElement(TreePath path) { + if (path.getSegmentCount() == 0) { + return getRootElement(); + } else { + return (TestElement)path.getLastSegment(); + } + } + + public void setAllExpanded() { + doSetExpanded(fRoot); + } + + private void doSetExpanded(TestElement element) { + element.fExpanded = true; + for (int i = 0; i < element.fChildren.length; i++) { + doSetExpanded(element.fChildren[i]); + } + } + + public void validateData(ITreeModelViewer viewer, TreePath path) { + + validateData(viewer, path, false); + } + + public void validateData(ITreeModelViewer _viewer, TreePath path, boolean expandedElementsOnly) { + ITreeModelContentProviderTarget viewer = (ITreeModelContentProviderTarget)_viewer; + TestElement element = getElement(path); +// TODO: wait for bug 286310 +// if ( Boolean.TRUE.equals(_viewer.getPresentationContext().getProperty(ICheckUpdate.PROP_CHECK)) ) { +// ITreeModelCheckProviderTarget checkTarget = (ITreeModelCheckProviderTarget)_viewer; +// Assert.assertEquals(element.getChecked(), checkTarget.getElementChecked(path)); +// Assert.assertEquals(element.getGrayed(), checkTarget.getElementGrayed(path)); +// } + + if (!expandedElementsOnly || path.getSegmentCount() == 0 || viewer.getExpandedState(path) ) { + TestElement[] children = element.getChildren(); + Assert.assertEquals(children.length, viewer.getChildCount(path)); + + for (int i = 0; i < children.length; i++) { + Assert.assertEquals(children[i], viewer.getChildElement(path, i)); + validateData(viewer, path.createChildPath(children[i]), expandedElementsOnly); + } + } + } + + private void setRoot(TestElement root) { + fRoot = root; + } + + public void postDelta(IModelDelta delta) { + fModelProxy.fireModelChanged(delta); + } + + private ModelDelta getElementDelta(ModelDelta baseDelta, TreePath path) { + TestElement element = getRootElement(); + ModelDelta delta = baseDelta; + + for (int i = 0; i < path.getSegmentCount(); i++) { + TestElement[] children = element.getChildren(); + delta.setChildCount(children.length); + Object segment = path.getSegment(i); + int j = 0; + for (j = 0; j < element.getChildren().length; j++) { + if (segment.equals(element.getChildren()[j])) { + element = element.getChildren()[j]; + delta = delta.addNode(element, j, IModelDelta.NO_CHANGE); + } + } + if (j == element.getChildren().length) { + throw new IllegalArgumentException("Invalid path"); + } + } + return delta; + + } + + public ModelDelta appendElementLabel(TreePath path, String labelAppendix) { + ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE); + TestElement element = getElement(path); + ModelDelta delta = getElementDelta(baseDelta, path); + element.setLabelAppendix(labelAppendix); + delta.setFlags(delta.getFlags() | IModelDelta.STATE); + + return baseDelta; + } + + public ModelDelta setElementChecked(TreePath path, boolean checked, boolean grayed) { + ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE); + TestElement element = getElement(path); + ModelDelta delta = getElementDelta(baseDelta, path); + element.setChecked(checked, grayed); + delta.setFlags(delta.getFlags() | IModelDelta.STATE); + + return baseDelta; + } + + public ModelDelta setElementChildren(TreePath path, TestElement[] children) { + ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE); + + // Find the parent element and generate the delta node for it. + TestElement element = getElement(path); + ModelDelta delta = getElementDelta(baseDelta, path); + + // Set the new children array + element.fChildren = children; + + // Add the delta flag and update the child count in the parent delta. + delta.setFlags(delta.getFlags() | IModelDelta.CONTENT); + delta.setChildCount(children.length); + + return baseDelta; + } + + public ModelDelta replaceElementChild(TreePath parentPath, int index, TestElement child) { + ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE); + + TestElement element = getElement(parentPath); + ModelDelta delta= getElementDelta(baseDelta, parentPath); + TestElement oldChild = element.fChildren[index]; + element.fChildren[index] = child; + delta.addNode(oldChild, child, IModelDelta.REPLACED); + // TODO: set replacement index!?! + + return baseDelta; + } + + public ModelDelta addElementChild(TreePath parentPath, int index, TestElement newChild) { + ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE); + + // Find the parent element and generate the delta node for it. + TestElement element = getElement(parentPath); + ModelDelta delta= getElementDelta(baseDelta, parentPath); + + // Add the new element + element.fChildren = doInsertElementInArray(element.fChildren, index, newChild); + + // Add the delta flag and update the child count in the parent delta. + delta.setChildCount(element.getChildren().length); + delta.addNode(newChild, IModelDelta.ADDED); + + return baseDelta; + } + + public ModelDelta insertElementChild(TreePath parentPath, int index, TestElement newChild) { + ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE); + + // Find the parent element and generate the delta node for it. + TestElement element = getElement(parentPath); + ModelDelta delta= getElementDelta(baseDelta, parentPath); + + // Add the new element + element.fChildren = doInsertElementInArray(element.fChildren, index, newChild); + + // Add the delta flag and update the child count in the parent delta. + delta.setChildCount(element.getChildren().length); + delta.addNode(newChild, index, IModelDelta.INSERTED); + + return baseDelta; + } + + private TestElement[] doInsertElementInArray(TestElement[] children, int index, TestElement newChild) { + // Create the new children array add the element to it and set it to + // the parent. + TestElement[] newChildren = new TestElement[children.length + 1]; + System.arraycopy(children, 0, newChildren, 0, index); + newChildren[index] = newChild; + System.arraycopy(children, index, newChildren, index + 1, children.length - index); + return newChildren; + } + + public ModelDelta removeElementChild(TreePath parentPath, int index) { + ModelDelta baseDelta = new ModelDelta(getRootElement(), IModelDelta.NO_CHANGE); + + // Find the parent element and generate the delta node for it. + TestElement element = getElement(parentPath); + ModelDelta delta= getElementDelta(baseDelta, parentPath); + + // Create a new child array with the element removed + TestElement[] children = element.getChildren(); + TestElement childToRemove = children[index]; + TestElement[] newChildren = new TestElement[children.length - 1]; + System.arraycopy(children, 0, newChildren, 0, index); + System.arraycopy(children, index + 1, newChildren, index, children.length - index - 1); + element.fChildren = newChildren; + + // Add the delta flag and update the child count in the parent delta. + delta.setChildCount(element.getChildren().length); + delta.addNode(childToRemove, index, IModelDelta.REMOVED); + + return baseDelta; + } + + public TreePath findElement(String label) { + return findElement(TreePath.EMPTY, label); + } + + public TreePath findElement(TreePath startPath, String label) { + TestElement element = getElement(startPath); + for (int i = 0; i < element.getChildren().length; i++) { + TestElement child = element.getChildren()[i]; + TreePath path = startPath.createChildPath(child); + if ( label.equals(child.getLabel()) ) { + return path; + } else { + TreePath subPath = findElement(path, label); + if (subPath != null) { + return subPath; + } + } + } + return null; + } + + public static TestModel simpleSingleLevel() { + TestModel model = new TestModel(); + model.setRoot( model.new TestElement("root", new TestElement[] { + model.new TestElement("1", true, true, new TestElement[0]), + model.new TestElement("2", true, false, new TestElement[0]), + model.new TestElement("3", false, true, new TestElement[0]), + model.new TestElement("4", false, false, new TestElement[0]), + model.new TestElement("5", new TestElement[0]), + model.new TestElement("6", new TestElement[0]) + }) ); + return model; + } + + public static TestModel simpleMultiLevel() { + TestModel model = new TestModel(); + model.setRoot( model.new TestElement("root", new TestElement[] { + model.new TestElement("1", new TestElement[0]), + model.new TestElement("2", true, false, new TestElement[] { + model.new TestElement("2.1", true, true, new TestElement[0]), + model.new TestElement("2.2", false, true, new TestElement[0]), + model.new TestElement("2.3", true, false, new TestElement[0]), + }), + model.new TestElement("3", new TestElement[] { + model.new TestElement("3.1", new TestElement[] { + model.new TestElement("3.1.1", new TestElement[0]), + model.new TestElement("3.1.2", new TestElement[0]), + model.new TestElement("3.1.3", new TestElement[0]), + }), + model.new TestElement("3.2", new TestElement[] { + model.new TestElement("3.2.1", new TestElement[0]), + model.new TestElement("3.2.2", new TestElement[0]), + model.new TestElement("3.2.3", new TestElement[0]), + }), + model.new TestElement("3.3", new TestElement[] { + model.new TestElement("3.3.1", new TestElement[0]), + model.new TestElement("3.3.2", new TestElement[0]), + model.new TestElement("3.3.3", new TestElement[0]), + }), + }) + }) ); + return model; + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java new file mode 100644 index 000000000..d0995fe2a --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TestModelUpdatesListener.java @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import junit.framework.Assert; + +import org.eclipe.debug.tests.viewer.model.TestModel.TestElement; +import org.eclipse.debug.internal.ui.viewers.model.ILabelUpdateListener; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener; +import org.eclipse.jface.viewers.TreePath; + +public class TestModelUpdatesListener implements IViewerUpdateListener, ILabelUpdateListener, IModelChangedListener { + + public static final int LABEL_UPDATES_COMPLETE = 0X0001; + public static final int CONTENT_UPDATES_COMPLETE = 0X0002; + public static final int LABEL_UPDATES = 0X0004; + public static final int HAS_CHILDREN_UPDATES = 0X0008; + public static final int CHILDREN_COUNT_UPDATES = 0X0010; + public static final int CHILDREN_UPDATES = 0X0020; + public static final int MODEL_CHANGED_COMPLETE = 0X0040; + + public static final int LABEL_COMPLETE = LABEL_UPDATES_COMPLETE | LABEL_UPDATES; + public static final int CONTENT_COMPLETE = + CONTENT_UPDATES_COMPLETE | HAS_CHILDREN_UPDATES | CHILDREN_COUNT_UPDATES | CHILDREN_UPDATES; + + + public static final int ALL_UPDATES_COMPLETE = LABEL_COMPLETE | CONTENT_COMPLETE; + + private boolean fFailOnRedundantUpdates; + private boolean fFailOnMultipleUpdateSequences; + + private Set fHasChildrenUpdates = new HashSet(); + private Map fChildrenUpdates = new HashMap(); + private Set fChildCountUpdates = new HashSet(); + private Set fLabelUpdates = new HashSet(); + private boolean fViewerUpdatesComplete; + private boolean fLabelUpdatesComplete; + private boolean fModelChangedComplete; + + public TestModelUpdatesListener(boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) { + setFailOnRedundantUpdates(failOnRedundantUpdates); + setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences); + } + + public void setFailOnRedundantUpdates(boolean failOnRedundantUpdates) { + fFailOnRedundantUpdates = failOnRedundantUpdates; + } + + public void setFailOnMultipleUpdateSequences(boolean failOnMultipleUpdateSequences) { + fFailOnMultipleUpdateSequences = failOnMultipleUpdateSequences; + } + + + public void reset(TreePath path, TestElement element, int levels, boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) { + reset(); + addUpdates(path, element, levels); + setFailOnRedundantUpdates(failOnRedundantUpdates); + setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences); + } + + public void reset() { + fHasChildrenUpdates.clear(); + fChildrenUpdates.clear(); + fChildCountUpdates.clear(); + fLabelUpdates.clear(); + fViewerUpdatesComplete = false; + fLabelUpdatesComplete = false; + fModelChangedComplete = false; + } + + public void addHasChildrenUpdate(TreePath path) { + fHasChildrenUpdates.add(path); + } + + public void removeHasChildrenUpdate(TreePath path) { + fHasChildrenUpdates.remove(path); + } + + public void addChildreCountUpdate(TreePath path) { + fChildCountUpdates.add(path); + } + + public void removeChildreCountUpdate(TreePath path) { + fChildCountUpdates.remove(path); + } + + public void addChildreUpdate(TreePath path, int index) { + Set childrenIndexes = (Set)fChildrenUpdates.get(path); + if (childrenIndexes == null) { + childrenIndexes = new HashSet(1); + fChildrenUpdates.put(path, childrenIndexes); + } + childrenIndexes.add(new Integer(index)); + } + + public void recurseremoveChildreUpdate(TreePath path, int index) { + Set childrenIndexes = (Set)fChildrenUpdates.get(path); + if (childrenIndexes != null) { + childrenIndexes.remove(new Integer(index)); + if (childrenIndexes.isEmpty()) { + fChildrenUpdates.remove(path); + } + } + } + + public void addLabelUpdate(TreePath path) { + fLabelUpdates.add(path); + } + + public void removeLabelUpdate(TreePath path) { + fLabelUpdates.remove(path); + } + + public void addUpdates(TreePath path, TestElement element, int levels) { + TestElement[] children = element.getChildren(); + + if (!path.equals(TreePath.EMPTY)) { + fLabelUpdates.add(path); + fHasChildrenUpdates.add(path); + } + + if (levels != 0) { + levels--; + if (children.length > 0) { + fChildCountUpdates.add(path); + Set childrenIndexes = new HashSet(); + for (int i = 0; i < children.length; i++) { + childrenIndexes.add(new Integer(i)); + } + fChildrenUpdates.put(path, childrenIndexes); + } + + for (int i = 0; i < children.length; i++) { + addUpdates(path.createChildPath(children[i]), children[i], levels); + } + } + } + + public boolean isFinished() { + return isFinished(ALL_UPDATES_COMPLETE); + } + + public boolean isFinished(int flags) { + if ( (flags & LABEL_UPDATES_COMPLETE) != 0) { + if (!fLabelUpdatesComplete) return false; + } + if ( (flags & LABEL_UPDATES) != 0) { + if (!fLabelUpdates.isEmpty()) return false; + } + if ( (flags & CONTENT_UPDATES_COMPLETE) != 0) { + if (!fViewerUpdatesComplete) return false; + } + if ( (flags & HAS_CHILDREN_UPDATES) != 0) { + if (!fHasChildrenUpdates.isEmpty()) return false; + } + if ( (flags & CHILDREN_COUNT_UPDATES) != 0) { + if (!fChildCountUpdates.isEmpty()) return false; + } + if ( (flags & CHILDREN_UPDATES) != 0) { + if (!fChildrenUpdates.isEmpty()) return false; + } + if ( (flags & MODEL_CHANGED_COMPLETE) != 0) { + if (!fModelChangedComplete) return false; + } + return true; + } + + public void updateStarted(IViewerUpdate update) { + System.out.println("started: " + update); + + } + + public void updateComplete(IViewerUpdate update) { + if (!update.isCanceled()) { + if (update instanceof IHasChildrenUpdate) { + if (!fHasChildrenUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) { + Assert.fail("Redundant update: " + update); + } + } if (update instanceof IChildrenCountUpdate) { + if (!fChildCountUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) { + Assert.fail("Redundant update: " + update); + } + } else if (update instanceof IChildrenUpdate) { + int start = ((IChildrenUpdate)update).getOffset(); + int end = start + ((IChildrenUpdate)update).getLength(); + + Set childrenIndexes = (Set)fChildrenUpdates.get(update.getElementPath()); + if (childrenIndexes != null) { + for (int i = start; i < end; i++) { + childrenIndexes.remove(new Integer(i)); + } + if (childrenIndexes.isEmpty()) { + fChildrenUpdates.remove(update.getElementPath()); + } + } else if (fFailOnRedundantUpdates) { + Assert.fail("Redundant update: " + update); + } + } + } + } + + public void viewerUpdatesBegin() { + + } + + public void viewerUpdatesComplete() { + if (fFailOnMultipleUpdateSequences && fViewerUpdatesComplete) { + Assert.fail("Multiple viewer update sequences detected"); + } + fViewerUpdatesComplete = true; + } + + public void labelUpdateComplete(ILabelUpdate update) { + if (!fLabelUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) { + Assert.fail("Redundant update: " + update); + } + } + + public void labelUpdateStarted(ILabelUpdate update) { + System.out.println("started: " + update); + } + + public void labelUpdatesBegin() { + } + + public void labelUpdatesComplete() { + if (fFailOnMultipleUpdateSequences && fLabelUpdatesComplete) { + Assert.fail("Multiple label update sequences detected"); + } + fLabelUpdatesComplete = true; + } + + public void modelChanged(IModelDelta delta, IModelProxy proxy) { + if (fFailOnMultipleUpdateSequences && fModelChangedComplete) { + Assert.fail("Multiple model changed sequences detected"); + } + fModelChangedComplete = true; + } +} + + diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TreeModelViewerAutopopulateAgent.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TreeModelViewerAutopopulateAgent.java new file mode 100644 index 000000000..2600fbebb --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/TreeModelViewerAutopopulateAgent.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import java.util.LinkedList; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener; +import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; +import org.eclipse.jface.viewers.ILazyTreePathContentProvider; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.swt.widgets.Widget; + +/** + * + */ +public class TreeModelViewerAutopopulateAgent implements IViewerUpdateListener { + + private TreeModelViewer fViewer; + + + public TreeModelViewerAutopopulateAgent(TreeModelViewer viewer) { + fViewer = viewer; + fViewer.addViewerUpdateListener(this); + } + + public void updateComplete(IViewerUpdate update) { + if (update instanceof IChildrenCountUpdate) { + TreePath path = update.getElementPath(); + ILazyTreePathContentProvider contentProvider = (ILazyTreePathContentProvider) fViewer.getContentProvider(); + + Widget[] items = fViewer.testFindItems(update.getElement()); + for (int i = 0; i < items.length; i++) { + if ( path.equals(getTreePath(items[i])) ) { + int itemCount = getItemChildCount(items[i]); + for (int j = 0; j < itemCount; j++) { + contentProvider.updateElement(path, j); + } + } + } + } + } + + public void updateStarted(IViewerUpdate update) { + // TODO Auto-generated method stub + + } + + public void viewerUpdatesBegin() { + // TODO Auto-generated method stub + + } + + public void viewerUpdatesComplete() { + // TODO Auto-generated method stub + + } + + private TreePath getTreePath(Widget w) { + if (w instanceof TreeItem) { + TreeItem item = (TreeItem)w; + LinkedList segments = new LinkedList(); + while (item != null) { + Object segment = item.getData(); + Assert.isNotNull(segment); + segments.addFirst(segment); + item = item.getParentItem(); + } + return new TreePath(segments.toArray()); + } + return TreePath.EMPTY; + } + + private int getItemChildCount(Widget w) { + if (w instanceof Tree) { + return ((Tree)w).getItemCount(); + } else if (w instanceof TreeItem) { + return ((TreeItem)w).getItemCount(); + } + return 0; + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java new file mode 100644 index 000000000..5bc65f6bb --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/UpdateTests.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import junit.framework.TestCase; + +import org.eclipe.debug.tests.viewer.model.TestModel.TestElement; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Tests to verify that the viewer property updates following changes in the + * model, following simple content update deltas from the model. + * + * @since 3.6 + */ +abstract public class UpdateTests extends TestCase { + Display fDisplay; + Shell fShell; + ITreeModelViewer fViewer; + TestModelUpdatesListener fListener; + + public UpdateTests(String name) { + super(name); + } + + /** + * @throws java.lang.Exception + */ + protected void setUp() throws Exception { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + + fViewer = createViewer(fDisplay, fShell); + + fListener = new TestModelUpdatesListener(false, false); + fViewer.addViewerUpdateListener(fListener); + fViewer.addLabelUpdateListener(fListener); + fViewer.addModelChangedListener(fListener); + + fShell.open (); + } + + abstract protected ITreeModelViewer createViewer(Display display, Shell shell); + + /** + * @throws java.lang.Exception + */ + protected void tearDown() throws Exception { + fViewer.removeLabelUpdateListener(fListener); + fViewer.removeViewerUpdateListener(fListener); + fViewer.removeModelChangedListener(fListener); + + // Close the shell and exit. + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + + /** + * This test: + * - creates a simple model + * - replaces the list of elements with a shorter list of elements + * - refreshes the viewer + */ + public void testRemoveElements() { + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + TestElement root = model.getRootElement(); + TreePath rootPath = new TreePath(new Object[] {}); + TestElement[] newElements = new TestElement[] { + model.new TestElement("1", new TestElement[0]), + model.new TestElement("2", new TestElement[0]), + model.new TestElement("3", new TestElement[0]), + }; + model.setElementChildren(rootPath, newElements); + + // Reset the listener to NOT fail on redundant updates. + // When elements are remvoed from the model and the model is + // refreshed the viewer will issue an IChildrenUpdate for the + // missing elements as an optimization. + fListener.reset(rootPath, root, -1, false, false); + + model.postDelta(new ModelDelta(root, IModelDelta.CONTENT)); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + /** + * This test: + * - creates a simple model + * - sets a list of children to one of the elements + * - refreshes the viewer + */ + public void testAddNewChildren() { + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, true, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + TestElement element = model.getRootElement().getChildren()[0]; + TreePath elementPath = new TreePath(new Object[] { element }); + TestElement[] newChildren = new TestElement[] { + model.new TestElement("1.1", new TestElement[0]), + model.new TestElement("1.2", new TestElement[0]), + model.new TestElement("1.3", new TestElement[0]), + }; + model.setElementChildren(elementPath, newChildren); + + // Reset the viewer to ignore redundant updates. The '1' element + // will be updated for "hasChildren" before it is expanded, which is + // expected. + TreePath rootPath = TreePath.EMPTY; + TestElement rootElement = model.getRootElement(); + fListener.reset(rootPath, rootElement, -1, false, false); + + // Refresh the viewer + model.postDelta(new ModelDelta(rootElement, IModelDelta.CONTENT)); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + + private void removeElement(TestModel model, int index) { + ModelDelta delta = model.removeElementChild(TreePath.EMPTY, index); + + // Remove delta should generate no new updates, but we still need to wait for the event to + // be processed. + fListener.reset(); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.MODEL_CHANGED_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + private void addElement(TestModel model, String label, int position) { + ModelDelta delta = model.addElementChild(TreePath.EMPTY, position, model.new TestElement(label, new TestElement[0])); + + // Remove delta should generate no new updates, but we still need to wait for the event to + // be processed. + fListener.reset(); + model.postDelta(delta); + while (!fListener.isFinished(TestModelUpdatesListener.MODEL_CHANGED_COMPLETE | TestModelUpdatesListener.CONTENT_UPDATES_COMPLETE | TestModelUpdatesListener.LABEL_UPDATES_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + } + + public void testRepeatedAddRemoveElement() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleSingleLevel(); + fViewer.setAutoExpandLevel(-1); + + // Create the listener + fListener.reset(TreePath.EMPTY, model.getRootElement(), -1, false, false); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + model.validateData(fViewer, TreePath.EMPTY); + + // Update the model + removeElement(model, 2); + addElement(model, "3-new", 3); + removeElement(model, 4); + addElement(model, "5-new", 5); + removeElement(model, 1); + addElement(model, "1-new", 1); + removeElement(model, 3); + addElement(model, "4-new", 4); + } + +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerDeltaTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerDeltaTests.java new file mode 100644 index 000000000..f3101784f --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerDeltaTests.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelContentProviderTarget; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class VirtualViewerDeltaTests extends DeltaTests { + + public VirtualViewerDeltaTests(String name) { + super(name); + } + + protected ITreeModelContentProviderTarget createViewer(Display display, Shell shell) { + return new VirtualTreeModelViewer(fDisplay, 0, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java new file mode 100644 index 000000000..720723164 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerLazyModeTests.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.eclipe.debug.tests.viewer.model.TestModel.TestElement; +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Tests which verify the operation of the virtual viewer in the lazy mode. + * + * @since 3.6 + */ +public class VirtualViewerLazyModeTests extends TestCase { + Display fDisplay; + Shell fShell; + ITreeModelViewer fViewer; + TestModelUpdatesListener fListener; + + public VirtualViewerLazyModeTests(String name) { + super(name); + } + + /** + * @throws java.lang.Exception + */ + protected void setUp() throws Exception { + fDisplay = PlatformUI.getWorkbench().getDisplay(); + fShell = new Shell(fDisplay/*, SWT.ON_TOP | SWT.SHELL_TRIM*/); + fShell.setMaximized(true); + fShell.setLayout(new FillLayout()); + + fViewer = createViewer(fDisplay, fShell); + + fListener = new TestModelUpdatesListener(false, false); + fViewer.addViewerUpdateListener(fListener); + fViewer.addLabelUpdateListener(fListener); + fViewer.addModelChangedListener(fListener); + + fShell.open (); + } + + protected ITreeModelViewer createViewer(Display display, Shell shell) { + return new VirtualTreeModelViewer(fDisplay, SWT.VIRTUAL, new PresentationContext("TestViewer")); + } + + /** + * @throws java.lang.Exception + */ + protected void tearDown() throws Exception { + fViewer.removeLabelUpdateListener(fListener); + fViewer.removeViewerUpdateListener(fListener); + fViewer.removeModelChangedListener(fListener); + + // Close the shell and exit. + fShell.close(); + while (!fShell.isDisposed()) if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + } + + public void testUpdateViewer() { + //TreeModelViewerAutopopulateAgent autopopulateAgent = new TreeModelViewerAutopopulateAgent(fViewer); + + TestModel model = TestModel.simpleMultiLevel(); + + // Initialize the listener. In lazy mode, until a selection + // is made, only the root element count should be updated. + fListener.reset(); + fListener.addChildreCountUpdate(TreePath.EMPTY); + + // Set the input into the view and update the view. + fViewer.setInput(model.getRootElement()); + while (!fListener.isFinished(TestModelUpdatesListener.CONTENT_UPDATES_COMPLETE)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + // Do not try to validate data, because the virtual viewer contains only + // a subset of model. + + // Create the update delta + TestElement element = model.getRootElement(); + TreePath path0 = TreePath.EMPTY; + ModelDelta delta = new ModelDelta(model.getRootElement(), -1, IModelDelta.EXPAND, element.getChildren().length); + ModelDelta updateDelta = delta; + element = element.getChildren()[2]; + TreePath path1 = path0.createChildPath(element); + delta = delta.addNode(element, 2, IModelDelta.EXPAND, element.fChildren.length); + element = element.getChildren()[1]; + TreePath path2 = path1.createChildPath(element); + delta = delta.addNode(element, 1, IModelDelta.EXPAND, element.fChildren.length); + element = element.getChildren()[1]; + TreePath path3 = path2.createChildPath(element); + delta = delta.addNode(element, 1, IModelDelta.SELECT); + + fViewer.updateViewer(updateDelta); + + // Viewer should update data and labels of items in selection + fListener.reset(); + fListener.addChildreUpdate(path0, 2); + fListener.addHasChildrenUpdate(path1); + fListener.addChildreCountUpdate(path1); + fListener.addLabelUpdate(path1); + fListener.addChildreUpdate(path1, 1); + fListener.addHasChildrenUpdate(path2); + fListener.addChildreCountUpdate(path2); + fListener.addLabelUpdate(path2); + fListener.addHasChildrenUpdate(path2); + fListener.addChildreCountUpdate(path2); + fListener.addChildreUpdate(path2, 1); + fListener.addHasChildrenUpdate(path3); + fListener.addLabelUpdate(path3); + + // When processing expand and select deltas, the label may be requested + // multiple times for the same element. So we have to set the fail for + // redundant updates to false. + fListener.setFailOnRedundantUpdates(false); + + while (!fListener.isFinished(TestModelUpdatesListener.CONTENT_UPDATES_COMPLETE | TestModelUpdatesListener.LABEL_UPDATES)) + if (!fDisplay.readAndDispatch ()) fDisplay.sleep (); + + // Extract the new state from viewer + ModelDelta savedDelta = new ModelDelta(model.getRootElement(), IModelDelta.NO_CHANGE); + fViewer.saveElementState(path0, savedDelta); + + Assert.assertTrue( deltaMatches(updateDelta, savedDelta) ); + } + + boolean deltaMatches(ModelDelta requested, ModelDelta received) { + if ( requested.getElement().equals(received.getElement()) && + requested.getFlags() == received.getFlags() && + ( requested.getChildCount() == -1 || requested.getChildCount() == received.getChildCount() )&& + ( requested.getIndex() == -1 || requested.getIndex() == received.getIndex()) && + ((requested.getReplacementElement() != null && requested.getReplacementElement().equals(received.getReplacementElement())) || + (requested.getReplacementElement() == null && received.getReplacementElement() == null)) && + requested.getChildDeltas().length == received.getChildDeltas().length) + { + for (int i = 0; i < requested.getChildDeltas().length; i++) { + ModelDelta requestedChildDelta = (ModelDelta)requested.getChildDeltas()[i]; + ModelDelta receivedChildDelta = (ModelDelta)received.getChildDelta(requestedChildDelta.getElement()); + if ( receivedChildDelta == null || !deltaMatches(requestedChildDelta, receivedChildDelta) ) { + return false; + } + } + return true; + } + return false; + } + +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerSelectionTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerSelectionTests.java new file mode 100644 index 000000000..e716acf03 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerSelectionTests.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class VirtualViewerSelectionTests extends SelectionTests { + + public VirtualViewerSelectionTests(String name) { + super(name); + } + + protected ITreeModelViewer createViewer(Display display, Shell shell) { + return new VirtualTreeModelViewer(fDisplay, 0, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerStateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerStateTests.java new file mode 100644 index 000000000..5a4e4d671 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerStateTests.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class VirtualViewerStateTests extends StateTests { + + public VirtualViewerStateTests(String name) { + super(name); + } + + protected ITreeModelViewer createViewer(Display display, Shell shell) { + return new VirtualTreeModelViewer(fDisplay, 0, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerUpdateTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerUpdateTests.java new file mode 100644 index 000000000..507be5192 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/viewer/model/VirtualViewerUpdateTests.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipe.debug.tests.viewer.model; + +import org.eclipse.debug.internal.ui.viewers.model.ITreeModelViewer; +import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualTreeModelViewer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * @since 3.6 + */ +public class VirtualViewerUpdateTests extends UpdateTests { + + public VirtualViewerUpdateTests(String name) { + super(name); + } + + protected ITreeModelViewer createViewer(Display display, Shell shell) { + return new VirtualTreeModelViewer(fDisplay, 0, new PresentationContext("TestViewer")); + } +} diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/TestsPlugin.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/TestsPlugin.java new file mode 100644 index 000000000..d237abed8 --- /dev/null +++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/TestsPlugin.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.tests; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + * + * @since 3.6 + */ +public class TestsPlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.debug.tests"; //$NON-NLS-1$ + + // The shared instance + private static TestsPlugin plugin; + + /** + * The constructor + */ + public TestsPlugin() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static TestsPlugin getDefault() { + return plugin; + } + +} diff --git a/org.eclipse.debug.ui/META-INF/MANIFEST.MF b/org.eclipse.debug.ui/META-INF/MANIFEST.MF index e3a1fa8bf..97ec5f420 100644 --- a/org.eclipse.debug.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.debug.ui/META-INF/MANIFEST.MF @@ -29,13 +29,14 @@ Export-Package: org.eclipse.debug.internal.ui;x-internal:=true, org.eclipse.debug.internal.ui.stringsubstitution;x-internal:=true, org.eclipse.debug.internal.ui.viewers;x-internal:=true, org.eclipse.debug.internal.ui.viewers.breadcrumb;x-internal:=true, - org.eclipse.debug.internal.ui.viewers.model;x-internal:=true, + org.eclipse.debug.internal.ui.viewers.model;x-friends:="org.eclipse.debug.tests", org.eclipse.debug.internal.ui.viewers.model.provisional; x-friends:="org.eclipse.debug.examples.ui, org.eclipse.jdt.debug.ui, org.eclipse.cdt.dsf.ui, - org.eclipse.cdt.dsf.gdb.ui", - org.eclipse.debug.internal.ui.viewers.provisional;x-internal:=true, + org.eclipse.cdt.dsf.gdb.ui, + org.eclipse.debug.tests", + org.eclipse.debug.internal.ui.viewers.provisional;x-friends:="org.eclipse.debug.tests", org.eclipse.debug.internal.ui.viewers.update;x-internal:=true, org.eclipse.debug.internal.ui.views;x-internal:=true, org.eclipse.debug.internal.ui.views.breakpoints;x-internal:=true, |