001: /********************************************************************************
002: * CruiseControl, a Continuous Integration Toolkit
003: * Copyright (c) 2001, ThoughtWorks, Inc.
004: * 200 E. Randolph, 25th Floor
005: * Chicago, IL 60601 USA
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * + Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * + Redistributions in binary form must reproduce the above
016: * copyright notice, this list of conditions and the following
017: * disclaimer in the documentation and/or other materials provided
018: * with the distribution.
019: *
020: * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
021: * names of its contributors may be used to endorse or promote
022: * products derived from this software without specific prior
023: * written permission.
024: *
025: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
026: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
027: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
028: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
029: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
030: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
031: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
032: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
033: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
034: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036: ********************************************************************************/package net.sourceforge.cruisecontrol;
037:
038: import java.text.DateFormat;
039: import java.text.ParseException;
040: import java.text.SimpleDateFormat;
041: import java.util.ArrayList;
042: import java.util.Date;
043: import java.util.Hashtable;
044: import java.util.Iterator;
045: import java.util.List;
046:
047: import junit.framework.TestCase;
048: import net.sourceforge.cruisecontrol.sourcecontrols.MockSourceControl;
049:
050: import org.jdom.Element;
051: import org.jdom.output.XMLOutputter;
052:
053: public class ModificationSetTest extends TestCase {
054:
055: private static class MockProgress implements Progress {
056: private String value;
057:
058: public void setValue(String value) {
059: this .value = value;
060: }
061:
062: public String getValue() {
063: return value;
064: }
065: }
066:
067: private final MockProgress mockProgress = new MockProgress();
068:
069: private ModificationSet modSet;
070:
071: protected void setUp() throws Exception {
072: modSet = new ModificationSet();
073: modSet.setQuietPeriod(0);
074: }
075:
076: public void testIsLastModificationInQuietPeriod()
077: throws ParseException {
078: SimpleDateFormat formatter = new SimpleDateFormat(
079: "yyyyMMddHHmmss");
080: Modification mod1 = new Modification();
081: mod1.modifiedTime = formatter.parse("20020621140000");
082: Modification mod2 = new Modification();
083: mod2.modifiedTime = formatter.parse("20020621140100");
084:
085: // When a change is put into source control with a bad date in the
086: // future, we should still build
087: Modification modInFuture = new Modification();
088: modInFuture.modifiedTime = formatter.parse("30020731150000");
089:
090: List mods1 = new ArrayList();
091: mods1.add(mod1);
092: mods1.add(mod2);
093:
094: List mods2 = new ArrayList();
095: mods2.add(mod1);
096:
097: List hasModInFuture = new ArrayList();
098: hasModInFuture.add(mod1);
099: hasModInFuture.add(mod2);
100: hasModInFuture.add(modInFuture);
101:
102: Date now = formatter.parse("20020621140103");
103:
104: modSet.setQuietPeriod(5);
105:
106: assertEquals(true, modSet.isLastModificationInQuietPeriod(now,
107: mods1));
108: assertEquals(false, modSet.isLastModificationInQuietPeriod(now,
109: mods2));
110: assertEquals(false, modSet.isLastModificationInQuietPeriod(now,
111: hasModInFuture));
112: }
113:
114: public void testGetLastModificationMillis() throws ParseException {
115: SimpleDateFormat formatter = new SimpleDateFormat(
116: "yyyyMMddHHmmss");
117: Modification mod1 = new Modification();
118: mod1.modifiedTime = formatter.parse("20020621140000");
119: Modification mod2 = new Modification();
120: mod2.modifiedTime = formatter.parse("20020621140100");
121:
122: List mods1 = new ArrayList();
123: mods1.add(mod2);
124: mods1.add(mod1);
125:
126: assertEquals(mod2.modifiedTime.getTime(), modSet
127: .getLastModificationMillis(mods1));
128: }
129:
130: public void testGetQuietPeriodDifference() throws ParseException {
131: SimpleDateFormat formatter = new SimpleDateFormat(
132: "yyyyMMddHHmmss");
133: Date now = formatter.parse("20020621140103");
134: Modification mod1 = new Modification();
135: mod1.modifiedTime = formatter.parse("20020621140000");
136: Modification mod2 = new Modification();
137: mod2.modifiedTime = formatter.parse("20020621140100");
138:
139: List mods1 = new ArrayList();
140: mods1.add(mod1);
141:
142: List mods2 = new ArrayList();
143: mods2.add(mod2);
144:
145: modSet.setQuietPeriod(5);
146:
147: assertEquals(0, modSet.getQuietPeriodDifference(now, mods1));
148: assertEquals(2000, modSet.getQuietPeriodDifference(now, mods2));
149: }
150:
151: /**
152: * @deprecated Tests deprecated method, remove when method is removed.
153: */
154: public void testProgressNull() throws Exception {
155: // @todo Tests deprecated method, remove when method is removed.
156:
157: final Date now = new Date();
158:
159: final MockSourceControl mock1 = new MockSourceControl();
160: mock1.setType(1);
161: mock1.setModifiedDate(now);
162:
163: modSet.add(mock1);
164:
165: final int quietPeriod = 1;
166: modSet.setQuietPeriod(quietPeriod);
167:
168: // Wait to ensure "now" used in getMods will detect mod in quiet period
169: Thread.sleep((long) ((quietPeriod * 1000) * .5));
170:
171: assertNull(mockProgress.getValue());
172: modSet.retrieveModificationsAsElement(new Date(), null);
173: assertNull(mockProgress.getValue());
174: }
175:
176: public void testProgressInQuietPeriod() throws Exception {
177: final Date now = new Date();
178:
179: final MockSourceControl mock1 = new MockSourceControl();
180: mock1.setType(1);
181: mock1.setModifiedDate(now);
182:
183: modSet.add(mock1);
184:
185: final int quietPeriod = 1;
186: modSet.setQuietPeriod(quietPeriod);
187:
188: // Wait to ensure "now" used in getMods will detect mod in quiet period
189: Thread.sleep((long) ((quietPeriod * 1000) * .5));
190:
191: assertNull(mockProgress.getValue());
192: modSet.retrieveModificationsAsElement(now, mockProgress);
193: final String progressMsg = mockProgress.getValue();
194: assertNotNull("Modset progress msg should not be null",
195: progressMsg);
196: assertTrue(progressMsg
197: .indexOf(ModificationSet.MSG_PROGRESS_PREFIX_QUIETPERIOD_MODIFICATION_SLEEP) > -1);
198: }
199:
200: public void testGetModifications() throws Exception {
201: MockSourceControl mock1 = new MockSourceControl();
202: mock1.setType(1);
203: MockSourceControl mock2 = new MockSourceControl();
204: mock2.setType(2);
205:
206: modSet.add(mock1);
207: modSet.add(mock2);
208:
209: // mock source controls don't care about the date
210: final Element modSetResults = modSet
211: .retrieveModificationsAsElement(new Date(),
212: mockProgress);
213:
214: DateFormat formatter = DateFormatFactory.getDateFormat();
215: Element modificationsElement = new Element("modifications");
216: Iterator mock1ModificationsIterator = mock1.getModifications(
217: new Date(), new Date()).iterator();
218: while (mock1ModificationsIterator.hasNext()) {
219: Modification modification = (Modification) mock1ModificationsIterator
220: .next();
221: modificationsElement.addContent(modification
222: .toElement(formatter));
223: }
224: Iterator mock2ModificationsIterator = mock2.getModifications(
225: new Date(), new Date()).iterator();
226: while (mock2ModificationsIterator.hasNext()) {
227: Modification modification = (Modification) mock2ModificationsIterator
228: .next();
229: modificationsElement.addContent(modification
230: .toElement(formatter));
231: }
232:
233: XMLOutputter outputter = new XMLOutputter();
234: assertEquals("XML data differ", outputter
235: .outputString(modificationsElement), outputter
236: .outputString(modSetResults));
237: }
238:
239: /**
240: * This test will give modificationset two different types of modifications.
241: * One regular, based on the object, and one with Element data. Uses inline
242: * sourcecontrol implementation instead of mock.
243: */
244: public void testGetMixedModifications() throws ParseException {
245: DateFormat formatter = DateFormatFactory.getDateFormat();
246:
247: Modification mod1 = new Modification();
248: mod1.userName = "user3";
249: mod1.modifiedTime = formatter.parse("04/04/2004 17:23:50");
250: mod1.comment = "comment3";
251:
252: Modification.ModifiedFile mod1file = mod1.createModifiedFile(
253: "file3", "dir3");
254: mod1file.action = "Checkin";
255:
256: Modification mod2 = new Modification();
257: mod2.userName = "user4";
258: mod2.modifiedTime = formatter.parse("02/02/2002 17:23:50");
259: mod2.comment = "comment4";
260:
261: Modification.ModifiedFile mod2file = mod1.createModifiedFile(
262: "file4", "dir4");
263: mod2file.action = "Checkin";
264:
265: final List result = new ArrayList();
266: result.add(mod1.toElement(formatter));
267: result.add(mod2);
268:
269: assertEquals(mod1.modifiedTime.getTime(), modSet
270: .getLastModificationMillis(result));
271:
272: modSet.add(new MockSourceControl() {
273: public List getModifications(Date lastBuild, Date now) {
274: return result;
275: }
276: });
277:
278: final Element actual = modSet.retrieveModificationsAsElement(
279: new Date(), mockProgress);
280:
281: Element expected = new Element("modifications");
282: expected.addContent(mod1.toElement(formatter));
283: expected.addContent(mod2.toElement(formatter));
284:
285: XMLOutputter outputter = new XMLOutputter();
286: assertEquals("XML data differ", outputter
287: .outputString(expected), outputter.outputString(actual));
288:
289: }
290:
291: public void testGetProperties() throws Exception {
292: MockSourceControl mock1 = new MockSourceControl();
293: mock1.setType(1);
294: MockSourceControl mock2 = new MockSourceControl();
295: mock2.setType(2);
296:
297: modSet.add(mock1);
298: modSet.add(mock2);
299:
300: modSet.retrieveModificationsAsElement(new Date(), mockProgress); // mock source
301: // controls don't
302: // care about the
303: // date
304:
305: Hashtable table = modSet.getProperties();
306: assertNotNull("Properties shouldn't be null.", table);
307: assertEquals("Properties should be empty.", 0, table.size());
308:
309: modSet = new ModificationSet();
310: modSet.setQuietPeriod(0);
311: mock1 = new MockSourceControl();
312: mock2 = new MockSourceControl();
313: mock1.setType(1);
314: mock2.setType(2);
315: mock1.setProperty("property");
316: mock2.setPropertyOnDelete("propertyOnDelete");
317:
318: modSet.add(mock1);
319: modSet.add(mock2);
320:
321: modSet.retrieveModificationsAsElement(new Date(), mockProgress); // mock source
322: // controls don't
323: // care about the
324: // date
325:
326: table = modSet.getProperties();
327: assertNotNull("Properties shouldn't be null.", table);
328: assertEquals("Properties should should have 2 entries.", 2,
329: table.size());
330: assertTrue("Property not found.", table.containsKey("property"));
331: assertTrue("PropertyOnDelete not found.", table
332: .containsKey("propertyOnDelete"));
333:
334: modSet = new ModificationSet();
335: modSet.setQuietPeriod(0);
336: mock1 = new MockSourceControl();
337: mock1.setType(1);
338: mock1.setProperty("property");
339:
340: modSet.add(mock1);
341: modSet.retrieveModificationsAsElement(new Date(), mockProgress); // mock source
342: // controls don't
343: // care about the
344: // date
345: table = modSet.getProperties();
346: assertNotNull("Properties shouldn't be null.", table);
347: assertEquals("Properties should should have 1 entry.", 1, table
348: .size());
349: assertTrue("Property not found.", table.containsKey("property"));
350: }
351:
352: public void testValidate() throws CruiseControlException {
353: try {
354: modSet.validate();
355: fail("modificationset should require at least one sourcecontrol");
356: } catch (CruiseControlException expected) {
357: }
358:
359: SourceControl invalidSC = new MockSourceControl() {
360: public void validate() throws CruiseControlException {
361: throw new CruiseControlException(
362: "validation was called");
363: }
364: };
365: modSet.add(invalidSC);
366: try {
367: modSet.validate();
368: fail("validate should be called on child source controls");
369: } catch (CruiseControlException expected) {
370: assertEquals("validation was called", expected.getMessage());
371: }
372: }
373:
374: public void testSetIgnoreFiles() {
375:
376: final String correctPattern = "*.txt,dir1/*/file*.txt";
377: try {
378: modSet.setIgnoreFiles(correctPattern);
379: } catch (CruiseControlException e) {
380: fail("Exception while setting pattern");
381: }
382:
383: final List globPatterns = modSet.getIgnoreFiles();
384: assertEquals("The number of parsed patterns is not correct", 2,
385: globPatterns.size());
386:
387: }
388:
389: public void testFilterIgnoredFiles() throws CruiseControlException,
390: ParseException {
391: final DateFormat formatter = DateFormatFactory.getDateFormat();
392: final List modifications = new ArrayList();
393:
394: final Modification mod1 = new Modification();
395: mod1.type = "Checkin";
396: mod1.userName = "user1";
397: mod1.modifiedTime = formatter.parse("02/02/2002 17:23:50");
398: mod1.comment = "comment1";
399: mod1.createModifiedFile("file1", "dir1");
400: modifications.add(mod1);
401:
402: final Modification mod2 = new Modification();
403: mod2.type = "Checkin";
404: mod2.userName = "user2";
405: mod2.modifiedTime = formatter.parse("02/02/2002 17:23:50");
406: mod2.comment = "comment2";
407: mod2.createModifiedFile("file1", "dir2");
408: modifications.add(mod2);
409:
410: final Modification mod3 = new Modification();
411: mod3.type = "Checkin";
412: mod3.userName = "user3";
413: mod3.modifiedTime = formatter.parse("02/02/2002 17:23:50");
414: mod3.comment = "comment1";
415: mod3.createModifiedFile("file3", "dir1");
416: modifications.add(mod3);
417:
418: modSet.filterIgnoredModifications(modifications);
419: assertEquals("No modification should have been filtered out",
420: 3, modifications.size());
421:
422: // Now set a filter
423: modSet.setIgnoreFiles("dir2/file3,di?1/f*3");
424: modSet.filterIgnoredModifications(modifications);
425: assertEquals("No modification have been filtered out", 2,
426: modifications.size());
427:
428: final List expectedModifications = new ArrayList();
429: expectedModifications.add(mod1);
430: expectedModifications.add(mod2);
431:
432: assertEquals("The wrong modification has been filtered out",
433: expectedModifications, modifications);
434: }
435:
436: public void testFilterIgnoredFilesInMultipleSubdirectories()
437: throws CruiseControlException, ParseException {
438: final DateFormat formatter = DateFormatFactory.getDateFormat();
439: final List modifications = new ArrayList();
440:
441: final Modification mod1 = new Modification();
442: mod1.type = "Checkin";
443: mod1.userName = "user1";
444: mod1.modifiedTime = formatter.parse("02/02/2002 17:23:50");
445: mod1.comment = "comment1";
446: mod1.createModifiedFile("file1", "dir1");
447: modifications.add(mod1);
448:
449: final Modification mod2 = new Modification();
450: mod2.type = "Checkin";
451: mod2.userName = "user2";
452: mod2.modifiedTime = formatter.parse("02/02/2002 17:23:50");
453: mod2.comment = "comment2";
454: mod2.createModifiedFile("file1", "dir2");
455: modifications.add(mod2);
456:
457: final Modification mod3 = new Modification();
458: mod3.type = "Checkin";
459: mod3.userName = "user3";
460: mod3.modifiedTime = formatter.parse("02/02/2002 17:23:50");
461: mod3.comment = "comment1";
462: mod3.createModifiedFile("file3", "dir1");
463: modifications.add(mod3);
464:
465: // Now set a filter
466: modSet.setIgnoreFiles("*/file1");
467: modSet.filterIgnoredModifications(modifications);
468: assertEquals(1, modifications.size());
469:
470: assertEquals(mod3, modifications.get(0));
471: }
472:
473: /**
474: * Tests ignoring files when multiple files exist in the modification sets.
475: */
476: public void testFilterIgnoredFilesMultipleFiles()
477: throws CruiseControlException, ParseException {
478: final DateFormat formatter = DateFormatFactory.getDateFormat();
479: final List modifications = new ArrayList();
480:
481: final Modification mod1 = new Modification();
482: mod1.type = "Checkin";
483: mod1.userName = "user1";
484: mod1.modifiedTime = formatter.parse("02/02/2002 17:23:50");
485: mod1.comment = "comment1";
486: mod1.createModifiedFile("ignore1", "dir1");
487: mod1.createModifiedFile("ignore2", "dir1");
488: modifications.add(mod1);
489:
490: final Modification mod2 = new Modification();
491: mod2.type = "Checkin";
492: mod2.userName = "user2";
493: mod2.modifiedTime = formatter.parse("02/02/2002 17:23:50");
494: mod2.comment = "comment2";
495: mod2.createModifiedFile("ignore2", "dir1");
496: mod2.createModifiedFile("keep2", "dir1");
497: modifications.add(mod2);
498:
499: final Modification mod3 = new Modification();
500: mod3.type = "Checkin";
501: mod3.userName = "user3";
502: mod3.modifiedTime = formatter.parse("02/02/2002 17:23:50");
503: mod3.comment = "comment1";
504: mod3.createModifiedFile("file3", "dir1");
505: modifications.add(mod3);
506:
507: modSet.setIgnoreFiles("dir1/ignore*");
508: modSet.filterIgnoredModifications(modifications);
509: assertEquals(
510: "Incorrect number of modifications were filtered out",
511: 2, modifications.size());
512:
513: final List expectedModifications = new ArrayList();
514: expectedModifications.add(mod2);
515: expectedModifications.add(mod3);
516:
517: assertEquals("The wrong modification has been filtered out",
518: expectedModifications, modifications);
519: }
520: }
|