Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce file driven tests. #125

Merged
merged 11 commits into from
Nov 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,9 @@ dependencies {
runtime group: 'org.slf4j', name: 'slf4j-api', version:'1.7.5'
runtime group: 'org.javolution', name: 'javolution', version:'5.2.6'
}

test {
testLogging {
exceptionFormat = 'full'
}
}
2 changes: 0 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.6.3</version>
</dependency>


<!-- dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/com/cflint/CFLint.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import cfml.parsing.cfscript.CFIdentifier;
import cfml.parsing.cfscript.CFLiteral;
import cfml.parsing.cfscript.CFNestedExpression;
import cfml.parsing.cfscript.CFStatement;
import cfml.parsing.cfscript.CFUnaryExpression;
import cfml.parsing.cfscript.CFVarDeclExpression;
import cfml.parsing.cfscript.script.CFCompDeclStatement;
Expand Down Expand Up @@ -809,7 +810,13 @@ protected void reportRule(final Element elem, final Object expression, final Con
bldr.setSeverity("WARNING");
bldr.setMessage(msgcode);
}
if(elem != null){
if(expression instanceof CFStatement){
bldr.setExpression(((CFStatement) expression).Decompile(0));
}
else if(expression instanceof CFScriptStatement){
bldr.setExpression(((CFScriptStatement) expression).Decompile(0));
}
else if(elem != null){
bldr.setExpression(elem.toString());
}
bldr.setRuleParameters(ruleInfo.getParameters());
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/cflint/JSONOutput.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,24 @@
import com.fasterxml.jackson.core.JsonGenerator;

public class JSONOutput {

boolean prettyPrint = true;

public boolean isPrettyPrint() {
return prettyPrint;
}

public void setPrettyPrint(boolean prettyPrint) {
this.prettyPrint = prettyPrint;
}

@SuppressWarnings("unchecked")
public void output(final BugList bugList, final Writer writer) throws IOException {
// final StringBuilder sb = new StringBuilder();
JsonFactory jsonF = new JsonFactory();
JsonGenerator jg = jsonF.createGenerator(writer);
if(prettyPrint)
jg.useDefaultPrettyPrinter();
jg.writeStartArray();
for (final Entry<String, List<BugInfo>> bugEntry : bugList.getBugList().entrySet()) {
final Iterator<BugInfo> iterator = bugEntry.getValue().iterator();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.cflint.plugins.core;

import java.util.Arrays;
import java.util.List;

import ro.fortsoft.pf4j.Extension;
import net.htmlparser.jericho.Element;
import cfml.CFSCRIPTLexer;
import cfml.parsing.cfscript.CFBinaryExpression;
import cfml.parsing.cfscript.CFExpression;
import cfml.parsing.cfscript.script.CFExpressionStatement;
import cfml.parsing.cfscript.script.CFScriptStatement;

import com.cflint.BugInfo;
import com.cflint.BugList;
import com.cflint.plugins.CFLintScannerAdapter;
import com.cflint.plugins.Context;

@Extension
public class CFCompareVsAssignChecker extends CFLintScannerAdapter {
final String severity = "INFO";

List<Integer> TOKENS = Arrays.asList(CFSCRIPTLexer.EQUALSEQUALSOP,
CFSCRIPTLexer.LT,
CFSCRIPTLexer.LTE,
CFSCRIPTLexer.GT,
CFSCRIPTLexer.GTE,
CFSCRIPTLexer.OR,
CFSCRIPTLexer.OROPERATOR,
CFSCRIPTLexer.EQV,
CFSCRIPTLexer.XOR,
CFSCRIPTLexer.AND,
CFSCRIPTLexer.ANDOPERATOR,
CFSCRIPTLexer.EQ,
CFSCRIPTLexer.NEQ,
CFSCRIPTLexer.CONTAINS);

@Override
public void expression(final CFScriptStatement expression, final Context context, final BugList bugs) {
if(expression instanceof CFExpressionStatement){
final CFExpressionStatement exprStatement = (CFExpressionStatement)expression;
if(exprStatement.getExpression() instanceof CFBinaryExpression){
CFBinaryExpression binaryExpression = (CFBinaryExpression) exprStatement.getExpression();
if(TOKENS.contains(binaryExpression.getToken().getType())){
context.addMessage("COMPARE_INSTEAD_OF_ASSIGN", binaryExpression.getToken().getText());
}
}
}
}

protected void noNeedtoUseCreateObject(final int lineNo, final Context context, final BugList bugs) {
bugs.add(new BugInfo.BugInfoBuilder().setLine(lineNo).setMessageCode("AVOID_USING_CREATEOBJECT")
.setSeverity(severity).setFilename(context.getFilename())
.setMessage("CreateObject statement at line " + lineNo + ". Use createObject(path_to_component) or even better new path_to_component().")
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ private String actualFileName(final String fileName) {
actualFileName = fileName.substring(seperatorPosition + 1);
}

System.out.println(fileName);
System.out.println(actualFileName);

return actualFileName;
}

Expand All @@ -55,8 +52,6 @@ public void checkNameForBugs(String component, String filename, BugList bugs) {
int maxComponentWords = ValidName.MAX_COMPONENT_WORDS;
int line = 1;

System.out.println("COMP " + component);

if (getParameter("MinLength") != null) {
try {
minComponentLength = Integer.parseInt(getParameter("MinLength"));
Expand Down
12 changes: 12 additions & 0 deletions src/main/resources/cflint.definition.json
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,18 @@
}
],
"parameter": []
},
{
"name": "CFCompareVsAssignChecker",
"className": "CFCompareVsAssignChecker",
"message": [
{
"code": "COMPARE_INSTEAD_OF_ASSIGN",
"messageText": "CWE-482: Comparing instead of Assigning",
"severity": "WARNING"
}
],
"parameter": []
}
]
}
7 changes: 7 additions & 0 deletions src/main/resources/cflint.definition.xml
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,11 @@
<messageText>Avoid leaving debug attribute on tags.</messageText>
</message>
</ruleImpl>
<ruleImpl name="CFCompareVsAssignChecker" className="CFCompareVsAssignChecker">
<message code="COMPARE_INSTEAD_OF_ASSIGN">
<severity>WARNING</severity>
<messageText>CWE-482: Comparing instead of Assigning</messageText>
</message>
</ruleImpl>

</CFLint-Plugin>
2 changes: 1 addition & 1 deletion src/test/java/com/cflint/TestCFBugs_ComponentNames.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public void nameHasPrefixOrPostfixTag() throws ParseException, IOException {
final String tagSrc = "<cfcomponent>\r\n"
+ "</cfcomponent>";
cfBugs.process(tagSrc, "MyComp.cfc");
final List<BugInfo> result = cfBugs.getBugs().getBugList().values().iterator().next();
final List<BugInfo> result = cfBugs.getBugs().getBugList().get("COMPONENT_HAS_PREFIX_OR_POSTFIX");
assertEquals(1, result.size());
assertEquals("COMPONENT_HAS_PREFIX_OR_POSTFIX", result.get(0).getMessageCode());
assertEquals(1, result.get(0).getLine());
Expand Down
1 change: 1 addition & 0 deletions src/test/java/com/cflint/TestJSONOutput.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class TestJSONOutput {
@Before
public void setUp(){
outputer = new JSONOutput();
outputer.setPrettyPrint(false);
bugList = new BugList(null);
writer = new StringWriter();
}
Expand Down
180 changes: 180 additions & 0 deletions src/test/java/com/cflint/integration/TestFiles.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package com.cflint.integration;


import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ResourceBundle;

import javax.xml.bind.JAXBException;
import javax.xml.transform.TransformerException;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import com.cflint.BugInfo;
import com.cflint.CFLint;
import com.cflint.JSONOutput;
import com.cflint.config.CFLintConfig;
import com.cflint.config.ConfigUtils;


/**
* Run a test over each *.cf* file in src/test/resources/com/cflint/tests
*
* @author ryaneberly
*
*/
@RunWith(Parameterized.class)
public class TestFiles {

File sourceFile;

boolean autoReplaceFailed = false;
static String singleTestName = null;
static {
try {
singleTestName = ResourceBundle.getBundle("com.cflint.test").getString("RunSingleTest");
} catch (Exception e) {
}
}

public TestFiles(File sourceFile,String testName) {
super();
this.sourceFile = sourceFile;
try {
autoReplaceFailed = "Y".equalsIgnoreCase(ResourceBundle.getBundle("com.cflint.test").getString(
"AutoReplaceFailedTestResults"));
} catch (Exception e) {
}
}

@Test
public void test() throws IOException, URISyntaxException, JAXBException, TransformerException {
final String inputString = loadFile(sourceFile);
final File expectedFile = new File(sourceFile.getPath().replaceAll("\\.cf.", ".expected.txt"));
final String expectedFileText = expectedFile.exists() ? loadFile(expectedFile) : null;
String expectedText = expectedFileText ;

final CFLintConfig config = loadPluginInfo(sourceFile.getParentFile());
CFLint cflint = new CFLint(config );

cflint.process(inputString, sourceFile.getPath());
List<BugInfo> result = cflint.getBugs().getFlatBugList();
StringWriter writer = new StringWriter();
new JSONOutput().output(cflint.getBugs(), writer);

String actualTree=writer.toString();
if (expectedText == null || expectedText.trim().length() == 0) {
writeExpectFile(expectedFile, actualTree);
System.out.println("Tree written to " + expectedFile);
} else {
if (autoReplaceFailed && !actualTree.equals(expectedText)) {
System.out.println("Replaced content of " + expectedFile);
expectedText = actualTree;
writeExpectFile(expectedFile, actualTree);
}
assertEquals(actualTree.replaceAll("\\\\","/").replaceAll("/+","/").replaceAll("\r\n", "\n"),
expectedText.replaceAll("\\\\","/").replaceAll("/+","/").replaceAll("\r\n", "\n"));
}
}

private void writeExpectFile(File expectedFile, String actualTree) throws IOException {
final FileOutputStream fos = new FileOutputStream(expectedFile, false);
fos.write(actualTree.getBytes());
fos.close();

}




private String getTree(String expectedFileText) {
if (expectedFileText != null && expectedFileText.contains("/*===TREE===*/")) {
int startIdx = expectedFileText.indexOf("/*===TREE===*/") + 14;
while (expectedFileText.charAt(startIdx) == '\r' || expectedFileText.charAt(startIdx) == '\n') {
startIdx++;
}
int endIndex = expectedFileText.indexOf("/*======*/", startIdx);
if (endIndex > startIdx) {
while (expectedFileText.charAt(endIndex - 1) == '\r' || expectedFileText.charAt(endIndex - 1) == '\n') {
endIndex--;
}
return expectedFileText.substring(startIdx, endIndex);
}
}
if (expectedFileText != null && expectedFileText.contains("/*===")) {
return null;
}
return expectedFileText;
}

@Parameterized.Parameters(name = "{1}")
public static Collection<Object[]> primeNumbers() throws URISyntaxException, IOException {
final ArrayList<Object[]> retval = new ArrayList<Object[]>();
final List<File> listing = new ArrayList<File>();
final File baseFolder = new File("src/test/resources/com/cflint/tests");
fillResourceListing(baseFolder, listing);
for (File s : listing) {
retval.add(new Object[] { s, baseFolder.toPath().relativize(s.toPath() ).toString() });
}
return retval;
}

private static void fillResourceListing(File file, List<File> retval) {
if (file != null) {
if (file.isDirectory()) {
for (File subfile : file.listFiles()) {
fillResourceListing(subfile, retval);
}
} else if (file.getName().toLowerCase().endsWith(".cfc") || file.getName().toLowerCase().endsWith(".cfm")) {
if (singleTestName == null || singleTestName.equals(file.getName())) {
retval.add(file);
} else if (singleTestName.equals("*LAST")) {
if (retval.size() == 0 || file.lastModified() > retval.get(0).lastModified()) {
retval.clear();
retval.add(file);
}
}
}
}
}
public static String loadFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
byte[] b = new byte[is.available()];
is.read(b);
is.close();
return new String(b);
}

public static CFLintConfig loadPluginInfo(File folder) throws IOException {
try{
final InputStream jsonInputStream = new FileInputStream(folder.getPath() + "/.cflintrc");
if (jsonInputStream != null) {
return ConfigUtils.unmarshalJson(jsonInputStream, CFLintConfig.class);
}
}catch(FileNotFoundException fnfe){}

final InputStream inputStream = new FileInputStream(folder.getPath() + "/.cflintrc.xml");
if (inputStream != null) {
try {
return ConfigUtils.unmarshal(inputStream, CFLintConfig.class);
} catch (JAXBException e) {
throw new IOException(e);
}
}
return null;
}

}
4 changes: 4 additions & 0 deletions src/test/resources/com/cflint/test.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#Change the AutoReplaceFailedTestResults to Y to pass the test and replace the expected results
AutoReplaceFailedTestResults=N
#Uncomment the following line to run only the last updated test file.
#RunSingleTest=*LAST
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<config><includes code="COMPARE_INSTEAD_OF_ASSIGN"/></config>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!--- contains comparison operations that don't 'do' anything --->
<cfscript>
x = {};
x.x = 1;
x.x == 2;
if (x.x == 2){
x=123;
}
x.x EQ 6;
</cfscript>
Loading