Address some edge cases related to bootstrapping a fresh system.
[cfb.git] / test / net / jaekl / cfb / CFBTest.java
1 package net.jaekl.cfb;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotNull;
6 import static org.junit.Assert.assertTrue;
7
8 import java.io.ByteArrayInputStream;
9 import java.io.ByteArrayOutputStream;
10 import java.io.FileNotFoundException;
11 import java.io.IOException;
12 import java.io.OutputStreamWriter;
13 import java.io.PrintWriter;
14 import java.io.StringWriter;
15 import java.nio.charset.Charset;
16 import java.sql.Connection;
17 import java.sql.SQLException;
18 import java.util.Locale;
19
20 import net.jaekl.cfb.analyze.Analysis;
21 import net.jaekl.cfb.analyze.FBMsgFileNotFoundException;
22 import net.jaekl.cfb.analyze.MessageMap;
23 import net.jaekl.cfb.db.CfbSchema;
24 import net.jaekl.cfb.db.Column;
25 import net.jaekl.cfb.db.Condition;
26 import net.jaekl.cfb.db.Operation;
27 import net.jaekl.cfb.db.Row;
28 import net.jaekl.cfb.db.Table;
29 import net.jaekl.cfb.db.TypeMismatchException;
30 import net.jaekl.cfb.db.driver.DbDriverMock;
31 import net.jaekl.cfb.util.Command;
32 import net.jaekl.cfb.util.EnvMock;
33 import net.jaekl.cfb.xml.MessagesXmlData;
34
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.xml.sax.InputSource;
38 import org.xml.sax.SAXException;
39
40 public class CFBTest {
41         private CFBMock m_cfb;
42         private DbDriverMock m_driver;
43         
44         private static final String BUG_COLLECTION_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
45                         + "<BugCollection version=\"2.0.3\" sequence=\"0\" timestamp=\"1425655198000\" analysisTimestamp=\"1451305502231\" release=\"\">"
46                         + "<Project projectName=\"JUnit\">"
47                         + "<Jar>/data/prog/findbugs-3.0.1/lib/junit.jar</Jar>"
48                         + "</Project>"
49                         + "<BugInstance type=\"VO_VOLATILE_INCREMENT\" priority=\"2\" abbrev=\"VO\" category=\"MT_CORRECTNESS\">"
50                         + "<Class classname=\"junit.extensions.ActiveTestSuite\">"
51                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
52                         + "</Class>"
53                         + "<Method classname=\"junit.extensions.ActiveTestSuite\" name=\"runFinished\" signature=\"()V\" isStatic=\"false\">"
54                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"69\" startBytecode=\"0\" endBytecode=\"64\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
55                         + "</Method>"
56                         + "<Field classname=\"junit.extensions.ActiveTestSuite\" name=\"fActiveTestDeathCount\" signature=\"I\" isStatic=\"false\">"
57                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
58                         + "</Field>"
59                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
60                         + "</BugInstance>"
61                         + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
62                         + "<Class classname=\"junit.framework.Assert\">"
63                         + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
64                         + "</Class>"
65                         + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;BB)V\" isStatic=\"true\">"
66                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"157\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
67                         + "</Method>"
68                         + "<Method classname=\"java.lang.Byte\" name=\"&lt;init&gt;\" signature=\"(B)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
69                         + "<SourceLine classname=\"java.lang.Byte\" start=\"307\" end=\"309\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
70                         + "</Method>"
71                         + "<Method classname=\"java.lang.Byte\" name=\"valueOf\" signature=\"(B)Ljava/lang/Byte;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
72                         + "<SourceLine classname=\"java.lang.Byte\" start=\"87\" end=\"87\" startBytecode=\"0\" endBytecode=\"33\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
73                         + "</Method>"
74                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"156\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
75                         + "</BugInstance>"
76                         + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
77                         + "<Class classname=\"junit.framework.Assert\">"
78                         + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
79                         + "</Class>"
80                         + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;CC)V\" isStatic=\"true\">"
81                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"170\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
82                         + "</Method>"
83                         + "<Method classname=\"java.lang.Character\" name=\"&lt;init&gt;\" signature=\"(C)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
84                         + "<SourceLine classname=\"java.lang.Character\" start=\"2056\" end=\"2058\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
85                         + "</Method>"
86                         + "<Method classname=\"java.lang.Character\" name=\"valueOf\" signature=\"(C)Ljava/lang/Character;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
87                         + "<SourceLine classname=\"java.lang.Character\" start=\"2085\" end=\"2088\" startBytecode=\"0\" endBytecode=\"52\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
88                         + "</Method>"
89                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"169\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
90                         + "</BugInstance>"
91                         + "</BugCollection>";
92
93         private Analysis analysisFromXml(String xml, String projectName, String version) 
94                         throws FileNotFoundException, IOException, SAXException 
95         {
96                 Analysis analysis = new Analysis(projectName, version);
97                 ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes(Command.UTF_8));
98                 InputSource inputSource = new InputSource(bais); 
99                 analysis.parse(inputSource);
100                 
101                 return analysis;
102         }
103                 
104         @Before
105         public void setUp()
106         {
107                 m_driver = new DbDriverMock();
108                 m_cfb = new CFBMock(Locale.getDefault(), m_driver);
109         }
110         
111         @Test
112         public void testParseArgs_noParams() throws IOException 
113         {
114                 StringWriter sw = new StringWriter();
115                 PrintWriter pw = new PrintWriter(sw);
116                 String[] args = {};
117                 
118                 boolean result = m_cfb.parseArgs(pw, args);
119                 pw.close();
120                 sw.close();
121                 
122                 assertFalse(result);
123                 assertEquals("[must.specify.fbp.file]\n[invoke.with.help.for.help]\n", sw.toString());
124         }
125         
126         @Test
127         public void testParseArgs_dropTables() throws IOException
128         {
129                 StringWriter sw = new StringWriter();
130                 PrintWriter pw = new PrintWriter(sw);
131                 String[] args = { "--drop-tables" };
132                 
133                 boolean result = m_cfb.parseArgs(pw, args);
134                 pw.close();
135                 sw.close();
136                 
137                 assertTrue(result);
138                 assertEquals("", sw.toString());
139         }
140         
141         @Test
142         public void testParseArgs_invalidParam() throws IOException
143         {
144                 StringWriter sw = new StringWriter();
145                 PrintWriter pw = new PrintWriter(sw);
146                 String[] args = {"--xyzzyaoeuidhtnsl"};
147                 
148                 boolean result = m_cfb.parseArgs(pw, args);
149                 pw.close();
150                 sw.close();
151                 String actual = sw.toString();
152                 
153                 assertFalse(result);
154                 assertTrue(actual.contains("usage"));
155                 assertTrue(actual.contains("--help"));
156         }
157         
158         @Test
159         public void testStoreAndReport_noPrior() throws IOException, SQLException, SAXException, TypeMismatchException 
160         {
161                 final String PROJECT_NAME = "ProjectName";
162                 final String VERSION = "1.0.1";
163                 
164                 try (
165                                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
166                                 PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos, Charset.forName(Command.UTF_8)));
167                         )
168                 {
169                         MessageMap msgMap = new MessageMap();
170                         msgMap.parse(new InputSource(new ByteArrayInputStream(MessagesXmlData.XML.getBytes(Command.UTF_8))));
171                         
172                         Analysis analysis = analysisFromXml(BUG_COLLECTION_XML, PROJECT_NAME, VERSION);
173                         
174                         m_cfb.ensureDbInitialized(pw, msgMap);
175                         m_cfb.storeAndReport(pw, msgMap, analysis);
176                 }
177                 
178                 Connection con = m_driver.connect("host", 1234, "dbName", "dbUser", "dbPass");
179                 Column[] columns = { CfbSchema.RUNID, CfbSchema.PROJNAME, CfbSchema.VERSION };
180                 Table[] tables = { CfbSchema.RUNS };
181                 Condition[] conditions = { new Condition(CfbSchema.RUNID, Operation.NOT_NULL) };
182                 
183                 Row row = m_driver.selectExactlyOne(con, columns, tables, conditions);
184                 assertNotNull(row);
185                 assertEquals(PROJECT_NAME, row.getValue(1));
186                 assertEquals(VERSION, row.getValue(2));
187         }
188         
189         @Test
190         public void testTrans()
191         {
192                 Object[][] data = {
193                                 { "hello", new Object[] {}, "[hello]" },
194                                 { "hello", new Object[] {"world"}, "[hello][world]"}    
195                         };
196                 
197                 for (Object[] datum : data) {
198                         String key = (String)datum[0];
199                         Object[] params = (Object[])datum[1];
200                         String expected = (String)datum[2];
201                         String actual = m_cfb.trans(key, params);
202                         assertEquals(expected, actual);
203                 }
204         }
205         
206         @Test
207         public void testReportException_FBMsgFileNotFoundException() throws IOException
208         {
209                 String[][] data = {
210                                 { 
211                                         "/home/fred/findbugs3.0.1", "messages.xml", 
212                                         "[cannot.load.fbmsg.file][messages.xml]\n[findbugs.home.is.set.to][FINDBUGS_HOME][/home/fred/findbugs3.0.1]\n"
213                                 },
214                                 { 
215                                         null, "messages.xml", 
216                                         "[cannot.load.fbmsg.file][messages.xml]\n[findbugs.home.is.not.set][FINDBUGS_HOME]\n"
217                                 },
218                                 { 
219                                         null, null, "[cannot.load.fbmsg.file][null]\n[findbugs.home.is.not.set][FINDBUGS_HOME]\n" 
220                                 }
221                 };
222
223                 try {
224                         EnvMock envMock = EnvMock.mock_putInstance();
225                         
226                         for (String[] datum : data) 
227                         {
228                                 String fbHome = datum[0];
229                                 String filename = datum[1];
230                                 String expected = datum[2];
231                                 
232                                 try (
233                                                 StringWriter sw = new StringWriter();
234                                                 PrintWriter pw = new PrintWriter(sw);
235                                         )
236                                 {
237                                         envMock.mock_putEnv(CFB.FINDBUGS_HOME, fbHome);
238                                         FBMsgFileNotFoundException exc = new FBMsgFileNotFoundException(filename);
239                                         m_cfb.reportException(pw, exc);
240                                         
241                                         pw.close();
242                                         sw.close();
243                                         
244                                         String actual = sw.toString();
245                                         boolean pass = actual.endsWith(expected);
246                                         if (!pass) {
247                                                 System.out.println("Expected:\n" + expected + "\nActual:\n" + actual);
248                                         }
249                                         assertTrue(pass);
250                                 }
251                         }
252                 }
253                 finally {
254                         EnvMock.mock_resetInstance();
255                 }
256         }
257 }