public class CFB {
DbDriver m_driver;
CfbSchema m_schema;
- CfbBundle m_bundle;
+ volatile static CfbBundle m_bundle = null;
Locale m_locale;
Config m_config;
m_driver = new PostgresqlDriver();
m_schema = new CfbSchema(m_driver);
m_locale = locale;
- m_bundle = CfbBundle.getInst(m_locale);
+ m_bundle = null;
m_config = new Config();
m_configFile = new File("config.properties");
m_output = null;
}
+ CfbBundle getBundle() {
+ CfbBundle bundle = m_bundle;
+ if (null == bundle) {
+ synchronized(CFB.class) {
+ if (null == m_bundle) {
+ m_bundle = bundle = CfbBundle.getInst(m_locale);
+ }
+ }
+ }
+ return bundle;
+ }
+
Options createOptions() {
Options opt = new Options();
}
String trans(String key) {
- return m_bundle.get(key);
+ return getBundle().get(key);
}
String getenv(String varName) {
MessageMap messageMap = new MessageMap();
messageMap.load(findBugsDir, Locale.getDefault(Category.DISPLAY));
+ if (!ensureDbInitialized(pw, messageMap)) {
+ return;
+ }
+
+ Analyzer analyzer = new Analyzer(messageMap);
+ Analysis analysis = analyzer.analyze(pw, workDir, m_fbp, m_projName, m_buildNum);
+ if (null == analysis) {
+ pw.println(trans(CfbBundle.ANALYSIS_FAILED));
+ return;
+ }
+
+ storeAndReport(pw, messageMap, analysis);
+ }
+
+ boolean ensureDbInitialized(PrintWriter pw, MessageMap messageMap)
+ throws TypeMismatchException
+ {
try (Connection con = m_driver.connect(
m_config.getDbHost(), m_config.getDbPort(),
m_config.getDbName(),
if (m_removeSchema) {
m_schema.purge(con);
- return;
+ return false; // do not continue execution
}
m_schema.ensureDbInitialized(con);
messageMap.loadIds(con, m_driver);
}
catch (SQLException exc) {
reportUnableToConnect(pw, exc);
- return;
- }
-
- Analyzer analyzer = new Analyzer(messageMap);
- Analysis analysis = analyzer.analyze(pw, workDir, m_fbp, m_projName, m_buildNum);
- if (null == analysis) {
- pw.println(trans(CfbBundle.ANALYSIS_FAILED));
- return;
+ return false; // do not continue execution
}
+ return true; // all OK; continue execution
+ }
+
+ void storeAndReport(PrintWriter pw, MessageMap messageMap, Analysis analysis)
+ throws TypeMismatchException, IOException
+ {
try (
Connection con = m_driver.connect(
m_config.getDbHost(), m_config.getDbPort(),
Analysis prior = store.getPrior(analysis);
Delta delta = new Delta(prior, analysis);
- HtmlReport report = new HtmlReport(m_bundle, messageMap.getColl(), delta);
+ HtmlReport report = new HtmlReport(getBundle(), messageMap.getColl(), delta);
if (null != m_output) {
report.write(m_output);
}
- Notifier notifier = new Notifier(m_bundle, m_config);
+ Notifier notifier = new Notifier(getBundle(), m_config);
notifier.sendEmailIfNeeded(pw, report);
}
catch (StoreException exc) {
exc.printStackTrace(pw);
- return;
}
catch (SQLException exc) {
reportUnableToConnect(pw, exc);
- return;
}
}
m_bundle = QDBundleFactory.getInst().getBundle(BUNDLE_NAME, locale);
}
+ // This constructor is intended only for use during unit testing.
+ CfbBundle() {
+ m_bundle = null;
+ }
+
public String get(String key, Object... arguments) {
try {
if (null != m_bundle) {
// Fall through to the fallback behaviour below
}
+ return fallbackGet(key, arguments);
+ }
+
+ String fallbackGet(String key, Object... arguments) {
StringBuilder sb = new StringBuilder("[" + key + "]");
for (Object obj : arguments) {
sb.append("[" + obj + "]");
}
return sb.toString();
+
}
}
--- /dev/null
+package net.jaekl.cfb;
+
+import java.util.Locale;
+
+import net.jaekl.cfb.db.CfbSchema;
+import net.jaekl.cfb.db.driver.DbDriver;
+
+public class CFBMock extends CFB {
+ private CfbBundleMock mock_bundle;
+
+ CFBMock(Locale locale, DbDriver driver)
+ {
+ super(locale);
+ m_driver = driver;
+ m_schema = new CfbSchema(m_driver);
+ mock_bundle = new CfbBundleMock();
+ }
+
+ @Override
+ CfbBundle getBundle()
+ {
+ return mock_bundle;
+ }
+}
--- /dev/null
+package net.jaekl.cfb;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Locale;
+
+import net.jaekl.cfb.analyze.Analysis;
+import net.jaekl.cfb.analyze.MessageMap;
+import net.jaekl.cfb.db.CfbSchema;
+import net.jaekl.cfb.db.Column;
+import net.jaekl.cfb.db.Condition;
+import net.jaekl.cfb.db.Operation;
+import net.jaekl.cfb.db.Row;
+import net.jaekl.cfb.db.Table;
+import net.jaekl.cfb.db.TypeMismatchException;
+import net.jaekl.cfb.db.driver.DbDriverMock;
+import net.jaekl.cfb.util.Command;
+import net.jaekl.cfb.xml.MessagesXmlData;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class CFBTest {
+ private CFBMock m_cfb;
+ private DbDriverMock m_driver;
+
+ private static final String BUG_COLLECTION_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + "<BugCollection version=\"2.0.3\" sequence=\"0\" timestamp=\"1425655198000\" analysisTimestamp=\"1451305502231\" release=\"\">"
+ + "<Project projectName=\"JUnit\">"
+ + "<Jar>/data/prog/findbugs-3.0.1/lib/junit.jar</Jar>"
+ + "</Project>"
+ + "<BugInstance type=\"VO_VOLATILE_INCREMENT\" priority=\"2\" abbrev=\"VO\" category=\"MT_CORRECTNESS\">"
+ + "<Class classname=\"junit.extensions.ActiveTestSuite\">"
+ + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+ + "</Class>"
+ + "<Method classname=\"junit.extensions.ActiveTestSuite\" name=\"runFinished\" signature=\"()V\" isStatic=\"false\">"
+ + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"69\" startBytecode=\"0\" endBytecode=\"64\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+ + "</Method>"
+ + "<Field classname=\"junit.extensions.ActiveTestSuite\" name=\"fActiveTestDeathCount\" signature=\"I\" isStatic=\"false\">"
+ + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+ + "</Field>"
+ + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+ + "</BugInstance>"
+ + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
+ + "<Class classname=\"junit.framework.Assert\">"
+ + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+ + "</Class>"
+ + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;BB)V\" isStatic=\"true\">"
+ + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"157\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+ + "</Method>"
+ + "<Method classname=\"java.lang.Byte\" name=\"<init>\" signature=\"(B)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
+ + "<SourceLine classname=\"java.lang.Byte\" start=\"307\" end=\"309\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
+ + "</Method>"
+ + "<Method classname=\"java.lang.Byte\" name=\"valueOf\" signature=\"(B)Ljava/lang/Byte;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
+ + "<SourceLine classname=\"java.lang.Byte\" start=\"87\" end=\"87\" startBytecode=\"0\" endBytecode=\"33\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
+ + "</Method>"
+ + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"156\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+ + "</BugInstance>"
+ + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
+ + "<Class classname=\"junit.framework.Assert\">"
+ + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+ + "</Class>"
+ + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;CC)V\" isStatic=\"true\">"
+ + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"170\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+ + "</Method>"
+ + "<Method classname=\"java.lang.Character\" name=\"<init>\" signature=\"(C)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
+ + "<SourceLine classname=\"java.lang.Character\" start=\"2056\" end=\"2058\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
+ + "</Method>"
+ + "<Method classname=\"java.lang.Character\" name=\"valueOf\" signature=\"(C)Ljava/lang/Character;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
+ + "<SourceLine classname=\"java.lang.Character\" start=\"2085\" end=\"2088\" startBytecode=\"0\" endBytecode=\"52\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
+ + "</Method>"
+ + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"169\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+ + "</BugInstance>"
+ + "</BugCollection>";
+
+ private Analysis analysisFromXml(String xml, String projectName, String version)
+ throws FileNotFoundException, IOException, SAXException
+ {
+ Analysis analysis = new Analysis(projectName, version);
+ ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes(Command.UTF_8));
+ InputSource inputSource = new InputSource(bais);
+ analysis.parse(inputSource);
+
+ return analysis;
+ }
+
+ @Before
+ public void setUp()
+ {
+ m_driver = new DbDriverMock();
+ m_cfb = new CFBMock(Locale.getDefault(), m_driver);
+ }
+
+ @Test
+ public void testStoreAndReport_noPrior() throws IOException, SQLException, SAXException, TypeMismatchException
+ {
+ final String PROJECT_NAME = "ProjectName";
+ final String VERSION = "1.0.1";
+
+ try (
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, Charset.forName(Command.UTF_8)));
+ )
+ {
+ MessageMap msgMap = new MessageMap();
+ msgMap.parse(new InputSource(new ByteArrayInputStream(MessagesXmlData.XML.getBytes(Command.UTF_8))));
+
+ Analysis analysis = analysisFromXml(BUG_COLLECTION_XML, PROJECT_NAME, VERSION);
+
+ m_cfb.ensureDbInitialized(pw, msgMap);
+ m_cfb.storeAndReport(pw, msgMap, analysis);
+ }
+
+ Connection con = m_driver.connect("host", 1234, "dbName", "dbUser", "dbPass");
+ Column[] columns = { CfbSchema.RUNID, CfbSchema.PROJNAME, CfbSchema.VERSION };
+ Table[] tables = { CfbSchema.RUNS };
+ Condition[] conditions = { new Condition(CfbSchema.RUNID, Operation.NOT_NULL) };
+
+ Row row = m_driver.selectExactlyOne(con, columns, tables, conditions);
+ assertNotNull(row);
+ assertEquals(PROJECT_NAME, row.getValue(1));
+ assertEquals(VERSION, row.getValue(2));
+ }
+}
--- /dev/null
+package net.jaekl.cfb;
+
+import java.util.Locale;
+
+public class CfbBundleMock extends CfbBundle {
+ public CfbBundleMock()
+ {
+ super();
+ synchronized(CfbBundle.class){
+ m_bundleMap.put(Locale.getDefault(), this);
+ }
+ }
+
+ @Override
+ public String get(String key, Object... arguments)
+ {
+ return fallbackGet(key, arguments);
+ }
+}
+ "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"101\" end=\"101\" startBytecode=\"46\" endBytecode=\"46\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\" role=\"SOURCE_REDUNDANT_NULL_CHECK\"/>\n"
+ "</BugInstance>\n";
- /*
private static String VO_VOLATILE_INCREMENT = ""
+ "<BugInstance type=\"VO_VOLATILE_INCREMENT\" priority=\"2\" abbrev=\"VO\" category=\"MT_CORRECTNESS\">"
+ "<Class classname=\"junit.extensions.ActiveTestSuite\">"
+ "</Field>"
+ "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+ "</BugInstance>";
- */
private static final String DM_NUMBER_CTOR_156 = ""
+ "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
}
@Test
- public void test_computeDeltas() throws FileNotFoundException, IOException, SAXException {
+ public void test_computeDeltas() throws FileNotFoundException, IOException, SAXException
+ {
String[][] bugSpecs = {
{ DM_DEFAULT_ENCODING, "DM_DEFAULT_ENCODING" },
{ RCN_REDUNDANT_NULL_CHECK, "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" },
}
}
+ @Test
+ public void test_deltaWithNoPrior() throws FileNotFoundException, IOException, SAXException
+ {
+ String[][] bugSpecs = {
+ { DM_DEFAULT_ENCODING, "DM_DEFAULT_ENCODING" },
+ { RCN_REDUNDANT_NULL_CHECK, "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" },
+ { VO_VOLATILE_INCREMENT, "VO_VOLATILE_INCREMENT" },
+ { DM_NUMBER_CTOR_156, "DM_NUMBER_CTOR" },
+ { DM_NUMBER_CTOR_169, "DM_NUMBER_CTOR" }
+ };
+
+ final String PROJECT_NAME = "AlphaOne";
+ String secondXml = buildXml(bugSpecs, 0, bugSpecs.length - 1);
+
+ Analysis second = analysisFromXml(secondXml, PROJECT_NAME, "1.0.1");
+
+ Delta delta = new Delta(null, second);
+
+ assertNotNull(delta);
+ for (int i = 0; i < bugSpecs.length; ++i) {
+ assertFalse(contains(delta.getCommon(), bugSpecs[i][1]));
+ assertFalse(contains(delta.getFixed(), bugSpecs[i][1]));
+ assertTrue(contains(delta.getNew(), bugSpecs[i][1]));
+ }
+ }
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
- // TODO Auto-generated method stub
- return null;
+ throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public class DbDriverMock extends DbDriver {
- private HashMap<String, TableMock> m_tables;
+ private ArrayList<ConnectionMock> m_cons;
private HashMap<String, SequenceMock> m_sequences;
+ private HashMap<String, TableMock> m_tables;
public DbDriverMock() {
super();
- m_tables = new HashMap<String, TableMock>();
+ m_cons = new ArrayList<ConnectionMock>();
m_sequences = new HashMap<String, SequenceMock>();
+ m_tables = new HashMap<String, TableMock>();
}
@Override
public Connection connect(String host, int port, String dbName, String user, String pass)
throws SQLException
{
- return null;
+ ConnectionMock con = new ConnectionMock();
+ m_cons.add(con);
+ return con;
}
@Override