/*==========================================================================*\
| $Id$
|*-------------------------------------------------------------------------*|
| Copyright (C) 2006-2009 Virginia Tech
|
| This file is part of Web-CAT Eclipse Plugins.
|
| Web-CAT is free software; you can redistribute it and/or modify
| it under the terms of the GNU General Public License as published by
| the Free Software Foundation; either version 2 of the License, or
| (at your option) any later version.
|
| Web-CAT is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with Web-CAT; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/
package net.sf.webcat.eclipse.cxxtest.ui;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Vector;
import net.sf.webcat.eclipse.cxxtest.CxxTestPlugin;
import net.sf.webcat.eclipse.cxxtest.i18n.Messages;
import net.sf.webcat.eclipse.cxxtest.model.ICxxTestAssertion;
import net.sf.webcat.eclipse.cxxtest.model.ICxxTestBase;
import net.sf.webcat.eclipse.cxxtest.model.ICxxTestMethod;
import net.sf.webcat.eclipse.cxxtest.model.ICxxTestStackFrame;
import net.sf.webcat.eclipse.cxxtest.model.ICxxTestSuite;
import net.sf.webcat.eclipse.cxxtest.model.ICxxTestSuiteChild;
import net.sf.webcat.eclipse.cxxtest.model.ICxxTestSuiteError;
import net.sf.webcat.eclipse.cxxtest.model.IDerefereeSummary;
import net.sf.webcat.eclipse.cxxtest.model.IDerefereeLeak;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;
/**
* The view part that represents the CxxTest view in the Eclipse IDE. This
* view displays the results of the CxxTest execution and flags any tests
* that failed.
*
* Influenced greatly by the same JUnit class.
*
* @author Tony Allevato (Virginia Tech Computer Science)
* @author latest changes by: $Author$
* @version $Revision$ $Date$
*/
public class TestRunnerViewPart extends ViewPart
{
private class DetailsContentProvider implements ITreeContentProvider
{
public Object[] getElements(Object inputElement)
{
if(inputElement == null)
{
return new Object[0];
}
else if(inputElement instanceof IDerefereeSummary)
{
IDerefereeSummary info = (IDerefereeSummary)inputElement;
String[] array = new String[7];
array[0] = MessageFormat.format(
Messages.TestRunnerViewPart_TotalBytesAllocated,
info.getTotalBytesAllocated());
array[1] = MessageFormat.format(
Messages.TestRunnerViewPart_MaximumBytesInUse,
info.getMaxBytesInUse());
array[2] = MessageFormat.format(
Messages.TestRunnerViewPart_CallsToNew,
info.getCallsToNew());
array[3] = MessageFormat.format(
Messages.TestRunnerViewPart_CallsToDeleteNonNull,
info.getCallsToDelete());
array[4] = MessageFormat.format(
Messages.TestRunnerViewPart_CallsToArrayNew,
info.getCallsToArrayNew());
array[5] = MessageFormat.format(
Messages.TestRunnerViewPart_CallsToArrayDeleteNonNull,
info.getCallsToArrayDelete());
array[6] = MessageFormat.format(
Messages.TestRunnerViewPart_CallsToDeleteNull,
info.getCallsToDeleteNull());
return array;
}
else
{
return (Object[])inputElement;
}
}
public void dispose() { }
public void inputChanged(
Viewer viewer, Object oldInput, Object newInput) { }
public Object[] getChildren(Object parentElement)
{
if(parentElement instanceof ICxxTestAssertion)
{
ICxxTestAssertion cta = (ICxxTestAssertion)parentElement;
return cta.getStackTrace();
}
else if(parentElement instanceof ICxxTestSuiteError)
{
ICxxTestSuiteError cta = (ICxxTestSuiteError)parentElement;
return cta.getStackTrace();
}
else if(parentElement instanceof IDerefereeLeak)
{
IDerefereeLeak mwl = (IDerefereeLeak)parentElement;
return mwl.getStackTrace();
}
else
{
return null;
}
}
public Object getParent(Object element)
{
return null;
}
public boolean hasChildren(Object element)
{
if(element instanceof ICxxTestAssertion)
{
ICxxTestAssertion cta = (ICxxTestAssertion)element;
return cta.getStackTrace() != null;
}
else if(element instanceof ICxxTestSuiteError)
{
ICxxTestSuiteError cta = (ICxxTestSuiteError)element;
return cta.getStackTrace() != null;
}
else if(element instanceof IDerefereeLeak)
{
IDerefereeLeak leak = (IDerefereeLeak)element;
return leak.getStackTrace() != null;
}
else
return false;
}
}
private class DetailsLabelProvider extends LabelProvider
{
public String getText(Object element)
{
if(element instanceof ICxxTestAssertion)
{
ICxxTestAssertion assertion = (ICxxTestAssertion)element;
return assertion.getMessage(true);
}
else if(element instanceof ICxxTestSuiteError)
{
ICxxTestSuiteError assertion = (ICxxTestSuiteError)element;
return assertion.getMessage();
}
else if(element instanceof IDerefereeLeak)
{
IDerefereeLeak leak = (IDerefereeLeak)element;
if(leak.getStackTrace() != null && leak.getStackTrace().length > 0)
{
return leak.toString() +
Messages.TestRunnerViewPart_AllocatedUsingSuffix;
}
else
{
return leak.toString();
}
}
else if(element instanceof ICxxTestStackFrame)
{
ICxxTestStackFrame ste = (ICxxTestStackFrame)element;
return ste.toString();
}
else
{
return element.toString();
}
}
public Image getImage(Object element)
{
if(element instanceof ICxxTestAssertion ||
element instanceof ICxxTestSuiteError)
{
ICxxTestBase test = (ICxxTestBase)element;
switch(test.getStatus())
{
case ICxxTestBase.STATUS_OK:
return assertTraceIcon;
case ICxxTestBase.STATUS_WARNING:
return assertWarnIcon;
case ICxxTestBase.STATUS_FAILED:
return assertFailureIcon;
case ICxxTestBase.STATUS_ERROR:
return assertErrorIcon;
default:
return null;
}
}
else if(element instanceof ICxxTestStackFrame ||
element instanceof IDerefereeLeak)
{
return stackFrameIcon;
}
else
return null;
}
}
private final Image testOkIcon = TestRunnerViewPart.createImage("obj16/testok.gif"); //$NON-NLS-1$
private final Image testWarnIcon = TestRunnerViewPart.createImage("obj16/testwarn.gif"); //$NON-NLS-1$
private final Image testFailureIcon = TestRunnerViewPart.createImage("obj16/testfail.gif"); //$NON-NLS-1$
private final Image testErrorIcon = TestRunnerViewPart.createImage("obj16/testerr.gif"); //$NON-NLS-1$
private final Image assertTraceIcon = TestRunnerViewPart.createImage("obj16/asserttrace.gif"); //$NON-NLS-1$
private final Image assertWarnIcon = TestRunnerViewPart.createImage("obj16/assertwarn.gif"); //$NON-NLS-1$
private final Image assertFailureIcon = TestRunnerViewPart.createImage("obj16/assertfail.gif"); //$NON-NLS-1$
private final Image assertErrorIcon = TestRunnerViewPart.createImage("obj16/asserterror.gif"); //$NON-NLS-1$
private final Image stackFrameIcon = TestRunnerViewPart.createImage("obj16/stkfrm_obj.gif"); //$NON-NLS-1$
public static final String ID = CxxTestPlugin.PLUGIN_ID + ".TestRunnerView"; //$NON-NLS-1$
private Composite parent;
private Composite counterComposite;
private CounterPanel counterPanel;
private CxxTestProgressBar progressBar;
private CTabFolder tabFolder;
private SashForm sashForm;
private TreeViewer detailViewer;
private int orientation = VIEW_ORIENTATION_AUTOMATIC;
private int currentOrientation;
private ILaunch currentLaunch;
private ICProject launchedProject;
protected Vector<TestRunTab> testRunTabs = new Vector<TestRunTab>();
private TestRunTab activeRunTab;
private Clipboard clipboard;
private StopAction stopAction;
private ToggleOrientationAction[] toggleOrientationActions;
private static final int VIEW_ORIENTATION_VERTICAL= 0;
private static final int VIEW_ORIENTATION_HORIZONTAL= 1;
private static final int VIEW_ORIENTATION_AUTOMATIC= 2;
private class StopAction extends Action
{
public StopAction()
{
setText(Messages.TestRunnerViewPart_TerminateLabel);
setToolTipText(Messages.TestRunnerViewPart_TerminateTooltip);
setDisabledImageDescriptor(CxxTestPlugin.getImageDescriptor("dlcl16/stop.gif")); //$NON-NLS-1$
setHoverImageDescriptor(CxxTestPlugin.getImageDescriptor("elcl16/stop.gif")); //$NON-NLS-1$
setImageDescriptor(CxxTestPlugin.getImageDescriptor("elcl16/stop.gif")); //$NON-NLS-1$
}
public void run()
{
stopTest();
}
}
private class ToggleOrientationAction extends Action
{
private final int actionOrientation;
public ToggleOrientationAction(int orientation)
{
super("", AS_RADIO_BUTTON); //$NON-NLS-1$
if(orientation == TestRunnerViewPart.VIEW_ORIENTATION_HORIZONTAL)
{
setText(Messages.TestRunnerViewPart_HorizontalViewLabel);
setImageDescriptor(CxxTestPlugin.getImageDescriptor("elcl16/th_horizontal.gif")); //$NON-NLS-1$
}
else if(orientation == TestRunnerViewPart.VIEW_ORIENTATION_VERTICAL)
{
setText(Messages.TestRunnerViewPart_VerticalViewLabel);
setImageDescriptor(CxxTestPlugin.getImageDescriptor("elcl16/th_vertical.gif")); //$NON-NLS-1$
}
else if(orientation == TestRunnerViewPart.VIEW_ORIENTATION_AUTOMATIC)
{
setText(Messages.TestRunnerViewPart_AutomaticViewLabel);
setImageDescriptor(CxxTestPlugin.getImageDescriptor("elcl16/th_automatic.gif")); //$NON-NLS-1$
}
actionOrientation = orientation;
}
public int getOrientation()
{
return actionOrientation;
}
public void run()
{
if(isChecked())
{
orientation = actionOrientation;
computeOrientation();
}
}
}
public void createPartControl(Composite parent)
{
this.parent = parent;
parent.addControlListener(new ControlAdapter()
{
public void controlResized(ControlEvent e)
{
computeOrientation();
}
});
setContentDescription(""); //$NON-NLS-1$
clipboard = new Clipboard(Display.getCurrent());
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
parent.setLayout(layout);
configureToolBar();
counterComposite = createProgressCountPanel(parent);
counterComposite.setLayoutData(new GridData(
GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
SashForm sashForm = createSashForm(parent);
sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
}
private SashForm createSashForm(Composite parent)
{
sashForm = new SashForm(parent, SWT.HORIZONTAL);
ViewForm top = new ViewForm(sashForm, SWT.NONE);
tabFolder = createTestRunTabs(top);
top.setContent(tabFolder);
ViewForm bottom = new ViewForm(sashForm, SWT.NONE);
CLabel label = new CLabel(bottom, SWT.NONE);
label.setText(Messages.TestRunnerViewPart_DetailsLabel);
bottom.setTopLeft(label);
detailViewer = new TreeViewer(bottom, SWT.NONE);
detailViewer.setContentProvider(new DetailsContentProvider());
detailViewer.setLabelProvider(new DetailsLabelProvider());
detailViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event)
{
IStructuredSelection selection =
(IStructuredSelection)detailViewer.getSelection();
if(selection.size() > 0)
showTest(selection.getFirstElement());
}
});
bottom.setContent(detailViewer.getTree());
sashForm.setWeights(new int[] { 50, 50 });
return sashForm;
}
private Composite createProgressCountPanel(Composite parent)
{
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
composite.setLayout(layout);
setCounterColumns(layout);
counterPanel = new CounterPanel(composite);
counterPanel.setLayoutData(new GridData(
GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
progressBar = new CxxTestProgressBar(composite);
progressBar.setLayoutData(new GridData(
GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
return composite;
}
private void configureToolBar()
{
IActionBars actionBars = getViewSite().getActionBars();
IToolBarManager toolBar = actionBars.getToolBarManager();
IMenuManager viewMenu = actionBars.getMenuManager();
toggleOrientationActions = new ToggleOrientationAction[] {
new ToggleOrientationAction(VIEW_ORIENTATION_VERTICAL),
new ToggleOrientationAction(VIEW_ORIENTATION_HORIZONTAL),
new ToggleOrientationAction(VIEW_ORIENTATION_AUTOMATIC)
};
stopAction = new StopAction();
stopAction.setEnabled(false);
toolBar.add(stopAction);
for(int i = 0; i < toggleOrientationActions.length; ++i)
viewMenu.add(toggleOrientationActions[i]);
viewMenu.add(new Separator());
actionBars.updateActionBars();
}
public void dispose()
{
disposeIcons();
}
private void disposeIcons()
{
testOkIcon.dispose();
testWarnIcon.dispose();
testFailureIcon.dispose();
testErrorIcon.dispose();
assertTraceIcon.dispose();
assertWarnIcon.dispose();
assertFailureIcon.dispose();
assertErrorIcon.dispose();
}
private CTabFolder createTestRunTabs(Composite parent)
{
CTabFolder tabFolder = new CTabFolder(parent, SWT.TOP);
tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL));
TestHierarchyTab hierarchyTab = new TestHierarchyTab();
hierarchyTab.createTabControl(tabFolder, clipboard, this);
testRunTabs.addElement(hierarchyTab);
TestMemoryTab memoryTab = new TestMemoryTab();
memoryTab.createTabControl(tabFolder, clipboard, this);
testRunTabs.addElement(memoryTab);
if(tabFolder.getItemCount() > 0)
{
tabFolder.setSelection(0);
activeRunTab = testRunTabs.firstElement();
}
tabFolder.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event)
{
testTabChanged(event);
}
});
return tabFolder;
}
private void testTabChanged(SelectionEvent event)
{
for(Enumeration<TestRunTab> e = testRunTabs.elements(); e.hasMoreElements(); )
{
TestRunTab v = e.nextElement();
if(((CTabFolder)event.widget).getSelection().getText() == v.getName())
{
// v.setSelectedTest(activeRunTab.getSelectedTestObject());
activeRunTab = v;
activeRunTab.activate();
}
}
}
private void computeOrientation()
{
if(orientation != VIEW_ORIENTATION_AUTOMATIC)
{
currentOrientation = orientation;
setOrientation(currentOrientation);
}
else
{
Point size = parent.getSize();
if(size.x != 0 && size.y != 0)
{
if(size.x > size.y)
setOrientation(VIEW_ORIENTATION_HORIZONTAL);
else
setOrientation(VIEW_ORIENTATION_VERTICAL);
}
}
}
private void setOrientation(int orientation)
{
if((sashForm == null) || sashForm.isDisposed())
return;
boolean horizontal = orientation == VIEW_ORIENTATION_HORIZONTAL;
sashForm.setOrientation(horizontal ? SWT.HORIZONTAL : SWT.VERTICAL);
for(int i = 0; i < toggleOrientationActions.length; ++i)
toggleOrientationActions[i].setChecked(
orientation == toggleOrientationActions[i].getOrientation());
currentOrientation = orientation;
GridLayout layout = (GridLayout)counterComposite.getLayout();
setCounterColumns(layout);
parent.layout();
}
private void setCounterColumns(GridLayout layout)
{
if(currentOrientation == VIEW_ORIENTATION_HORIZONTAL)
layout.numColumns = 2;
else
layout.numColumns = 1;
}
public void setFocus()
{
}
public void showTest(Object test)
{
new OpenTestAction(this, test).run();
}
public void stopTest()
{
if(currentLaunch != null)
{
try
{
currentLaunch.terminate();
}
catch (DebugException e) { }
currentLaunch = null;
}
setContentDescription(""); //$NON-NLS-1$
stopAction.setEnabled(false);
}
public void handleObjectSelected(Object obj)
{
showDetails(obj);
}
private void showDetails(Object obj)
{
if(obj == null)
detailViewer.setInput(null);
else
{
if(obj instanceof ICxxTestMethod)
{
ICxxTestMethod test = (ICxxTestMethod)obj;
ICxxTestAssertion[] assertions = test.getFailedAssertions();
detailViewer.setInput(assertions);
}
else if(obj instanceof ICxxTestSuiteError)
{
ICxxTestSuiteError test = (ICxxTestSuiteError)obj;
detailViewer.setInput(new Object[] { test });
}
else if(obj instanceof IDerefereeLeak)
{
IDerefereeLeak leak = (IDerefereeLeak)obj;
detailViewer.setInput(new Object[] { leak });
}
else if(obj instanceof IDerefereeSummary)
{
detailViewer.setInput(obj);
}
detailViewer.expandAll();
}
}
public static Image createImage(String path)
{
try
{
URL base = Platform.getBundle(CxxTestPlugin.PLUGIN_ID).
getEntry("/icons/full/"); //$NON-NLS-1$
URL url = new URL(base, path);
ImageDescriptor id= ImageDescriptor.createFromURL(url);
return id.createImage();
}
catch (MalformedURLException e)
{
}
return null;
}
public void testRunStarted(ICProject project, ILaunch launch)
{
launchedProject = project;
for(Enumeration<TestRunTab> e = testRunTabs.elements(); e.hasMoreElements(); )
{
TestRunTab v = e.nextElement();
v.testRunStarted(project, launch);
}
counterPanel.reset();
progressBar.reset();
currentLaunch = launch;
String name = ""; //$NON-NLS-1$
try
{
name = launch.getLaunchConfiguration().getAttribute(
ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
}
catch (CoreException e) { }
detailViewer.setInput(null);
setContentDescription(MessageFormat.format(
Messages.TestRunnerViewPart_RunningMessage, name));
stopAction.setEnabled(true);
}
public ICProject getLaunchedProject()
{
return launchedProject;
}
public void testRunEnded()
{
currentLaunch = null;
stopTest();
for(Enumeration<TestRunTab> e = testRunTabs.elements(); e.hasMoreElements(); )
{
TestRunTab v = e.nextElement();
v.testRunEnded();
}
}
public void setSummary(ICxxTestSuite[] suites)
{
if(suites == null)
return;
if(suites.length > 0)
getViewSite().getPage().activate(this);
int totalTests = 0, failedTests = 0, errorTests = 0;
for(int i = 0; i < suites.length; i++)
{
ICxxTestSuiteChild[] tests = suites[i].getChildren(true);
totalTests += tests.length;
for(int j = 0; j < tests.length; j++)
{
if(tests[j].getStatus() == ICxxTestBase.STATUS_ERROR)
errorTests++;
else if(tests[j].getStatus() == ICxxTestBase.STATUS_FAILED)
failedTests++;
}
}
counterPanel.reset();
counterPanel.setRunValue(totalTests);
counterPanel.setFailureValue(failedTests);
counterPanel.setErrorValue(errorTests);
progressBar.reset();
progressBar.setMaximum(totalTests);
progressBar.step(failedTests + errorTests);
progressBar.refresh(failedTests + errorTests > 0);
}
}