blob: ea8e094c1e7f6977563d8b5463d75276744f6f8d [file] [log] [blame]
/*******************************************************************************
* 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.Iterator;
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.ITreeModelContentProviderTarget;
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.IStateUpdateListener;
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, ITestModelUpdatesListenerConstants,
IStateUpdateListener
{
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 Set fProxyModels = new HashSet();
private Set fStateUpdates = new HashSet();
private boolean fViewerUpdatesComplete;
private boolean fLabelUpdatesComplete;
private boolean fModelChangedComplete;
private boolean fStateSaveComplete;
private boolean fStateRestoreComplete;
private int fViewerUpdatesRunning;
private int fLabelUpdatesRunning;
private int fTimeoutInterval = 60000;
private long fTimeoutTime;
public TestModelUpdatesListener(boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) {
setFailOnRedundantUpdates(failOnRedundantUpdates);
setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences);
}
public void setFailOnRedundantUpdates(boolean failOnRedundantUpdates) {
fFailOnRedundantUpdates = failOnRedundantUpdates;
}
public void setFailOnMultipleUpdateSequences(boolean failOnMultipleUpdateSequences) {
fFailOnMultipleUpdateSequences = failOnMultipleUpdateSequences;
}
/**
* Sets the the maximum amount of time (in milliseconds) that the update listener
* is going to wait. If set to -1, the listener will wait indefinitely.
*/
public void setTimeoutInterval(int milis) {
fTimeoutInterval = milis;
}
public void reset(TreePath path, TestElement element, int levels, boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) {
reset();
addUpdates(path, element, levels);
addProxies(element);
setFailOnRedundantUpdates(failOnRedundantUpdates);
setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences);
}
public void reset(boolean failOnRedundantUpdates, boolean failOnMultipleUpdateSequences) {
reset();
setFailOnRedundantUpdates(failOnRedundantUpdates);
setFailOnMultipleUpdateSequences(failOnMultipleUpdateSequences);
}
public void reset() {
fHasChildrenUpdates.clear();
fChildrenUpdates.clear();
fChildCountUpdates.clear();
fLabelUpdates.clear();
fProxyModels.clear();
fViewerUpdatesComplete = false;
fLabelUpdatesComplete = false;
fModelChangedComplete = false;
fStateSaveComplete = false;
fStateRestoreComplete = false;
fTimeoutTime = System.currentTimeMillis() + fTimeoutInterval;
}
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 removeChildrenUpdate(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) {
addUpdates(path, element, levels, ALL_UPDATES_COMPLETE);
}
public void addStateUpdates(ITreeModelContentProviderTarget viewer, TreePath path, TestElement element) {
addUpdates(viewer, path, element, -1, STATE_UPDATES);
}
public void addUpdates(TreePath path, TestElement element, int levels, int flags) {
addUpdates(null, path, element, levels, flags);
}
public void addUpdates(ITreeModelContentProviderTarget viewer, TreePath path, TestElement element, int levels, int flags) {
if (!path.equals(TreePath.EMPTY)) {
if ((flags & LABEL_UPDATES) != 0) {
fLabelUpdates.add(path);
}
if ((flags & HAS_CHILDREN_UPDATES) != 0) {
fHasChildrenUpdates.add(path);
}
}
if (levels-- != 0) {
TestElement[] children = element.getChildren();
if (children.length > 0 && (viewer == null || path.getSegmentCount() == 0 || viewer.getExpandedState(path))) {
if ((flags & CHILDREN_COUNT_UPDATES) != 0) {
fChildCountUpdates.add(path);
}
if ((flags & CHILDREN_UPDATES) != 0) {
Set childrenIndexes = new HashSet();
for (int i = 0; i < children.length; i++) {
childrenIndexes.add(new Integer(i));
}
fChildrenUpdates.put(path, childrenIndexes);
}
if ((flags & STATE_UPDATES) != 0 && viewer != null) {
fStateUpdates.add(path);
}
for (int i = 0; i < children.length; i++) {
addUpdates(viewer, path.createChildPath(children[i]), children[i], levels, flags);
}
}
}
}
private void addProxies(TestElement element) {
TestModel model = element.getModel();
if (model.getModelProxy() == null) {
fProxyModels.add(element.getModel());
}
TestElement[] children = element.getChildren();
for (int i = 0; i < children.length; i++) {
addProxies(children[i]);
}
}
public boolean isFinished() {
return isFinished(ALL_UPDATES_COMPLETE);
}
public boolean isFinished(int flags) {
if (fTimeoutInterval > 0 && fTimeoutTime < System.currentTimeMillis()) {
throw new RuntimeException("Test timed out");
}
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;
}
if ( (flags & STATE_SAVE_COMPLETE) != 0) {
if (!fStateSaveComplete) return false;
}
if ( (flags & STATE_RESTORE_COMPLETE) != 0) {
if (!fStateRestoreComplete) return false;
}
if ( (flags & MODEL_PROXIES_INSTALLED) != 0) {
if (fProxyModels.size() != 0) return false;
}
if ( (flags & VIEWER_UPDATES_RUNNING) != 0) {
if (fViewerUpdatesRunning != 0) {
return false;
}
}
if ( (flags & LABEL_UPDATES_RUNNING) != 0) {
if (fLabelUpdatesRunning != 0) {
return false;
}
}
return true;
}
public void updateStarted(IViewerUpdate update) {
synchronized (this) {
fViewerUpdatesRunning++;
}
}
public void updateComplete(IViewerUpdate update) {
synchronized (this) {
fViewerUpdatesRunning--;
}
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) {
synchronized (this) {
fLabelUpdatesRunning--;
}
if (!fLabelUpdates.remove(update.getElementPath()) && fFailOnRedundantUpdates) {
Assert.fail("Redundant update: " + update);
}
}
public void labelUpdateStarted(ILabelUpdate update) {
synchronized (this) {
fLabelUpdatesRunning++;
}
}
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;
for (Iterator itr = fProxyModels.iterator(); itr.hasNext();) {
TestModel model = (TestModel)itr.next();
if (model.getModelProxy() == proxy) {
itr.remove();
break;
}
}
}
public void stateRestoreUpdatesBegin(Object input) {
}
public void stateRestoreUpdatesComplete(Object input) {
fStateRestoreComplete = true;
}
public void stateSaveUpdatesBegin(Object input) {
}
public void stateSaveUpdatesComplete(Object input) {
fStateSaveComplete = true;
}
public void stateUpdateComplete(Object input, IViewerUpdate update) {
}
public void stateUpdateStarted(Object input, IViewerUpdate update) {
}
}