blob: 2af175165fc807046c60c5f787280d23398fc191 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ui.leaktest;
import org.eclipse.jdt.testplugin.util.DisplayHelper;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.jdt.ui.leaktest.reftracker.ReferenceTracker;
import org.eclipse.jdt.ui.leaktest.reftracker.ReferenceVisitor;
import org.eclipse.jdt.ui.leaktest.reftracker.ReferencedObject;
import junit.framework.TestCase;
/**
* Base class for leak test cases.
*/
public class LeakTestCase extends TestCase {
public class MulipleCollectorVisitor extends ReferenceVisitor {
private ReferenceVisitor[] fVisitors;
public MulipleCollectorVisitor(ReferenceVisitor[] visitors) {
fVisitors= visitors;
}
@Override
public boolean visit(ReferencedObject object, Class<?> clazz, boolean firstVisit) {
boolean visitChildren= false;
for (int i= 0; i < fVisitors.length; i++) {
boolean res= fVisitors[i].visit(object, clazz, firstVisit);
visitChildren |= res;
}
return visitChildren;
}
}
public LeakTestCase(String name) {
super(name);
}
private InstancesOfTypeCollector collect(String requestedTypeName) {
InstancesOfTypeCollector requestor= new InstancesOfTypeCollector(requestedTypeName, false);
calmDown();
new ReferenceTracker(requestor).start(getClass().getClassLoader());
return requestor;
}
private InstancesOfTypeCollector[] collect(String[] requestedTypeNames) {
final InstancesOfTypeCollector[] requestors= new InstancesOfTypeCollector[requestedTypeNames.length];
for (int i= 0; i < requestors.length; i++) {
requestors[i]= new InstancesOfTypeCollector(requestedTypeNames[i], false);
}
calmDown();
ReferenceVisitor visitor= new ReferenceVisitor() {
@Override
public boolean visit(ReferencedObject object, Class<?> clazz, boolean firstVisit) {
for (int i= 0; i < requestors.length; i++) {
requestors[i].visit(object, clazz, firstVisit);
}
return true;
}
};
new ReferenceTracker(visitor).start(getClass().getClassLoader());
return requestors;
}
/*
* @see junit.framework.TestCase#setUp()
* @since 3.4
*/
@Override
protected void setUp() throws Exception {
super.setUp();
// Ensure active page to allow test being run
IWorkbenchWindow activeWindow= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (activeWindow.getActivePage() == null) {
activeWindow.openPage(null);
}
}
private void calmDown() {
// Make sure we wait > 500, to allow e.g. TextViewer.queuePostSelectionChanged(boolean)
// and OpenStrategy to time out and release references in delayed runnables.
new DisplayHelper() {
@Override
protected boolean condition() {
return false;
}
}.waitForCondition(Display.getCurrent(), 1000);
for (int i= 0; i < 10; i++) {
System.gc();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
}
/**
* Asserts that the instance count of the given class is as expected.
*
* @param clazz the class of the instances to count
* @param expected the expected instance count
*/
public void assertInstanceCount(final Class<?> clazz, final int expected) {
int numTries= 2;
while (true) {
InstancesOfTypeCollector requestor= collect(clazz.getName());
int actual= requestor.getNumberOfResults();
if (expected == actual) {
return;
}
numTries--;
if (numTries == 0) {
assertTrue("Expected instance count: " + expected + ", actual: " + actual + "\n" + requestor.getResultString(), false);
}
}
}
/**
* Asserts that the instance count of the given class is as expected.
*
* @param classNames the types names of the instances to count
* @param expected the expected instance count
*/
public void assertInstanceCount(final String[] classNames, final int[] expected) {
int numTries= 2;
while (true) {
InstancesOfTypeCollector[] requestors= collect(classNames);
boolean success= true;
for (int k= 0; success && k < requestors.length; k++) {
if (expected[k] != requestors[k].getNumberOfResults()) {
success= false;
}
}
if (success)
return;
numTries--;
if (numTries == 0) {
StringBuffer buf= new StringBuffer();
for (int k= 0; k < requestors.length; k++) {
int actual= requestors[k].getNumberOfResults();
if (expected[k] != actual) {
buf.append("Expected instance count: " + expected[k] + ", actual: " + actual + "\n" + requestors[k].getResultString()).append("\n---------------------\n");
}
}
assertTrue(buf.toString(), false);
}
}
}
/**
* Returns the number of instances of a given class that are live (not garbage).
* @param clazz The class of the instances to count
* @return Returns the current number of instances of the given class or <code>-1</code> if
* no connection is established.
*/
protected int getInstanceCount(Class<?> clazz) {
InstancesOfTypeCollector requestor= collect(clazz.getName());
return requestor.getNumberOfResults();
}
/**
* Assert that two counts are different. The method does not fail if the profile connection has
* not established (e.g. because profiling is not supported on the given platform).
*
* @param startCount the start count
* @param endCount the end count
*/
protected void assertDifferentCount(int startCount, int endCount) {
assertDifferentCount(null, startCount, endCount);
}
/**
* Assert that two counts are different. The method does not fail if the profile connection has
* not established (e.g. because profiling is not supported on the given platform)
*
* @param message Message to be printed if the test fails.
*
* @param startCount the start count
* @param endCount the end count
*/
protected void assertDifferentCount(String message, int startCount, int endCount) {
if (startCount == endCount) {
String str= message != null ? message + ": " : "";
assertTrue(str + "instance count is not different: (" + startCount + " / " + endCount + " )", false);
}
}
/**
* Assert that two counts are equal. The method does not fail if the profile connection has not
* established (e.g. because profiling is not supported on the given platform).
*
* @param startCount the start count
* @param endCount the end count
*/
protected void assertEqualCount(int startCount, int endCount) {
assertEqualCount(null, startCount, endCount);
}
/**
* Assert that two counts are equal. The method does not fail if the profile connection has not
* established (e.g. because profiling is not supported on the given platform).
*
* @param message Message to be printed if the test fails.
* @param startCount the start count
* @param endCount the end count
*/
protected void assertEqualCount(String message, int startCount, int endCount) {
if (startCount != endCount) {
// only compare if connection could be established
String str= message != null ? message + ": " : "";
assertTrue(str + "instance count is not the same: (" + startCount + " / " + endCount + " )", false);
}
}
}