Further unit tests: loading a variable.
[cfb.git] / test / net / jaekl / cfb / store / DbStoreTest.java
1 package net.jaekl.cfb.store;
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.assertNull;
7 import static org.junit.Assert.assertTrue;
8 import static org.junit.Assert.fail;
9
10 import java.io.ByteArrayInputStream;
11 import java.io.FileNotFoundException;
12 import java.io.IOException;
13 import java.io.UnsupportedEncodingException;
14 import java.nio.charset.Charset;
15 import java.sql.SQLException;
16 import java.util.Date;
17
18 import net.jaekl.cfb.analyze.Analysis;
19 import net.jaekl.cfb.analyze.MessageMap;
20 import net.jaekl.cfb.db.CfbSchema;
21 import net.jaekl.cfb.db.TypeMismatchException;
22 import net.jaekl.cfb.db.driver.ConnectionMock;
23 import net.jaekl.cfb.db.driver.DbDriverMock;
24 import net.jaekl.cfb.util.Command;
25 import net.jaekl.cfb.xml.BugCollection;
26 import net.jaekl.cfb.xml.LocalVariable;
27 import net.jaekl.cfb.xml.MessagesXmlData;
28
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.xml.sax.InputSource;
32 import org.xml.sax.SAXException;
33
34 public class DbStoreTest {      
35         private static final String BUG_COLLECTION_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
36                         + "<BugCollection version=\"2.0.3\" sequence=\"0\" timestamp=\"1425655198000\" analysisTimestamp=\"1451305502231\" release=\"\">"
37                         + "<Project projectName=\"JUnit\">"
38                         + "<Jar>/data/prog/findbugs-3.0.1/lib/junit.jar</Jar>"
39                         + "</Project>"
40                         + "<BugInstance type=\"VO_VOLATILE_INCREMENT\" priority=\"2\" abbrev=\"VO\" category=\"MT_CORRECTNESS\">"
41                         + "<Class classname=\"junit.extensions.ActiveTestSuite\">"
42                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
43                         + "</Class>"
44                         + "<Method classname=\"junit.extensions.ActiveTestSuite\" name=\"runFinished\" signature=\"()V\" isStatic=\"false\">"
45                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"69\" startBytecode=\"0\" endBytecode=\"64\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
46                         + "</Method>"
47                         + "<Field classname=\"junit.extensions.ActiveTestSuite\" name=\"fActiveTestDeathCount\" signature=\"I\" isStatic=\"false\">"
48                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
49                         + "</Field>"
50                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
51                         + "</BugInstance>"
52                         + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
53                         + "<Class classname=\"junit.framework.Assert\">"
54                         + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
55                         + "</Class>"
56                         + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;BB)V\" isStatic=\"true\">"
57                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"157\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
58                         + "</Method>"
59                         + "<Method classname=\"java.lang.Byte\" name=\"&lt;init&gt;\" signature=\"(B)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
60                         + "<SourceLine classname=\"java.lang.Byte\" start=\"307\" end=\"309\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
61                         + "</Method>"
62                         + "<Method classname=\"java.lang.Byte\" name=\"valueOf\" signature=\"(B)Ljava/lang/Byte;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
63                         + "<SourceLine classname=\"java.lang.Byte\" start=\"87\" end=\"87\" startBytecode=\"0\" endBytecode=\"33\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
64                         + "</Method>"
65                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"156\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
66                         + "</BugInstance>"
67                         + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
68                         + "<Class classname=\"junit.framework.Assert\">"
69                         + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
70                         + "</Class>"
71                         + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;CC)V\" isStatic=\"true\">"
72                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"170\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
73                         + "</Method>"
74                         + "<Method classname=\"java.lang.Character\" name=\"&lt;init&gt;\" signature=\"(C)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
75                         + "<SourceLine classname=\"java.lang.Character\" start=\"2056\" end=\"2058\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
76                         + "</Method>"
77                         + "<Method classname=\"java.lang.Character\" name=\"valueOf\" signature=\"(C)Ljava/lang/Character;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
78                         + "<SourceLine classname=\"java.lang.Character\" start=\"2085\" end=\"2088\" startBytecode=\"0\" endBytecode=\"52\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
79                         + "</Method>"
80                         + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"169\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
81                         + "</BugInstance>"
82                         + "</BugCollection>";
83         
84         private static final String UNKNOWN_BUG_CATEGORY_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
85                         + "<BugCollection version=\"2.0.3\" sequence=\"0\" timestamp=\"1425655198000\" analysisTimestamp=\"1451305502231\" release=\"\">"
86                         + "<Project projectName=\"JUnit\">"
87                         + "<Jar>/data/prog/findbugs-3.0.1/lib/junit.jar</Jar>"
88                         + "</Project>"
89                         + "<BugInstance type=\"VO_VOLATILE_INCREMENT\" priority=\"2\" abbrev=\"VO\" category=\"NON_EXTANT\">"
90                         + "<Class classname=\"junit.extensions.ActiveTestSuite\">"
91                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
92                         + "</Class>"
93                         + "<Method classname=\"junit.extensions.ActiveTestSuite\" name=\"runFinished\" signature=\"()V\" isStatic=\"false\">"
94                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"69\" startBytecode=\"0\" endBytecode=\"64\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
95                         + "</Method>"
96                         + "<Field classname=\"junit.extensions.ActiveTestSuite\" name=\"fActiveTestDeathCount\" signature=\"I\" isStatic=\"false\">"
97                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
98                         + "</Field>"
99                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
100                         + "</BugInstance>"
101                         + "</BugCollection>";
102
103         private static final String UNKNOWN_BUG_PATTERN_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
104                         + "<BugCollection version=\"2.0.3\" sequence=\"0\" timestamp=\"1425655198000\" analysisTimestamp=\"1451305502231\" release=\"\">"
105                         + "<Project projectName=\"JUnit\">"
106                         + "<Jar>/data/prog/findbugs-3.0.1/lib/junit.jar</Jar>"
107                         + "</Project>"
108                         + "<BugInstance type=\"DN_DOES_NOT_EXIST\" priority=\"2\" abbrev=\"DN\" category=\"MT_CORRECTNESS\">"
109                         + "<Class classname=\"junit.extensions.ActiveTestSuite\">"
110                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
111                         + "</Class>"
112                         + "<Method classname=\"junit.extensions.ActiveTestSuite\" name=\"runFinished\" signature=\"()V\" isStatic=\"false\">"
113                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"69\" startBytecode=\"0\" endBytecode=\"64\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
114                         + "</Method>"
115                         + "<Field classname=\"junit.extensions.ActiveTestSuite\" name=\"fActiveTestDeathCount\" signature=\"I\" isStatic=\"false\">"
116                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
117                         + "</Field>"
118                         + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
119                         + "</BugInstance>"
120                         + "</BugCollection>";
121         
122         private DbStore m_store;
123         
124         @Before
125         public void setUp() throws SQLException, FileNotFoundException, UnsupportedEncodingException, IOException, SAXException 
126         {
127                 MessageMap msgMap = new MessageMap();
128                 msgMap.parse(new InputSource(new ByteArrayInputStream(MessagesXmlData.XML.getBytes("UTF-8"))));
129                 
130                 DbDriverMock driver = new DbDriverMock();
131                 CfbSchema schema = new CfbSchema(driver);
132                 ConnectionMock con = new ConnectionMock();
133
134                 schema.setMessageMap(msgMap);
135                 schema.ensureDbInitialized(con);                
136
137                 m_store = new DbStore(con, driver, msgMap.getColl());
138         }
139
140         @Test
141         public void testGetPrior_withNoEntries() throws SQLException, TypeMismatchException, StoreException {
142                 // First test:  getPrior(null) should return null
143                 Analysis actual = m_store.getPrior(null);
144                 assertNull(actual);
145                 
146                 // Second test:  getPrior(current) with no data in the DB should return null
147                 String projName = "ProjectName";
148                 String version = "1.2.3";
149                 Date start = new Date(1234567890);
150                 Date end = new Date(1234567900);
151                 Analysis current = new Analysis(projName, version);
152                 current.setStart(start);
153                 current.setEnd(end);
154                 actual = m_store.getPrior(current);
155                 assertNull(actual);
156         }
157         
158         private BugCollection parseBugCollection(String xml) throws IOException, SAXException
159         {
160                 Charset utf8 = Charset.forName(Command.UTF_8);
161                 
162                 try ( ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes(utf8)))
163                 {
164                         InputSource inputSource = new InputSource(bais); 
165                         Analysis analysis = new Analysis(null, null);
166                         analysis.parse(inputSource);
167                         
168                         assertNotNull(analysis);
169                         
170                         BugCollection bugColl = analysis.getBugCollection();
171                         return bugColl;
172                 }
173         }
174         
175         @Test
176         public void testPut_null() throws StoreException, SQLException, TypeMismatchException
177         {
178                 // Adding null should return false, with no exception thrown
179                 boolean result = m_store.put(null);
180                 assertFalse(result);            
181         }
182         
183         @Test
184         public void testPut_withUnknownPatternOrCategory() throws SQLException, TypeMismatchException, IOException, SAXException 
185         {
186                 final String[] data = { UNKNOWN_BUG_PATTERN_XML, UNKNOWN_BUG_CATEGORY_XML};
187                 String projName = "ProjectName";
188                 String firstVersion = "1.0.1";
189                 Date firstStart = new Date(100);
190                 Date firstEnd = new Date(200);
191                 Analysis firstAnalysis = new Analysis(projName, firstVersion);
192                 firstAnalysis.setStart(firstStart);
193                 firstAnalysis.setEnd(firstEnd);
194
195                 for (String xml : data) {
196                         firstAnalysis.setBugCollection(parseBugCollection(xml));
197
198                         try {
199                                 m_store.put(firstAnalysis);
200                                 fail("Should have thrown an exception\n" + xml);
201                         }
202                         catch (StoreException exc) {
203                                 // This is the success path
204                         }
205                 }
206         }
207
208         @Test
209         public void testPut_thenGetPrior() throws SQLException, TypeMismatchException, IOException, SAXException, StoreException {
210                 String projName = "ProjectName";
211                 String firstVersion = "1.0.1";
212                 Date firstStart = new Date(100);
213                 Date firstEnd = new Date(200);
214                 Analysis firstAnalysis = new Analysis(projName, firstVersion);
215                 firstAnalysis.setStart(firstStart);
216                 firstAnalysis.setEnd(firstEnd);
217                 firstAnalysis.setBugCollection(parseBugCollection(BUG_COLLECTION_XML));
218                 
219                 // Adding a valid Analysis object should return true
220                 boolean result = m_store.put(firstAnalysis);
221                 assertTrue(result);
222                 
223                 // Create a second Analysis object
224                 String secondVersion = "1.0.2";
225                 Date secondStart = new Date(2300);
226                 Date secondEnd = new Date(2400);
227                 Analysis secondAnalysis = new Analysis(projName, secondVersion);
228                 secondAnalysis.setStart(secondStart);
229                 secondAnalysis.setEnd(secondEnd);
230                 
231                 // Retrieve the first Analysis object
232                 Analysis priorAnalysis = m_store.getPrior(secondAnalysis);
233                 assertNotNull(priorAnalysis);
234                 assertEquals(firstAnalysis.getProjectName(), priorAnalysis.getProjectName());
235                 assertEquals(firstAnalysis.getBuildNumber(), priorAnalysis.getBuildNumber());
236                 assertEquals(firstAnalysis.getStart(), priorAnalysis.getStart());
237                 assertEquals(firstAnalysis.getEnd(), priorAnalysis.getEnd());
238                 assertEquals(firstAnalysis.getBugCollection(), priorAnalysis.getBugCollection());
239         }
240
241         @Test
242         public void testGetLocId_nullReturnsNull() throws SQLException, TypeMismatchException {
243                 Long locId = m_store.getLocId(null);
244                 assertNull(locId);
245         }
246
247         @Test
248         public void testGetLocId_notFoundIsStored() throws SQLException, TypeMismatchException {
249                 Location loc = new Location(1234567890L, 
250                                                                         "ThisClassDoesNotExist", 
251                                                                         "thisMethodDoesNotExist", 
252                                                                         "INVALID_METHOD_ROLE", 
253                                                                         0, 90909);
254                 Long locId = m_store.getLocId(loc);
255                 assertNotNull(locId);
256                 assertTrue(locId.longValue() > 0);
257                 
258                 Long secondLocId = m_store.getLocId(loc);
259                 assertEquals(locId, secondLocId);
260         }
261
262         @Test
263         public void testGetLoc_nullReturnsNull() throws SQLException, TypeMismatchException, StoreException {
264                 Location loc = m_store.getLoc(null);
265                 assertNull(loc);
266         }
267         
268         @Test
269         public void testGetLoc_invalidId() throws SQLException, TypeMismatchException {
270                 try {
271                         m_store.getLoc(Long.valueOf(-3));
272                         fail("Should have thrown a StoreException");
273                 }
274                 catch (StoreException exc) {
275                         assertEquals(StoreException.Type.INVALID_LOC_ID, exc.getType());
276                 }
277         }
278         
279         @Test
280         public void testGetVar_nullReturnsNull() throws SQLException, TypeMismatchException, StoreException {
281                 LocalVariable var = m_store.getVar(null);
282                 assertNull(var);
283         }
284         
285         @Test
286         public void testGetVar_invalidId() throws SQLException, TypeMismatchException {
287                 try {
288                         m_store.getVar(Long.valueOf(-3));
289                         fail("Should have thrown a StoreException");
290                 }
291                 catch (StoreException exc) {
292                         assertEquals(StoreException.Type.INVALID_VAR_ID, exc.getType());
293                 }
294         }
295
296         @Test
297         public void testGetVarId_notFoundIsStored() throws SQLException, TypeMismatchException, StoreException {
298                 LocalVariable var = new LocalVariable(2345678901L, "VariableNameDoesNotYetExist", "VARIABLE_READ");
299
300                 Long varId = m_store.getVarId(var);
301                 assertNotNull(varId);
302                 assertTrue(varId.longValue() > 0);
303                 
304                 Long secondVarId = m_store.getVarId(var);
305                 assertEquals(varId, secondVarId);
306                 
307                 LocalVariable loadedVar = m_store.getVar(secondVarId);
308                 assertEquals(var, loadedVar);
309         }
310 }