From bedb0c5b72bcbbbcc2b8d11575ad99489aef6853 Mon Sep 17 00:00:00 2001 From: Chris Jaekl Date: Thu, 31 Dec 2015 18:48:02 +0900 Subject: [PATCH] Further unit tests: CFB and Delta --- prod/net/jaekl/cfb/CFB.java | 58 +++++--- prod/net/jaekl/cfb/CfbBundle.java | 10 ++ test/net/jaekl/cfb/CFBMock.java | 24 ++++ test/net/jaekl/cfb/CFBTest.java | 136 ++++++++++++++++++ test/net/jaekl/cfb/CfbBundleMock.java | 19 +++ test/net/jaekl/cfb/analyze/DeltaTest.java | 30 +++- .../jaekl/cfb/db/driver/ConnectionMock.java | 3 +- .../net/jaekl/cfb/db/driver/DbDriverMock.java | 10 +- 8 files changed, 266 insertions(+), 24 deletions(-) create mode 100644 test/net/jaekl/cfb/CFBMock.java create mode 100644 test/net/jaekl/cfb/CFBTest.java create mode 100644 test/net/jaekl/cfb/CfbBundleMock.java diff --git a/prod/net/jaekl/cfb/CFB.java b/prod/net/jaekl/cfb/CFB.java index 639a731..c97a1c8 100644 --- a/prod/net/jaekl/cfb/CFB.java +++ b/prod/net/jaekl/cfb/CFB.java @@ -42,7 +42,7 @@ import org.xml.sax.SAXException; public class CFB { DbDriver m_driver; CfbSchema m_schema; - CfbBundle m_bundle; + volatile static CfbBundle m_bundle = null; Locale m_locale; Config m_config; @@ -60,7 +60,7 @@ public class CFB { 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"); @@ -72,6 +72,18 @@ public class CFB { 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(); @@ -141,7 +153,7 @@ public class CFB { } String trans(String key) { - return m_bundle.get(key); + return getBundle().get(key); } String getenv(String varName) { @@ -187,6 +199,23 @@ public class CFB { 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(), @@ -197,23 +226,22 @@ public class CFB { 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(), @@ -228,21 +256,19 @@ public class CFB { 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; } } diff --git a/prod/net/jaekl/cfb/CfbBundle.java b/prod/net/jaekl/cfb/CfbBundle.java index 5f5aa9e..b46b290 100644 --- a/prod/net/jaekl/cfb/CfbBundle.java +++ b/prod/net/jaekl/cfb/CfbBundle.java @@ -58,6 +58,11 @@ public class CfbBundle { 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) { @@ -71,10 +76,15 @@ public class CfbBundle { // 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(); + } } diff --git a/test/net/jaekl/cfb/CFBMock.java b/test/net/jaekl/cfb/CFBMock.java new file mode 100644 index 0000000..b76876f --- /dev/null +++ b/test/net/jaekl/cfb/CFBMock.java @@ -0,0 +1,24 @@ +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; + } +} diff --git a/test/net/jaekl/cfb/CFBTest.java b/test/net/jaekl/cfb/CFBTest.java new file mode 100644 index 0000000..de10fe7 --- /dev/null +++ b/test/net/jaekl/cfb/CFBTest.java @@ -0,0 +1,136 @@ +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 = "" + + "" + + "" + + "/data/prog/findbugs-3.0.1/lib/junit.jar" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + 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)); + } +} diff --git a/test/net/jaekl/cfb/CfbBundleMock.java b/test/net/jaekl/cfb/CfbBundleMock.java new file mode 100644 index 0000000..71aea1d --- /dev/null +++ b/test/net/jaekl/cfb/CfbBundleMock.java @@ -0,0 +1,19 @@ +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); + } +} diff --git a/test/net/jaekl/cfb/analyze/DeltaTest.java b/test/net/jaekl/cfb/analyze/DeltaTest.java index 04f1dcd..cb2222c 100644 --- a/test/net/jaekl/cfb/analyze/DeltaTest.java +++ b/test/net/jaekl/cfb/analyze/DeltaTest.java @@ -44,7 +44,6 @@ public class DeltaTest { + "\n" + "\n"; - /* private static String VO_VOLATILE_INCREMENT = "" + "" + "" @@ -58,7 +57,6 @@ public class DeltaTest { + "" + "" + ""; - */ private static final String DM_NUMBER_CTOR_156 = "" + "" @@ -189,7 +187,8 @@ public class DeltaTest { } @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" }, @@ -208,4 +207,29 @@ public class DeltaTest { } } + @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])); + } + } } diff --git a/test/net/jaekl/cfb/db/driver/ConnectionMock.java b/test/net/jaekl/cfb/db/driver/ConnectionMock.java index b25a3fc..7734b88 100644 --- a/test/net/jaekl/cfb/db/driver/ConnectionMock.java +++ b/test/net/jaekl/cfb/db/driver/ConnectionMock.java @@ -229,8 +229,7 @@ public class ConnectionMock implements Connection { @Override public PreparedStatement prepareStatement(String sql) throws SQLException { - // TODO Auto-generated method stub - return null; + throw new UnsupportedOperationException("Not yet implemented"); } @Override diff --git a/test/net/jaekl/cfb/db/driver/DbDriverMock.java b/test/net/jaekl/cfb/db/driver/DbDriverMock.java index bb4675a..927f276 100644 --- a/test/net/jaekl/cfb/db/driver/DbDriverMock.java +++ b/test/net/jaekl/cfb/db/driver/DbDriverMock.java @@ -25,13 +25,15 @@ import net.jaekl.cfb.util.Util; public class DbDriverMock extends DbDriver { - private HashMap m_tables; + private ArrayList m_cons; private HashMap m_sequences; + private HashMap m_tables; public DbDriverMock() { super(); - m_tables = new HashMap(); + m_cons = new ArrayList(); m_sequences = new HashMap(); + m_tables = new HashMap(); } @Override @@ -43,7 +45,9 @@ public class DbDriverMock extends DbDriver { 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 -- 2.39.2