/*******************************************************************************
* Copyright (c) 2009, 2016 Alena Laskavaia
* 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:
* Alena Laskavaia - initial API and implementation
* Marc-Andre Laperle
*******************************************************************************/
package org.eclipse.cdt.codan.core.test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.codan.core.CodanRuntime;
import org.eclipse.cdt.codan.core.model.CheckerLaunchMode;
import org.eclipse.cdt.codan.core.model.IProblem;
import org.eclipse.cdt.codan.core.model.IProblemProfile;
import org.eclipse.cdt.codan.core.model.IProblemReporter;
import org.eclipse.cdt.codan.core.param.IProblemPreference;
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
import org.eclipse.cdt.codan.core.param.RootProblemPreference;
import org.eclipse.cdt.codan.internal.core.model.CodanProblem;
import org.eclipse.cdt.codan.internal.core.model.CodanProblemMarker;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* Base class for tests. If you want to use outside of this plugin, you need
* to override {@link #getPlugin()} method and maybe {@link #getSourcePrefix()}
* method to get source directory for the tests,
* default is "src". To make it read comment from java class, you need to
* include this source directory (with test java files) into the build bundle.
*
*/
@SuppressWarnings("nls")
public class CheckerTestCase extends CodanTestCase {
protected IMarker[] markers;
public IMarker checkErrorLine(int i) {
return checkErrorLine(currentFile, i);
}
public void checkErrorLines(Object... args) {
for (Object i : args) {
checkErrorLine((Integer) i);
}
assertEquals(args.length, markers.length);
}
public void checkErrorComments() {
for (Object i : errLines) {
checkErrorLine((Integer) i);
}
assertEquals("Expected number of errors " + errLines.size(),errLines.size(), markers.length);
}
public IMarker checkErrorLine(int i, String problemId) {
return checkErrorLine(currentFile, i, problemId);
}
public IMarker checkErrorLine(File file, int expectedLine) {
return checkErrorLine(file, expectedLine, null);
}
/**
* @param expectedLine
* - line
* @return
*/
public IMarker checkErrorLine(File file, int expectedLine, String problemId) {
assertTrue(markers != null);
assertTrue("No problems found but should", markers.length > 0); //$NON-NLS-1$
boolean found = false;
Integer line = null;
String mfile = null;
IMarker m = null;
for (int j = 0; j < markers.length; j++) {
m = markers[j];
line = getLine(m);
mfile = m.getResource().getName();
if (line.equals(expectedLine) && (problemId == null || problemId.equals(CodanProblemMarker.getProblemId(m)))) {
found = true;
if (file != null && !file.getName().equals(mfile))
found = false;
else
break;
}
}
assertEquals("Error on line " + expectedLine + " is not found", Integer.valueOf(expectedLine), line);
if (file != null)
assertEquals(file.getName(), mfile);
assertTrue(found);
assertNotNull(m);
return m;
}
/**
* @param line
* @param m
* @return
*/
public Integer getLine(IMarker m) {
Integer line = null;
try {
line = (Integer) m.getAttribute(IMarker.LINE_NUMBER);
if (line == null || line.equals(-1)) {
Object pos = m.getAttribute(IMarker.CHAR_START);
line = pos2line(((Integer) pos).intValue());
}
} catch (CoreException e) {
fail(e.getMessage());
} catch (IOException e) {
fail(e.getMessage());
}
return line;
}
public void checkNoErrors() {
if (markers != null && markers.length > 0) {
IMarker m = markers[0];
fail("Found " + markers.length + " errors but should not. First " +
CodanProblemMarker.getProblemId(m) + " at line " + getLine(m));
}
}
public void checkNoErrorsOfKind(String problemId) {
if (markers != null && markers.length > 0) {
List<IMarker> filtered = new ArrayList<IMarker>(markers.length);
for (IMarker m : markers) {
if (CodanProblemMarker.getProblemId(m).equals(problemId)) {
filtered.add(m);
}
}
if (!filtered.isEmpty()) {
IMarker m = filtered.get(0);
fail("Found " + filtered.size() + " errors but should not. First " +
CodanProblemMarker.getProblemId(m) + " at line " + getLine(m));
}
}
}
public void runOnProject() {
try {
indexFiles();
} catch (Exception e) {
fail(e.getMessage());
}
runCodan();
}
public void loadCodeAndRun(String code) throws CoreException {
loadcode(code);
runCodan();
}
public void loadCodeAndRunCpp(String code) throws CoreException {
loadcode(code, true);
runCodan();
}
protected void runCodan() {
CodanRuntime.getInstance().getBuilder().processResource(cproject.getProject(), new NullProgressMonitor());
try {
markers = cproject.getProject().findMarkers(IProblemReporter.GENERIC_CODE_ANALYSIS_MARKER_TYPE, true, 1);
} catch (CoreException e) {
fail(e.getMessage());
}
}
/**
* @param problemId
* @param paramId
* @return
*/
protected IProblemPreference getPreference(String problemId, String paramId) {
IProblemProfile resourceProfile =
CodanRuntime.getInstance().getCheckersRegistry().getResourceProfile(cproject.getResource());
IProblem problem = resourceProfile.findProblem(problemId);
IProblemPreference pref = ((MapProblemPreference) problem.getPreference()).getChildDescriptor(paramId);
return pref;
}
protected IProblemPreference setPreferenceValue(String problemId, String paramId, Object value) {
IProblemPreference param = getPreference(problemId, paramId);
param.setValue(value);
return param;
}
/**
* @param string
* @param m
*/
public void assertMessageMatch(String pattern, IMarker m) {
try {
String message = (String) m.getAttribute(IMarker.MESSAGE);
if (message.matches(pattern)) {
fail("Expected " + message + " to match with /" + pattern //$NON-NLS-1$ //$NON-NLS-2$
+ "/"); //$NON-NLS-1$
}
} catch (CoreException e) {
fail(e.getMessage());
}
}
public void assertMessageContains(CharSequence charSequence, IMarker m) {
try {
String message = (String) m.getAttribute(IMarker.MESSAGE);
if (!message.contains(charSequence)) {
fail("Expected " + message + " to contain /" + charSequence //$NON-NLS-1$ //$NON-NLS-2$
+ "/"); //$NON-NLS-1$
}
} catch (CoreException e) {
fail(e.getMessage());
}
}
/**
* Enable given problems and disable the rest
* @param ids
*/
protected void enableProblems(String... ids) {
IProblemProfile profile = CodanRuntime.getInstance().getCheckersRegistry().getWorkspaceProfile();
IProblem[] problems = profile.getProblems();
for (int i = 0; i < problems.length; i++) {
IProblem p = problems[i];
boolean enabled = false;
for (int j = 0; j < ids.length; j++) {
String pid = ids[j];
if (p.getId().equals(pid)) {
enabled = true;
// Force the launch mode to FULL_BUILD to make sure we can test the problem even
// if by default it is not set to run on FULL_BUILD.
IProblemPreference preference = p.getPreference();
if (preference instanceof RootProblemPreference) {
RootProblemPreference rootProblemPreference = (RootProblemPreference) preference;
rootProblemPreference.getLaunchModePreference().enableInLaunchModes(CheckerLaunchMode.RUN_ON_FULL_BUILD);
}
break;
}
}
((CodanProblem) p).setEnabled(enabled);
}
CodanRuntime.getInstance().getCheckersRegistry().updateProfile(cproject.getProject(), profile);
}
protected void checkSampleAbove() throws CoreException {
loadCodeAndRun(getAboveComment());
checkErrorComments();
}
protected void checkSampleAboveCpp() throws CoreException {
loadCodeAndRunCpp(getAboveComment());
checkErrorComments();
}
}