001: /* ArchiveUtilsTest
002: *
003: * $Id: ArchiveUtilsTest.java 5052 2007-04-10 02:26:52Z gojomo $
004: *
005: * Created Tue Jan 20 14:17:59 PST 2004
006: *
007: * Copyright (C) 2004 Internet Archive.
008: *
009: * This file is part of the Heritrix web crawler (crawler.archive.org).
010: *
011: * Heritrix is free software; you can redistribute it and/or modify
012: * it under the terms of the GNU Lesser Public License as published by
013: * the Free Software Foundation; either version 2.1 of the License, or
014: * any later version.
015: *
016: * Heritrix is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019: * GNU Lesser Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser Public License
022: * along with Heritrix; if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: */
025:
026: package org.archive.util;
027:
028: import java.util.Date;
029: import java.util.LinkedList;
030: import java.util.concurrent.Semaphore;
031: import java.util.concurrent.atomic.AtomicInteger;
032: import java.text.ParseException;
033:
034: import junit.framework.Test;
035: import junit.framework.TestCase;
036: import junit.framework.TestSuite;
037:
038: /**
039: * JUnit test suite for ArchiveUtils
040: *
041: * @author <a href="mailto:me@jamesc.net">James Casey</a>
042: * @version $Id: ArchiveUtilsTest.java 5052 2007-04-10 02:26:52Z gojomo $
043: */
044: public class ArchiveUtilsTest extends TestCase {
045:
046: /**
047: * Create a new ArchiveUtilsTest object
048: *
049: * @param testName the name of the test
050: */
051: public ArchiveUtilsTest(final String testName) {
052: super (testName);
053: }
054:
055: /**
056: * run all the tests for ArchiveUtilsTest
057: *
058: * @param argv the command line arguments
059: */
060: public static void main(String argv[]) {
061: junit.textui.TestRunner.run(suite());
062: }
063:
064: /**
065: * return the suite of tests for ArchiveUtilsTest
066: *
067: * @return the suite of test
068: */
069: public static Test suite() {
070: return new TestSuite(ArchiveUtilsTest.class);
071: }
072:
073: /** check the getXXDigitDate() methods produce valid dates*/
074: public void testGetXXDigitDate() {
075: // TODO - we only really test the date lengths here. How to test
076: // other stuff well ?
077: final String date12 = ArchiveUtils.get12DigitDate();
078: assertEquals("12 digits", 12, date12.length());
079:
080: final String date14 = ArchiveUtils.get14DigitDate();
081: assertEquals("14 digits", 14, date14.length());
082:
083: final String date17 = ArchiveUtils.get17DigitDate();
084: assertEquals("17 digits", 17, date17.length());
085:
086: // now parse, and check they're all within 1 minute
087:
088: try {
089: final long long12 = ArchiveUtils.parse12DigitDate(date12)
090: .getTime();
091: long long14 = ArchiveUtils.parse14DigitDate(date14)
092: .getTime();
093: long long17 = ArchiveUtils.parse17DigitDate(date17)
094: .getTime();
095:
096: assertClose("12 and 14 close", long12, long14, 600000);
097: assertClose("12 and 17 close", long12, long17, 600000);
098: assertClose("14 and 17 close", long14, long17, 600000);
099: } catch (ParseException e) {
100: fail("Could not parse a date : " + e.getMessage());
101: }
102: }
103:
104: /** check that getXXDigitDate(long) does the right thing */
105: public void testGetXXDigitDateLong() {
106: final long now = System.currentTimeMillis();
107: final String date12 = ArchiveUtils.get12DigitDate(now);
108: assertEquals("12 digits", 12, date12.length());
109:
110: final String date14 = ArchiveUtils.get14DigitDate(now);
111: assertEquals("14 digits", 14, date14.length());
112: assertEquals("first twelve digits same as date12", date12,
113: date14.substring(0, 12));
114: final String date17 = ArchiveUtils.get17DigitDate(now);
115: assertEquals("17 digits", 17, date17.length());
116: assertEquals("first twelve digits same as date12", date12,
117: date17.substring(0, 12));
118: assertEquals("first fourteen digits same as date14", date14,
119: date17.substring(0, 14));
120: }
121:
122: /**
123: * Check that parseXXDigitDate() works
124: *
125: * @throws ParseException
126: */
127: public void testParseXXDigitDate() throws ParseException {
128: // given a date, check it get resolved properly
129: // It's 02 Jan 2004, 12:40:02.111
130: final String date = "20040102124002111";
131: try {
132: final long long12 = ArchiveUtils.parse12DigitDate(
133: date.substring(0, 12)).getTime();
134: final long long14 = ArchiveUtils.parse14DigitDate(
135: date.substring(0, 14)).getTime();
136: final long long17 = ArchiveUtils.parse17DigitDate(date)
137: .getTime();
138:
139: assertClose("12 and 14 close", long12, long14, 600000);
140: assertClose("12 and 17 close", long12, long17, 600000);
141: assertClose("14 and 17 close", long14, long17, 600000);
142: } catch (ParseException e) {
143: fail("Could not parse a date : " + e.getMessage());
144: }
145: }
146:
147: public void testTooShortParseDigitDate() throws ParseException {
148: String d = "X";
149: boolean b = false;
150: try {
151: ArchiveUtils.getDate(d);
152: } catch (ParseException e) {
153: b = true;
154: }
155: assertTrue(b);
156:
157: Date date = ArchiveUtils.getDate("1999");
158: assertTrue(date.getTime() == 915148800000L);
159:
160: b = false;
161: try {
162: ArchiveUtils.getDate("19991");
163: } catch (ParseException e) {
164: b = true;
165: }
166: assertTrue(b);
167:
168: ArchiveUtils.getDate("19990101");
169: ArchiveUtils.getDate("1999010101");
170: ArchiveUtils.getDate("19990101010101");
171: ArchiveUtils.getDate("1960");
172: }
173:
174: /** check that parse12DigitDate doesn't accept a bad date */
175: public void testBad12Date() {
176: // now try a badly formed dates
177: assertBad12DigitDate("a-stringy-digit-date");
178: assertBad12DigitDate("20031201"); // too short
179: }
180:
181: /**
182: * check that parse14DigitDate doesn't accept a bad date
183: */
184: public void testBad14Date() {
185: // now try a badly formed dates
186: assertBad14DigitDate("a-stringy-digit-date");
187: assertBad14DigitDate("20031201"); // too short
188: assertBad14DigitDate("200401021240"); // 12 digit
189: }
190:
191: /**
192: * check that parse12DigitDate doesn't accept a bad date
193: */
194: public void testBad17Date() {
195: // now try a badly formed dates
196: assertBad17DigitDate("a-stringy-digit-date");
197: assertBad17DigitDate("20031201"); // too short
198: assertBad17DigitDate("200401021240"); // 12 digit
199: assertBad17DigitDate("20040102124002"); // 14 digit
200: }
201:
202: /** check that padTo(String) works */
203: public void testPadToString() {
204: assertEquals("pad to one (smaller)", "foo", ArchiveUtils.padTo(
205: "foo", 1));
206: assertEquals("pad to 0 (no sense)", "foo", ArchiveUtils.padTo(
207: "foo", 0));
208: assertEquals("pad to neg (nonsense)", "foo", ArchiveUtils
209: .padTo("foo", 0));
210: assertEquals("pad to 4", " foo", ArchiveUtils.padTo("foo", 4));
211: assertEquals("pad to 10", " foo", ArchiveUtils.padTo(
212: "foo", 10));
213: }
214:
215: /**
216: * check that padTo(int) works
217: */
218: public void testPadToInt() {
219: assertEquals("pad to one (smaller)", "123", ArchiveUtils.padTo(
220: 123, 1));
221: assertEquals("pad to 0 (no sense)", "123", ArchiveUtils.padTo(
222: 123, 0));
223: assertEquals("pad to neg (nonsense)", "123", ArchiveUtils
224: .padTo(123, 0));
225: assertEquals("pad to 4", " 123", ArchiveUtils.padTo(123, 4));
226: assertEquals("pad to 10", " 123", ArchiveUtils.padTo(123,
227: 10));
228: assertEquals("pad -123 to 10", " -123", ArchiveUtils
229: .padTo(-123, 10));
230: }
231:
232: /** check that byteArrayEquals() works */
233: public void testByteArrayEquals() {
234: // foo == foo2, foo != bar, foo != bar2
235: byte[] foo = new byte[10], bar = new byte[20];
236: byte[] foo2 = new byte[10], bar2 = new byte[10];
237:
238: for (byte i = 0; i < 10; ++i) {
239: foo[i] = foo2[i] = bar[i] = i;
240: bar2[i] = (byte) (01 + i);
241: }
242: assertTrue("two nulls", ArchiveUtils
243: .byteArrayEquals(null, null));
244: assertFalse("lhs null", ArchiveUtils.byteArrayEquals(null, foo));
245: assertFalse("rhs null", ArchiveUtils.byteArrayEquals(foo, null));
246:
247: // now check with same length, with same (foo2) and different (bar2)
248: // contents
249: assertFalse("different lengths", ArchiveUtils.byteArrayEquals(
250: foo, bar));
251:
252: assertTrue("same to itself", ArchiveUtils.byteArrayEquals(foo,
253: foo));
254: assertTrue("same contents", ArchiveUtils.byteArrayEquals(foo,
255: foo2));
256: assertFalse("different contents", ArchiveUtils.byteArrayEquals(
257: foo, bar2));
258: }
259:
260: /** test doubleToString() */
261: public void testDoubleToString() {
262: double test = 12.345;
263: assertTrue("cecking zero precision", ArchiveUtils
264: .doubleToString(test, 0).equals("12"));
265: assertTrue("cecking 2 character precision", ArchiveUtils
266: .doubleToString(test, 2).equals("12.34"));
267: assertTrue("cecking precision higher then the double has",
268: ArchiveUtils.doubleToString(test, 65).equals("12.345"));
269: }
270:
271: public void testFormatBytesForDisplayPrecise() {
272: assertEquals("formating negative number", "0 B", ArchiveUtils
273: .formatBytesForDisplay(-1));
274: assertEquals("0 bytes", "0 B", ArchiveUtils
275: .formatBytesForDisplay(0));
276: assertEquals("1023 bytes", "1,023 B", ArchiveUtils
277: .formatBytesForDisplay(1023));
278: assertEquals("1025 bytes", "1.0 KB", ArchiveUtils
279: .formatBytesForDisplay(1025));
280: // expected display values taken from Google calculator
281: assertEquals("10,000 bytes", "9.8 KB", ArchiveUtils
282: .formatBytesForDisplay(10000));
283: assertEquals("1,000,000 bytes", "977 KB", ArchiveUtils
284: .formatBytesForDisplay(1000000));
285: assertEquals("100,000,000 bytes", "95 MB", ArchiveUtils
286: .formatBytesForDisplay(100000000));
287: assertEquals("100,000,000,000 bytes", "93 GB", ArchiveUtils
288: .formatBytesForDisplay(100000000000L));
289: assertEquals("100,000,000,000,000 bytes", "91 TB", ArchiveUtils
290: .formatBytesForDisplay(100000000000000L));
291: assertEquals("100,000,000,000,000,000 bytes", "90,949 TB",
292: ArchiveUtils.formatBytesForDisplay(100000000000000000L));
293: }
294:
295: /*
296: * helper methods
297: */
298:
299: /** check that this is a bad date, and <code>fail()</code> if so.
300: *
301: * @param date the 12digit date to check
302: */
303: private void assertBad12DigitDate(final String date) {
304: try {
305: ArchiveUtils.parse12DigitDate(date);
306: } catch (ParseException e) {
307: return;
308: }
309: fail("Expected exception on parse of : " + date);
310:
311: }
312:
313: /**
314: * check that this is a bad date, and <code>fail()</code> if so.
315: *
316: * @param date the 14digit date to check
317: */
318: private void assertBad14DigitDate(final String date) {
319: try {
320: ArchiveUtils.parse14DigitDate(date);
321: } catch (ParseException e) {
322: return;
323: }
324: fail("Expected exception on parse of : " + date);
325:
326: }
327:
328: /**
329: * check that this is a bad date, and <code>fail()</code> if so.
330: *
331: * @param date the 17digit date to check
332: */
333: private void assertBad17DigitDate(final String date) {
334: try {
335: ArchiveUtils.parse17DigitDate(date);
336: } catch (ParseException e) {
337: return;
338: }
339: fail("Expected exception on parse of : " + date);
340:
341: }
342:
343: /** check that two longs are within a given <code>delta</code> */
344: private void assertClose(String desc, long date1, long date2,
345: long delta) {
346: assertTrue(desc, date1 == date2
347: || (date1 < date2 && date2 < (date1 + delta))
348: || (date2 < date1 && date1 < (date2 + delta)));
349: }
350:
351: public void testArrayToLong() {
352: testOneArrayToLong(-1);
353: testOneArrayToLong(1);
354: testOneArrayToLong(1000);
355: testOneArrayToLong(Integer.MAX_VALUE);
356: }
357:
358: private void testOneArrayToLong(final long testValue) {
359: byte[] a = new byte[8];
360: ArchiveUtils.longIntoByteArray(testValue, a, 0);
361: final long l = ArchiveUtils.byteArrayIntoLong(a, 0);
362: assertEquals(testValue, l);
363: }
364:
365: public void testSecondsSinceEpochCalculation()
366: throws ParseException {
367: assertEquals(ArchiveUtils.secondsSinceEpoch("20010909014640"),
368: "1000000000");
369: assertEquals(ArchiveUtils.secondsSinceEpoch("20010909014639"),
370: "0999999999");
371: assertEquals(ArchiveUtils.secondsSinceEpoch("19700101"),
372: "0000000000");
373: assertEquals(ArchiveUtils.secondsSinceEpoch("2005"),
374: "1104537600");
375: assertEquals(ArchiveUtils.secondsSinceEpoch("200501"),
376: "1104537600");
377: assertEquals(ArchiveUtils.secondsSinceEpoch("20050101"),
378: "1104537600");
379: assertEquals(ArchiveUtils.secondsSinceEpoch("2005010100"),
380: "1104537600");
381: boolean eThrown = false;
382: try {
383: ArchiveUtils.secondsSinceEpoch("20050");
384: } catch (IllegalArgumentException e) {
385: eThrown = true;
386: }
387: assertTrue(eThrown);
388: }
389:
390: public static void testZeroPadInteger() {
391: assertEquals(ArchiveUtils.zeroPadInteger(1), "0000000001");
392: assertEquals(ArchiveUtils.zeroPadInteger(1000000000),
393: "1000000000");
394: }
395:
396: /**
397: * Test stable behavior of date formatting under heavy concurrency.
398: *
399: * @throws InterruptedException
400: */
401: public static void testDateFormatConcurrency()
402: throws InterruptedException {
403: final int COUNT = 1000;
404: Thread[] ts = new Thread[COUNT];
405: final Semaphore allDone = new Semaphore(-COUNT + 1);
406: final AtomicInteger failures = new AtomicInteger(0);
407: for (int i = 0; i < COUNT; i++) {
408: Thread t = new Thread() {
409: public void run() {
410: long n = System.currentTimeMillis();
411: final String d = ArchiveUtils.get17DigitDate(n);
412: for (int i = 0; i < 1000; i++) {
413: try {
414: sleep(10);
415: } catch (InterruptedException e) {
416: // TODO Auto-generated catch block
417: e.printStackTrace();
418: }
419: String d2 = ArchiveUtils.get17DigitDate(n);
420: if (!d.equals(d2)) {
421: failures.incrementAndGet();
422: break;
423: }
424: }
425: allDone.release();
426: }
427: };
428: ts[i] = t;
429: ts[i].setName(Integer.toString(i));
430: ts[i].start();
431: while (!ts[i].isAlive())
432: /* Wait for thread to spin up*/;
433: }
434: allDone.acquire(); // wait for all threads to finish
435: assertEquals(failures.get() + " format mismatches", 0, failures
436: .get());
437: }
438: }
|