/*******************************************************************************
* Copyright (c) 2011, 2016 STMicroelectronics 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:
* Xavier Raynaud <xavier.raynaud@st.com> - initial API and implementation
* Red Hat Inc. - ongoing maintenance
*******************************************************************************/
package org.eclipse.linuxtools.internal.gcov.test;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.TreeSet;
import org.eclipse.cdt.core.CCProjectNature;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.actions.ContextualLaunchAction;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.linuxtools.dataviewers.actions.STExportToCSVAction;
import org.eclipse.linuxtools.internal.gcov.action.OpenGCAction;
import org.eclipse.linuxtools.profiling.tests.AbstractTest;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.resources.ProjectExplorer;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.osgi.framework.FrameworkUtil;
public abstract class GcovTest extends AbstractTest {
private static IProject project = null;
private static boolean isCppProject;
private static IWorkbenchWindow window;
private static Display display;
private static TreeSet<String> gcovFiles;
abstract protected String getTestProjectName();
abstract protected String getBinName();
abstract protected boolean useDefaultBin();
abstract protected boolean getTestProducedReference();
@BeforeClass
public static void init() {
display = Display.getDefault();
display.syncExec(() -> {
try {
window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPart part = window.getActivePage().getActivePart();
if (part.getTitle().equals("Welcome")) {
part.dispose();
}
PlatformUI.getWorkbench().showPerspective(CUIPlugin.ID_CPERSPECTIVE, window);
} catch (WorkbenchException e) {
Assert.fail("Couldn't open C/C++ perspective.");
}
});
}
@Before
public void setUp() throws Exception {
if (project == null) {
ICProject cproject = createProjectAndBuild(FrameworkUtil.getBundle(this.getClass()), getTestProjectName());
project = cproject.getProject();
isCppProject = project.getNature(CCProjectNature.CC_NATURE_ID) != null;
gcovFiles = new TreeSet<>();
do {
for (IResource r : project.members()) {
if (r.getType() == IResource.FILE && r.exists()) {
String fileName = r.getName();
if (fileName.endsWith(".gcda") || fileName.endsWith(".gcno")) {
gcovFiles.add(fileName);
}
}
}
} while (gcovFiles.size() < 1);
}
}
@After
public void cleanUp() {
display.syncExec(() -> {
Shell[] shells = Display.getCurrent().getShells();
for (final Shell shell : shells) {
String shellTitle = shell.getText();
if (!shellTitle.isEmpty() && !shellTitle.startsWith("Quick Access")
&& shell.getParent() != null) {
shell.close();
}
}
});
}
@AfterClass
public static void finalCleanUp() {
try {
project.delete(true, null);
} catch (CoreException e) {
Assert.fail("Project deletion failed");
} finally {
project = null;
}
}
@Test
public void testOpenGcovFileDetails() {
final String binPath = getBinPathOrDefault();
for (String string : gcovFiles) {
testGcovFileDetails(string, binPath);
}
}
private void testGcovFileDetails(final String filename, final String binPath) {
openGcovResult(project.getFile(filename), binPath, false);
display.syncExec(() -> {
final IWorkbenchPage page = window.getActivePage();
final IEditorPart editorPart = page.getActiveEditor();
final IFile openedFile = project.getFile(editorPart.getEditorInput().getName());
final IFile targetFile = project.getFile(
new Path(filename).removeFileExtension().addFileExtension(
isCppProject ? "cpp" : "c"));
if (!targetFile.equals(openedFile)) {
System.err.println("WARNING: editor for " + targetFile
+ " is not in focus.");
for (IEditorReference ref : page.getEditorReferences()) {
if (targetFile.equals(project.getFile(ref.getName()))) {
return;
}
}
Assert.fail("Editor for file " + targetFile + " was not opened,"
+ " instead opened " + openedFile + ".");
}
});
}
@Test
public void testOpenGcovSummary() {
final String binPath = getBinPathOrDefault();
final boolean testProducedReference = getTestProducedReference();
for (String string : gcovFiles) {
testGcovSummary(string, binPath, testProducedReference);
}
}
private void testGcovSummary(final String filename, String binPath,
final boolean testProducedReference) {
openGcovResult(project.getFile(filename), binPath, true);
IViewPart vp = window.getActivePage().findView("org.eclipse.linuxtools.gcov.view");
// No IDs on toolbar items, so explicitly check each one for tooltip texts
List<String> sortTypes = new ArrayList<>(Arrays.asList("function", "file", "folder"));
IContributionItem[] items = vp.getViewSite().getActionBars().getToolBarManager().getItems();
STExportToCSVAction csvAction = null;
for (IContributionItem item : items) {
if (item instanceof ActionContributionItem && ((ActionContributionItem) item).getAction() instanceof STExportToCSVAction) {
csvAction = (STExportToCSVAction) ((ActionContributionItem) item).getAction();
}
}
Assert.assertNotNull("CSV-Export toolbar button does not exist.", csvAction);
for (IContributionItem item : items) {
if (item instanceof ActionContributionItem) {
final IAction action = ((ActionContributionItem) item).getAction();
for (int i = 0, n = sortTypes.size(); i < n; i++) {
String sortType = sortTypes.get(i);
if (action.getText().equals("Sort coverage per " + sortType)) {
dumpCSV(action, csvAction, sortType, testProducedReference);
if (sortTypes.size() == 1) {
return;
}
sortTypes.remove(i);
break;
}
}
}
}
}
private void dumpCSV(final IAction sortAction, final STExportToCSVAction csvAction, String type, boolean testProducedReference) {
display.asyncExec(() -> sortAction.run());
String s = project.getLocation() + "/" + type + "-dump.csv";
new File(s).delete();
csvAction.getExporter().setFilePath(s);
csvAction.export();
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
if (Job.getJobManager().find(STExportToCSVAction.EXPORT_TO_CSV_JOB_FAMILY).length == 0) {
break;
}
}
if (testProducedReference) {
String ref = STJunitUtils.getAbsolutePath(FrameworkUtil.getBundle(GcovTest.class).getSymbolicName(), "csv/" + project.getName() + "/" + type + ".csv");
// STJunitUtils.compareIgnoreEOL(project.getLocation() + "/" + type + "-dump.csv", ref, false);
}
}
private void openGcovResult(final IFile file, String binaryPath, final boolean isCompleteCoverageResultWanted) {
new OpenGCAction().autoOpen(file.getLocation(), binaryPath, isCompleteCoverageResultWanted);
}
private class ProfileContextualLaunchAction extends ContextualLaunchAction {
public ProfileContextualLaunchAction(Menu menu) {
super("linuxtools");
fillMenu(menu);
}
}
@Test
public void testGcovSummaryByLaunch() {
display.syncExec(() -> {
try {
CommonNavigator vc = (CommonNavigator) window.getActivePage().showView(ProjectExplorer.VIEW_ID);
vc.selectReveal(new StructuredSelection(project.getFile(getBinName())));
Menu menu = new MenuManager().createContextMenu(vc.getCommonViewer().getControl());
new ProfileContextualLaunchAction(menu);
for (MenuItem item : menu.getItems()) {
if (item.getText().endsWith("Profile Code Coverage")) {
((ActionContributionItem) item.getData()).getAction().run();
break;
}
}
} catch (PartInitException e1) {
Assert.fail("Cannot show Project Explorer.");
}
try {
window.getActivePage().showView("org.eclipse.linuxtools.gcov.view");
} catch (PartInitException e2) {
Assert.fail("Cannot show GCov View.");
}
});
// Wait for the build job to finish (note: DebugUIPlugin doesn't put launch jobs in a family)
Job[] jobs = Job.getJobManager().find(null);
for (Job job : jobs) {
if (job.getName().contains("Gcov")) {
try {
job.join();
} catch (InterruptedException e) {}
break;
}
}
}
@Override
protected ILaunchConfigurationType getLaunchConfigType() {
return null;
}
@Override
protected void setProfileAttributes(ILaunchConfigurationWorkingCopy wc) {
}
private String getBinPathOrDefault() {
return !useDefaultBin() ? project.getFile(getBinName()).getLocation().toOSString() : "";
}
}