1   /*
2       StatCvs - CVS statistics generation 
3       Copyright (C) 2002  Lukasz Pekacki <lukasz@pekacki.de>
4       http://statcvs.sf.net/
5       
6       This library is free software; you can redistribute it and/or
7       modify it under the terms of the GNU Lesser General Public
8       License as published by the Free Software Foundation; either
9       version 2.1 of the License, or (at your option) any later version.
10  
11      This library is distributed in the hope that it will be useful,
12      but WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      Lesser General Public License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public
17      License along with this library; if not, write to the Free Software
18      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19      
20  	$RCSfile: LinesOfCodeTest.java,v $ 
21  	Created on $Date: 2008/04/02 11:22:14 $ 
22  */
23  
24  package net.sf.statcvs.input;
25  
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.Date;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.List;
32  
33  import junit.framework.TestCase;
34  import net.sf.statcvs.model.Revision;
35  import net.sf.statcvs.model.VersionedFile;
36  
37  /**
38   * Test cases for {@link Builder}, covering LOC calculations.
39   * 
40   * TODO: most/all of them test only the FileBuilder -- refactor!
41   * 
42   * @author Anja Jentzsch
43   * @author Richard Cyganiak
44   * @see BuilderTest
45   * @version $Id: LinesOfCodeTest.java,v 1.22 2008/04/02 11:22:14 benoitx Exp $
46   */
47  public class LinesOfCodeTest extends TestCase {
48      private Builder builder;
49      private VersionedFile file;
50      private Date date11;
51      private Date date12;
52      private Date date13;
53      private Date date14;
54      private Date date15;
55      private Revision rev0;
56      private Revision rev1;
57      private Revision rev2;
58      private Revision rev3;
59      private Revision rev4;
60      private DummyRepositoryFileManager fileman;
61  
62      /**
63       * Constructor
64       * @param arg0 input
65       */
66      public LinesOfCodeTest(final String arg0) {
67          super(arg0);
68      }
69  
70      /**
71       * @see TestCase#setUp()
72       */
73      protected void setUp() throws Exception {
74          super.setUp();
75          fileman = new DummyRepositoryFileManager();
76          builder = new Builder(fileman, null, null, null);
77          builder.buildFile("file", false, false, new HashMap());
78          file = null;
79          date11 = new Date(1100000000);
80          date12 = new Date(1200000000);
81          date13 = new Date(1300000000);
82          date14 = new Date(1400000000);
83          date15 = new Date(1500000000);
84          rev0 = null;
85          rev1 = null;
86          rev2 = null;
87          rev3 = null;
88          rev4 = null;
89      }
90  
91      /**
92       * Method testLinesOfCodeWithoutRepository1.
93       */
94      public void testLinesOfCodeWithoutRepository1() throws Exception {
95          buildRevision("1.2", date12, 5, 0);
96          buildRevisionInitial("1.1", date11);
97          finishBuilder();
98          assertEquals(5, file.getCurrentLinesOfCode());
99          assertRevisionLines(rev0, 5, 5, 5);
100         assertRevisionLines(rev1, 0, 0, 0);
101     }
102 
103     /**
104      * Method testLinesOfCodeWithoutRepository2.
105      */
106     public void testLinesOfCodeWithoutRepository2() throws Exception {
107         buildRevision("1.2", date12, 0, 5);
108         buildRevisionInitial("1.1", date11);
109         finishBuilder();
110         assertEquals(0, file.getCurrentLinesOfCode());
111         assertRevisionLines(rev0, 0, -5, 0);
112         assertRevisionLines(rev1, 5, 5, 5);
113     }
114 
115     /**
116      * Method testLinesOfCodeWithoutRepository3.
117      */
118     public void testLinesOfCodeWithoutRepository3() throws Exception {
119         buildRevision("1.5", date15, 10, 15);
120         buildRevision("1.4", date14, 10, 0);
121         buildRevision("1.3", date13, 25, 15);
122         buildRevision("1.2", date12, 10, 0);
123         buildRevisionInitial("1.1", date11);
124         finishBuilder();
125         assertEquals(30, file.getCurrentLinesOfCode());
126         assertRevisionLines(rev0, 30, -5, 10);
127         assertRevisionLines(rev1, 35, 10, 10);
128         assertRevisionLines(rev2, 25, 10, 25);
129         assertRevisionLines(rev3, 15, 10, 10);
130         assertRevisionLines(rev4, 5, 5, 5);
131     }
132 
133     /**
134      * Test a file whose initial revision is dead (this means it was
135      * added on another branch). The builder should filter this file,
136      * so the CvsContent should be empty.
137      */
138     public void testLinesOfCodeDeadInitial() throws Exception {
139         buildRevisionDead("1.1", date11);
140         finishBuilder();
141         assertNull(rev0);
142     }
143 
144     /**
145      * Test a file whose initial revision is dead (this means it was
146      * added on another branch), but that was later merged into the
147      * trunk.
148      */
149     public void testLinesOfCodeDeadInitialMerged() throws Exception {
150         buildRevision("1.2", date12, 10, 0);
151         buildRevisionDead("1.1", date11);
152         fileman.setLinesOfCode("file", 10);
153         finishBuilder();
154         assertTrue(rev0.isInitialRevision());
155         assertRevisionLines(rev0, 10, 10, 10);
156         assertEquals(1, file.getRevisions().size());
157     }
158 
159     /**
160      * Simple test to make sure that the Builder pulls the LOC number
161      * from the RepositoryFileManager
162      */
163     public void testLinesOfCodeInitial() throws Exception {
164         fileman.setLinesOfCode("file", 100);
165         buildRevisionInitial("1.1", date11);
166         finishBuilder();
167         assertEquals(100, file.getCurrentLinesOfCode());
168         assertRevisionLines(rev0, 100, 100, 100);
169     }
170 
171     /**
172      * Test to make sure that LOC count for binary files is 0
173      */
174     public void testLinesOfCodeBinary() throws Exception {
175         fileman.setLinesOfCode("binaryfile", 100);
176         builder.buildFile("binaryfile", true, false, new HashMap());
177         buildRevisionInitial("1.1", date11);
178         finishBuilder();
179 
180         // get "binaryfile"
181         file = (VersionedFile) builder.createCvsContent().getFiles().first();
182         assertEquals(0, file.getCurrentLinesOfCode());
183         rev0 = (Revision) file.getRevisions().first();
184         assertRevisionLines(rev0, 0, 0, 0);
185     }
186 
187     /**
188      * Test the behaviour of a deleted file, for which no HEAD LOC count
189      * is available.
190      */
191     public void testLinesOfCodeWithDeletion() throws Exception {
192         buildRevisionDead("1.3", date13);
193         buildRevision("1.2", date12, 100, 0);
194         buildRevisionInitial("1.1", date11);
195         finishBuilder();
196         assertTrue(file.isDead());
197         assertEquals(0, file.getCurrentLinesOfCode());
198         //TODO: WTF should LOC for a deleted file be 100? Counter-intuitive.
199         assertRevisionLines(rev0, 0, -100, 0);
200         assertRevisionLines(rev1, 100, 100, 100);
201         assertRevisionLines(rev2, 0, 0, 0);
202     }
203 
204     /**
205      * Tests the behaviour for deleted and re-added files.
206      */
207     public void testLinesOfCodeWithRestore() throws Exception {
208         fileman.setLinesOfCode("file", 100);
209         buildRevision("1.3", date13, 0, 0);
210         buildRevisionDead("1.2", date12);
211         buildRevisionInitial("1.1", date11);
212         finishBuilder();
213         assertTrue(!file.isDead());
214         assertEquals(100, file.getCurrentLinesOfCode());
215         assertTrue(rev0.isInitialRevision());
216         assertRevisionLines(rev0, 100, 100, 100);
217         assertTrue(rev1.isDead());
218         assertRevisionLines(rev1, 0, -100, 0);
219         assertTrue(rev2.isInitialRevision());
220         assertRevisionLines(rev2, 100, 100, 100);
221     }
222 
223     /**
224      * Tests if "cvs log -d" logs work correctly when the file
225      * has no revisions in the -d timespan, but it did exist
226      */
227     public void testPartialLogZeroRevisions() throws Exception {
228         fileman.setLinesOfCode("file", 100);
229         addAnotherFile();
230         finishBuilder();
231         assertNotNull(file);
232         assertEquals(1, file.getRevisions().size());
233         assertTrue(rev0.isBeginOfLog());
234         assertNull(rev0.getAuthor());
235         assertEquals(100, rev0.getLines());
236         assertEquals(0, rev0.getReplacedLines());
237         assertEquals(0, rev0.getLinesDelta());
238     }
239 
240     /**
241      * Tests if "cvs log -d" logs work correctly when the file
242      * did not exist during the -d timespan (that is, it was
243      * added at a later date, or removed before the start date)
244      */
245     public void testPartialLogZeroRevisionsNoFile() throws Exception {
246         addAnotherFile();
247         finishBuilder();
248         assertNull(file);
249     }
250 
251     public void testPartialLogOneRevision() throws Exception {
252         fileman.setLinesOfCode("file", 100);
253         buildRevision("1.5", date15, 80, 30);
254         finishBuilder();
255         assertEquals(2, file.getRevisions().size());
256         assertEquals("1.5", rev0.getRevisionNumber());
257         assertEquals("0.0", rev1.getRevisionNumber());
258         assertTrue(rev1.isBeginOfLog());
259         assertRevisionLines(rev0, 100, 50, 80);
260         assertRevisionLines(rev1, 50, 0, 0);
261     }
262 
263     private void buildRevision(final String revision, final Date date, final int linesAdded, final int linesRemoved) {
264         final RevisionData data = new RevisionData();
265         data.setStateExp();
266         data.setRevisionNumber(revision);
267         data.setLoginName("author1");
268         data.setDate(date);
269         data.setLines(linesAdded, linesRemoved);
270         data.setComment("comment");
271         builder.buildRevision(data);
272     }
273 
274     private void buildRevisionInitial(final String revision, final Date date) {
275         final RevisionData data = new RevisionData();
276         data.setStateExp();
277         data.setRevisionNumber(revision);
278         data.setLoginName("author1");
279         data.setDate(date);
280         data.setComment("comment");
281         builder.buildRevision(data);
282     }
283 
284     private void buildRevisionDead(final String revision, final Date date) {
285         final RevisionData data = new RevisionData();
286         data.setStateDead();
287         data.setRevisionNumber(revision);
288         data.setLoginName("author1");
289         data.setDate(date);
290         data.setComment("comment");
291         builder.buildRevision(data);
292     }
293 
294     private void addAnotherFile() {
295         builder.buildFile("file2", false, false, new HashMap());
296         buildRevisionInitial("1.1", date11);
297     }
298 
299     private void finishBuilder() {
300         final Iterator it = builder.createCvsContent().getFiles().iterator();
301         while (it.hasNext()) {
302             final VersionedFile f = (VersionedFile) it.next();
303             if (f.getFilename().equals("file")) {
304                 file = f;
305             }
306         }
307         if (file == null) {
308             return;
309         }
310         final List revisions = new ArrayList(file.getRevisions());
311         Collections.reverse(revisions);
312         try {
313             rev0 = (Revision) revisions.get(0);
314             rev1 = (Revision) revisions.get(1);
315             rev2 = (Revision) revisions.get(2);
316             rev3 = (Revision) revisions.get(3);
317             rev4 = (Revision) revisions.get(4);
318         } catch (final IndexOutOfBoundsException mightHappen) {
319             // do nothing
320         }
321     }
322 
323     private void assertRevisionLines(final Revision revision, final int effectiveLinesOfCode, final int locChange, final int lineValue) {
324         assertEquals("effective lines of code", effectiveLinesOfCode, revision.getLines());
325         assertEquals("lines of code change", locChange, revision.getLinesDelta());
326         assertEquals("line value", lineValue, revision.getNewLines());
327     }
328 }