/*
* Coverity Sonar Plugin
* Copyright (c) 2017 Synopsys, Inc
* support@coverity.com
*
* 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.
*/
package org.sonar.plugins.coverity.util;
import edu.emory.mathcs.backport.java.util.Arrays;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import static org.sonar.plugins.coverity.util.CoverityUtil.getValue;
public class RulesGeneratorTest {
private static final String outputFilePath = "./test";
private static final String qualityJsonFile = "src/test/java/org/sonar/plugins/coverity/util/quality-checker-properties.json";
private static final String findbugsJsonFile = "src/test/java/org/sonar/plugins/coverity/util/findbugs-checker-properties.json";
private static final String javaOutputFilePath = "./test/coverity-java.xml";
private static final String cppOutputFilePath = "./test/coverity-cov-cpp.xml";
private static final String csOutputFilePath = "./test/coverity-cs.xml";
private static final String jsOutputFilePath = "./test/coverity-js.xml";
private static final String pythonOutputFilePath = "./test/coverity-py.xml";
private static final String phpOutputFilePath = "./test/coverity-php.xml";
@Before
public void setUp() {
createTestDirectory();
RulesGenerator.setOutputFilePath(outputFilePath);
}
@After
public void tearDown() throws IOException {
File testDir = new File(outputFilePath);
if (testDir.exists()) {
File[] files = testDir.listFiles();
if (files != null) {
for (File file : files) {
Assert.assertTrue(file.delete());
}
}
Assert.assertTrue(testDir.delete());
}
}
@Test
public void rulesGeneratorTest() throws Exception {
File qualityCheckerFile = new File(qualityJsonFile);
File findbugCheckerFile = new File(findbugsJsonFile);
Assert.assertTrue(qualityCheckerFile.exists());
Assert.assertTrue(findbugCheckerFile.exists());
RulesGenerator.setOutputFilePath(outputFilePath);
RulesGenerator.main(new String[] {qualityCheckerFile.getAbsolutePath(), findbugCheckerFile.getAbsolutePath()});
File javaOutputFile = new File(javaOutputFilePath);
File cppOutputFile = new File(cppOutputFilePath);
File csOutputFile = new File(csOutputFilePath);
File jsOutputFile = new File(jsOutputFilePath);
File pythonOutputFile = new File(pythonOutputFilePath);
File phpOutputFile = new File(phpOutputFilePath);
Assert.assertTrue(javaOutputFile.exists());
Assert.assertTrue(cppOutputFile.exists());
Assert.assertTrue(csOutputFile.exists());
Assert.assertTrue(jsOutputFile.exists());
Assert.assertTrue(pythonOutputFile.exists());
Assert.assertTrue(phpOutputFile.exists());
checkCsOutputFile(csOutputFile);
checkJavaOutputFile(javaOutputFile);
checkCppOutputFile(cppOutputFile);
checkJavaScriptOutputFile(jsOutputFile);
checkPythonOutputFile(pythonOutputFile);
checkPhpOutputFile(phpOutputFile);
}
private void createTestDirectory() {
File testDir = new File(outputFilePath);
if (!testDir.exists()) {
Assert.assertTrue(testDir.mkdir());
}
}
private void checkCsOutputFile(File outputFile) throws IOException {
NodeList nodes = parseNodeList(outputFile);
Assert.assertNotNull(nodes);
boolean testSubcategory = false;
boolean noneSubcategory = false;
boolean msvsca = false;
boolean general = false;
Assert.assertEquals(4, nodes.getLength());
for (int i = 0 ; i < nodes.getLength() ; i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String key = getValue("key", element);
// STATIC_CS_coverity-cs
if (key.equals("STATIC_CS_coverity-cs")) {
Assert.assertEquals("Coverity General CS", getValue("name", element));
general = true;
checkRuleTags(new String[]{"coverity", "c#", "coverity-quality"}, element);
}
// STATIC_CS_MSVSCA.*
else if (key.equals("STATIC_CS_MSVSCA.*")) {
Assert.assertEquals("Coverity MSVSCA : Microsoft Visual Studio Code Analysis", getValue("name", element));
msvsca = true;
checkRuleTags(new String[]{"coverity", "c#", "coverity-quality", "msvsca"}, element);
}
// STATIC_CS_C# Example Checker_none
else if (key.equals("STATIC_CS_C# Example Checker_none")) {
Assert.assertEquals("C# Example Checker : Short Description", getValue("name", element));
noneSubcategory = true;
checkRuleTags(new String[]{"coverity", "c#", "coverity-quality"}, element);
}
// STATIC_CS_C# Example Checker_test-subcategory
else if (key.equals("STATIC_CS_C# Example Checker_test-subcategory")) {
Assert.assertEquals("C# Example Checker : Short Description", getValue("name", element));
testSubcategory = true;
checkRuleTags(new String[]{"coverity", "c#", "coverity-quality"}, element);
}
}
}
Assert.assertTrue(general && msvsca && noneSubcategory && testSubcategory);
}
private void checkJavaOutputFile(File outputFile) throws IOException {
NodeList nodes = parseNodeList(outputFile);
Assert.assertNotNull(nodes);
boolean noneSubcategory = false;
boolean fbGeneric = false;
boolean fbNone = false;
boolean general = false;
Assert.assertEquals(4, nodes.getLength());
for (int i = 0 ; i < nodes.getLength() ; i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String key = getValue("key", element);
// STATIC_JAVA_coverity-java
if (key.equals("STATIC_JAVA_coverity-java")) {
Assert.assertEquals("Coverity General JAVA", getValue("name", element));
general = true;
checkRuleTags(new String[]{"coverity", "java", "coverity-quality"}, element);
}
// STATIC_JAVA_Java Example Checker_none
else if (key.equals("STATIC_JAVA_Java Example Checker_none")) {
Assert.assertEquals("Java Example Checker : Short Description", getValue("name", element));
noneSubcategory = true;
checkRuleTags(new String[]{"coverity", "java", "coverity-quality"}, element);
}
// STATIC_JAVA_FB.AM_CREATES_EMPTY_JAR_FILE_ENTRY_generic
else if (key.equals("STATIC_JAVA_FB.AM_CREATES_EMPTY_JAR_FILE_ENTRY_generic")) {
Assert.assertEquals("The code calls putNextEntry(), immediately followed by a call to closeEntry().", getValue("description", element));
fbGeneric = true;
checkRuleTags(new String[]{"coverity", "java", "coverity-quality", "findbugs"}, element);
}
// STATIC_JAVA_FB.AM_CREATES_EMPTY_JAR_FILE_ENTRY_none
else if (key.equals("STATIC_JAVA_FB.AM_CREATES_EMPTY_JAR_FILE_ENTRY_none")) {
Assert.assertEquals("The code calls putNextEntry(), immediately followed by a call to closeEntry().", getValue("description", element));
fbNone = true;
checkRuleTags(new String[]{"coverity", "java", "coverity-quality"}, element);
}
}
}
Assert.assertTrue(general && fbGeneric && noneSubcategory && fbNone);
}
private void checkCppOutputFile(File outputFile) throws IOException {
NodeList nodes = parseNodeList(outputFile);
Assert.assertNotNull(nodes);
boolean noneSubcategory = false;
boolean general = false;
boolean pwRule = false;
boolean swRule = false;
boolean rwRule = false;
boolean misraRule = false;
Assert.assertEquals(6, nodes.getLength());
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String key = getValue("key", element);
// STATIC_C_coverity-cov-cpp
if (key.equals("STATIC_C_coverity-cov-cpp")) {
Assert.assertEquals("Coverity General COV-CPP", getValue("name", element));
general = true;
checkRuleTags(new String[]{"coverity", "c", "c++", "coverity-quality"}, element);
}
// STATIC_C_CPP Example Checker_none
else if (key.equals("STATIC_C_CPP Example Checker_none")) {
Assert.assertEquals("CPP Example Checker : Short Description", getValue("name", element));
Assert.assertEquals("VULNERABILITY", getValue("type", element));
noneSubcategory = true;
checkRuleTags(new String[]{"coverity", "c", "c++", "objective-c", "coverity-quality", "coverity-security"}, element);
}
// STATIC_C_PW.*
else if (key.equals("STATIC_C_PW.*")) {
Assert.assertEquals("Coverity PW : Parse Warnings", getValue("name", element));
pwRule = true;
checkRuleTags(new String[]{"coverity", "c", "c++", "coverity-quality", "parse-warning"}, element);
}
// STATIC_C_SW.*
else if (key.equals("STATIC_C_SW.*")) {
Assert.assertEquals("Coverity SW : Semantic Warnings", getValue("name", element));
swRule = true;
checkRuleTags(new String[]{"coverity", "c", "c++", "coverity-quality", "semantic-warning"}, element);
}
// STATIC_C_RW.*
else if (key.equals("STATIC_C_RW.*")) {
Assert.assertEquals("Coverity RW : Recovery Warnings", getValue("name", element));
rwRule = true;
checkRuleTags(new String[]{"coverity", "c", "c++", "coverity-quality", "recovery-warning"}, element);
}
// STATIC_C_MISRA.*
else if (key.equals("STATIC_C_MISRA.*")) {
Assert.assertEquals("Coverity MISRA : Coding Standard Violation", getValue("name", element));
misraRule = true;
checkRuleTags(new String[]{"coverity", "c", "c++", "coverity-quality", "misra"}, element);
}
}
}
Assert.assertTrue(general && noneSubcategory && pwRule && swRule && rwRule && misraRule);
}
private void checkJavaScriptOutputFile(File outputFile) throws IOException {
NodeList nodes = parseNodeList(outputFile);
Assert.assertNotNull(nodes);
boolean noneSubcategory = false;
boolean withSubcategory = false;
boolean jsHintGeneric = false;
boolean general = false;
Assert.assertEquals(4, nodes.getLength());
for (int i = 0 ; i < nodes.getLength() ; i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String key = getValue("key", element);
// OTHER_coverity-js
if (key.equals("OTHER_coverity-js")) {
Assert.assertEquals("Coverity General JS", getValue("name", element));
general = true;
checkRuleTags(new String[]{"coverity", "js", "coverity-quality"}, element);
}
// OTHER_JSHINT.*
else if (key.equals("OTHER_JSHINT.*")) {
Assert.assertEquals("Coverity JSHINT : JSHint Warning", getValue("name", element));
jsHintGeneric = true;
checkRuleTags(new String[]{"coverity", "js", "coverity-quality", "jshint"}, element);
}
// OTHER_JavaScript Example Checker_none
else if (key.equals("OTHER_JavaScript Example Checker_none")) {
Assert.assertEquals("JavaScript Example Checker : Short Description", getValue("name", element));
noneSubcategory = true;
checkRuleTags(new String[]{"coverity", "js", "coverity-quality"}, element);
}
// OTHER_JavaScript Example Checker_subcategory
else if (key.equals("OTHER_JavaScript Example Checker_subcategory")) {
Assert.assertEquals("JavaScript Example Checker : Short Description", getValue("name", element));
withSubcategory = true;
checkRuleTags(new String[]{"coverity", "js", "coverity-quality"}, element);
}
}
}
Assert.assertTrue(general && jsHintGeneric && noneSubcategory && withSubcategory);
}
private void checkPythonOutputFile(File outputFile) throws IOException {
NodeList nodes = parseNodeList(outputFile);
Assert.assertNotNull(nodes);
boolean subcategory = false;
boolean noneSubcategory = false;
boolean general = false;
Assert.assertEquals(3, nodes.getLength());
for (int i = 0 ; i < nodes.getLength() ; i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String key = getValue("key", element);
// OTHER_coverity-py
if (key.equals("OTHER_coverity-py")) {
Assert.assertEquals("Coverity General PY", getValue("name", element));
general = true;
checkRuleTags(new String[]{"coverity", "python", "coverity-quality"}, element);
}
// OTHER_CONSTANT_EXPRESSION_RESULT_bit_and_with_zero
else if (key.equals("OTHER_CONSTANT_EXPRESSION_RESULT_bit_and_with_zero")) {
Assert.assertEquals("Integer handling issues : Bitwise-and with zero", getValue("name", element));
subcategory = true;
checkRuleTags(new String[]{"coverity", "python", "coverity-quality"}, element);
}
// OTHER_CONSTANT_EXPRESSION_RESULT_none
else if (key.equals("OTHER_CONSTANT_EXPRESSION_RESULT_none")) {
Assert.assertEquals("Integer handling issues : Bitwise-and with zero", getValue("name", element));
noneSubcategory = true;
checkRuleTags(new String[]{"coverity", "python", "coverity-quality"}, element);
}
}
}
Assert.assertTrue(general && noneSubcategory && subcategory);
}
private void checkPhpOutputFile(File outputFile) throws IOException {
NodeList nodes = parseNodeList(outputFile);
Assert.assertNotNull(nodes);
boolean noneSubcategory = false;
boolean general = false;
Assert.assertEquals(2, nodes.getLength());
for (int i = 0 ; i < nodes.getLength() ; i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String key = getValue("key", element);
// OTHER_coverity-php
if (key.equals("OTHER_coverity-php")) {
Assert.assertEquals("Coverity General PHP", getValue("name", element));
general = true;
checkRuleTags(new String[]{"coverity", "php", "coverity-quality"}, element);
}
// OTHER_COPY_PASTE_ERROR_none
else if (key.equals("OTHER_COPY_PASTE_ERROR_none")) {
Assert.assertEquals("Incorrect expression : Copy-paste error", getValue("name", element));
noneSubcategory = true;
checkRuleTags(new String[]{"coverity", "php", "coverity-quality"}, element);
}
}
}
Assert.assertTrue(general && noneSubcategory);
}
private NodeList parseNodeList(File outputFile) throws IOException {
InputStream in = new FileInputStream(outputFile);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = null;
Document doc = null;
try {
dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(in);
doc.getDocumentElement().normalize();
return doc.getElementsByTagName("rule");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
in.close();
return null;
}
private void checkRuleTags(String[] expectedTags, Element element) {
NodeList tags = element.getElementsByTagName("tag");
Assert.assertNotNull(tags);
Assert.assertEquals(expectedTags.length, tags.getLength());
String[] ruleTags = new String[tags.getLength()];
for (int i = 0 ; i < tags.getLength() ; i++) {
ruleTags[i] = tags.item(i).getFirstChild().getNodeValue();
}
Arrays.sort(expectedTags);
Arrays.sort(ruleTags);
Assert.assertArrayEquals(expectedTags, ruleTags);
}
}