View Javadoc

1   /* ArchiveUtilsTest
2    *
3    * $Id: ArchiveUtilsTest.java 6829 2010-04-21 22:32:27Z gojomo $
4    *
5    * Created Tue Jan 20 14:17:59 PST 2004
6    *
7    * Copyright (C) 2004 Internet Archive.
8    *
9    * This file is part of the Heritrix web crawler (crawler.archive.org).
10   *
11   * Heritrix is free software; you can redistribute it and/or modify
12   * it under the terms of the GNU Lesser Public License as published by
13   * the Free Software Foundation; either version 2.1 of the License, or
14   * any later version.
15   *
16   * Heritrix is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU Lesser Public License for more details.
20   *
21   * You should have received a copy of the GNU Lesser Public License
22   * along with Heritrix; if not, write to the Free Software
23   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24   */
25  
26  package org.archive.util;
27  
28  import java.util.Date;
29  import java.util.concurrent.Semaphore;
30  import java.util.concurrent.atomic.AtomicInteger;
31  import java.text.ParseException;
32  
33  import junit.framework.Test;
34  import junit.framework.TestCase;
35  import junit.framework.TestSuite;
36  
37  /***
38   * JUnit test suite for ArchiveUtils
39   *
40   * @contributor <a href="mailto:me@jamesc.net">James Casey</a>
41   * @contributor gojomo
42   * @version $Id: ArchiveUtilsTest.java 6829 2010-04-21 22:32:27Z gojomo $
43   */
44  public class ArchiveUtilsTest extends TestCase {
45      
46      /***
47       * Create a new ArchiveUtilsTest object
48       *
49       * @param testName the name of the test
50       */
51      public ArchiveUtilsTest(final String testName) {
52          super(testName);
53      }
54  
55      /***
56       * run all the tests for ArchiveUtilsTest
57       *
58       * @param argv the command line arguments
59       */
60      public static void main(String argv[]) {
61          junit.textui.TestRunner.run(suite());
62      }
63  
64      /***
65       * return the suite of tests for ArchiveUtilsTest
66       *
67       * @return the suite of test
68       */
69      public static Test suite() {
70          return new TestSuite(ArchiveUtilsTest.class);
71      }
72  
73      /*** check the getXXDigitDate() methods produce valid dates*/
74      public void testGetXXDigitDate() {
75          // TODO - we only really test the date lengths here.  How to test
76          // other stuff well ?
77          final String date12 = ArchiveUtils.get12DigitDate();
78          assertEquals("12 digits", 12, date12.length());
79  
80          final String date14 = ArchiveUtils.get14DigitDate();
81          assertEquals("14 digits", 14, date14.length());
82  
83          final String date17 = ArchiveUtils.get17DigitDate();
84          assertEquals("17 digits", 17, date17.length());
85  
86          // now parse, and check they're all within 1 minute
87  
88          try {
89              final long long12 = ArchiveUtils.parse12DigitDate(date12).getTime();
90              long long14 = ArchiveUtils.parse14DigitDate(date14).getTime();
91              long long17 = ArchiveUtils.parse17DigitDate(date17).getTime();
92  
93              assertClose("12 and 14 close", long12, long14, 600000);
94              assertClose("12 and 17 close", long12, long17, 600000);
95              assertClose("14 and 17 close", long14, long17, 600000);
96          } catch (ParseException e) {
97              fail("Could not parse a date : " + e.getMessage());
98          }
99      }
100 
101     /*** check that getXXDigitDate(long) does the right thing */
102     public void testGetXXDigitDateLong() {
103         final long now = System.currentTimeMillis();
104         final String date12 = ArchiveUtils.get12DigitDate(now);
105         assertEquals("12 digits", 12, date12.length());
106 
107         final String date14 = ArchiveUtils.get14DigitDate(now);
108         assertEquals("14 digits", 14, date14.length());
109         assertEquals("first twelve digits same as date12", date12, date14.substring(0, 12));
110         final String date17 = ArchiveUtils.get17DigitDate(now);
111         assertEquals("17 digits", 17, date17.length());
112         assertEquals("first twelve digits same as date12", date12, date17.substring(0, 12));
113         assertEquals("first fourteen digits same as date14", date14, date17.substring(0, 14));
114     }
115 
116     /***
117      * Check that parseXXDigitDate() works
118      *
119      * @throws ParseException
120      */
121     public void testParseXXDigitDate() throws ParseException {
122         // given a date, check it get resolved properly
123         // It's 02 Jan 2004, 12:40:02.111
124         final String date = "20040102124002111";
125         try {
126             final long long12 = ArchiveUtils.parse12DigitDate(date.substring(0, 12)).getTime();
127             final long long14 = ArchiveUtils.parse14DigitDate(date.substring(0, 14)).getTime();
128             final long long17 = ArchiveUtils.parse17DigitDate(date).getTime();
129 
130             assertClose("12 and 14 close", long12, long14, 600000);
131             assertClose("12 and 17 close", long12, long17, 600000);
132             assertClose("14 and 17 close", long14, long17, 600000);
133         } catch (ParseException e) {
134             fail("Could not parse a date : " + e.getMessage());
135         }
136     }
137     
138     public void testTooShortParseDigitDate() throws ParseException {
139         String d = "X";
140         boolean b = false;
141         try {
142             ArchiveUtils.getDate(d);
143         } catch (ParseException e) {
144             b = true;
145         }
146         assertTrue(b);
147         
148         Date date = ArchiveUtils.getDate("1999");
149         assertTrue(date.getTime() == 915148800000L);
150         
151         b = false;
152         try {
153             ArchiveUtils.getDate("19991");
154         } catch (ParseException e) {
155             b = true;
156         }
157         assertTrue(b);
158         
159         ArchiveUtils.getDate("19990101");
160         ArchiveUtils.getDate("1999010101");
161         ArchiveUtils.getDate("19990101010101"); 
162         ArchiveUtils.getDate("1960"); 
163     }
164 
165     /*** check that parse12DigitDate doesn't accept a bad date */
166     public void testBad12Date() {
167         // now try a badly formed dates
168         assertBad12DigitDate("a-stringy-digit-date");
169         assertBad12DigitDate("20031201"); // too short
170     }
171 
172     /***
173      * check that parse14DigitDate doesn't accept a bad date
174      */
175     public void testBad14Date() {
176         // now try a badly formed dates
177         assertBad14DigitDate("a-stringy-digit-date");
178         assertBad14DigitDate("20031201"); // too short
179         assertBad14DigitDate("200401021240");  // 12 digit
180     }
181     /***
182      * check that parse12DigitDate doesn't accept a bad date
183      */
184     public void testBad17Date() {
185         // now try a badly formed dates
186         assertBad17DigitDate("a-stringy-digit-date");
187         assertBad17DigitDate("20031201"); // too short
188         assertBad17DigitDate("200401021240");  // 12 digit
189         assertBad17DigitDate("20040102124002");  // 14 digit
190     }
191 
192     /*** check that padTo(String) works */
193     public void testPadToString() {
194         assertEquals("pad to one (smaller)", "foo", ArchiveUtils.padTo("foo", 1));
195         assertEquals("pad to 0 (no sense)", "foo", ArchiveUtils.padTo("foo", 0));
196         assertEquals("pad to neg (nonsense)", "foo", ArchiveUtils.padTo("foo", 0));
197         assertEquals("pad to 4", " foo", ArchiveUtils.padTo("foo", 4));
198         assertEquals("pad to 10", "       foo", ArchiveUtils.padTo("foo", 10));
199     }
200 
201     /***
202      * check that padTo(int) works
203      */
204     public void testPadToInt() {
205         assertEquals("pad to one (smaller)", "123", ArchiveUtils.padTo(123, 1));
206         assertEquals("pad to 0 (no sense)", "123", ArchiveUtils.padTo(123, 0));
207         assertEquals("pad to neg (nonsense)", "123", ArchiveUtils.padTo(123, 0));
208         assertEquals("pad to 4", " 123", ArchiveUtils.padTo(123, 4));
209         assertEquals("pad to 10", "       123", ArchiveUtils.padTo(123, 10));
210         assertEquals("pad -123 to 10", "      -123", ArchiveUtils.padTo(-123, 10));
211     }
212 
213     /*** check that byteArrayEquals() works */
214     public void testByteArrayEquals() {
215         // foo == foo2, foo != bar, foo != bar2
216         byte[] foo = new byte[10], bar = new byte[20];
217         byte[] foo2 = new byte[10], bar2 = new byte[10];
218 
219         for (byte i = 0; i < 10 ; ++i) {
220             foo[i] = foo2[i] = bar[i] = i;
221             bar2[i] = (byte)(01 + i);
222         }
223         assertTrue("two nulls", ArchiveUtils.byteArrayEquals(null, null));
224         assertFalse("lhs null", ArchiveUtils.byteArrayEquals(null, foo));
225         assertFalse("rhs null", ArchiveUtils.byteArrayEquals(foo, null));
226 
227         // now check with same length, with same (foo2) and different (bar2)
228         // contents
229         assertFalse("different lengths", ArchiveUtils.byteArrayEquals(foo, bar));
230 
231         assertTrue("same to itself", ArchiveUtils.byteArrayEquals(foo, foo));
232         assertTrue("same contents", ArchiveUtils.byteArrayEquals(foo, foo2));
233         assertFalse("different contents", ArchiveUtils.byteArrayEquals(foo, bar2));
234     }
235 
236     /*** test doubleToString() */
237     public void testDoubleToString(){
238         double test = 12.345;
239         assertTrue(
240             "cecking zero precision",
241             ArchiveUtils.doubleToString(test, 0).equals("12"));
242         assertTrue(
243             "cecking 2 character precision",
244             ArchiveUtils.doubleToString(test, 2).equals("12.34"));
245         assertTrue(
246             "cecking precision higher then the double has",
247             ArchiveUtils.doubleToString(test, 65).equals("12.345"));
248     }
249 
250 
251     public void testFormatBytesForDisplayPrecise(){
252         assertEquals("formating negative number", "0 B", ArchiveUtils
253                 .formatBytesForDisplay(-1)); 
254         assertEquals("0 bytes", "0 B", ArchiveUtils
255                 .formatBytesForDisplay(0));
256         assertEquals("1023 bytes", "1,023 B", ArchiveUtils
257                 .formatBytesForDisplay(1023));
258         assertEquals("1025 bytes", "1.0 KB", ArchiveUtils
259                 .formatBytesForDisplay(1025));
260         // expected display values taken from Google calculator
261         assertEquals("10,000 bytes", "9.8 KB",
262                 ArchiveUtils.formatBytesForDisplay(10000));
263         assertEquals("1,000,000 bytes", "977 KB",
264                 ArchiveUtils.formatBytesForDisplay(1000000));
265         assertEquals("100,000,000 bytes", "95 MB",
266                 ArchiveUtils.formatBytesForDisplay(100000000));
267         assertEquals("100,000,000,000 bytes", "93 GB",
268                 ArchiveUtils.formatBytesForDisplay(100000000000L));
269         assertEquals("100,000,000,000,000 bytes", "91 TB",
270                 ArchiveUtils.formatBytesForDisplay(100000000000000L));
271         assertEquals("100,000,000,000,000,000 bytes", "90,949 TB",
272                 ArchiveUtils.formatBytesForDisplay(100000000000000000L));
273     }
274 
275     /*
276      * helper methods
277      */
278 
279     /*** check that this is a bad date, and <code>fail()</code> if so.
280      *
281      * @param date the 12digit date to check
282      */
283     private void assertBad12DigitDate(final String date) {
284         try {
285             ArchiveUtils.parse12DigitDate(date);
286         } catch (ParseException e) {
287             return;
288         }
289         fail("Expected exception on parse of : " + date);
290 
291     }
292     /***
293      * check that this is a bad date, and <code>fail()</code> if so.
294      *
295      * @param date the 14digit date to check
296      */
297     private void assertBad14DigitDate(final String date) {
298         try {
299             ArchiveUtils.parse14DigitDate(date);
300         } catch (ParseException e) {
301             return;
302         }
303         fail("Expected exception on parse of : " + date);
304 
305     }
306 
307     /***
308      * check that this is a bad date, and <code>fail()</code> if so.
309      *
310      * @param date the 17digit date to check
311      */
312     private void assertBad17DigitDate(final String date) {
313         try {
314             ArchiveUtils.parse17DigitDate(date);
315         } catch (ParseException e) {
316             return;
317         }
318         fail("Expected exception on parse of : " + date);
319 
320     }
321 
322     /*** check that two longs are within a given <code>delta</code> */
323     private void assertClose(String desc, long date1, long date2, long delta) {
324         assertTrue(desc, date1 == date2 ||
325                     (date1 < date2 && date2 < (date1 + delta)) ||
326                     (date2 < date1 && date1 < (date2 + delta)));
327     }
328     
329     public void testArrayToLong() {
330         testOneArrayToLong(-1);
331         testOneArrayToLong(1);
332         testOneArrayToLong(1000);
333         testOneArrayToLong(Integer.MAX_VALUE);
334     }
335     
336     private void testOneArrayToLong(final long testValue) {
337         byte [] a = new byte[8];
338         ArchiveUtils.longIntoByteArray(testValue, a, 0);
339         final long l = ArchiveUtils.byteArrayIntoLong(a, 0);
340         assertEquals(testValue, l);
341     }
342     
343     public void testSecondsSinceEpochCalculation() throws ParseException {
344         assertEquals(ArchiveUtils.secondsSinceEpoch("20010909014640"),
345             "1000000000");
346         assertEquals(ArchiveUtils.secondsSinceEpoch("20010909014639"),
347             "0999999999");
348         assertEquals(ArchiveUtils.secondsSinceEpoch("19700101"),
349             "0000000000");
350         assertEquals(ArchiveUtils.secondsSinceEpoch("2005"), "1104537600");
351         assertEquals(ArchiveUtils.secondsSinceEpoch("200501"), "1104537600");
352         assertEquals(ArchiveUtils.secondsSinceEpoch("20050101"), "1104537600");
353         assertEquals(ArchiveUtils.secondsSinceEpoch("2005010100"),
354             "1104537600");
355         boolean eThrown = false;
356         try {
357             ArchiveUtils.secondsSinceEpoch("20050");
358         } catch (IllegalArgumentException e) {
359             eThrown = true;
360         }
361         assertTrue(eThrown);
362     }
363     
364     public static void testZeroPadInteger() {
365         assertEquals(ArchiveUtils.zeroPadInteger(1), "0000000001");
366         assertEquals(ArchiveUtils.zeroPadInteger(1000000000), "1000000000");
367     }
368     
369     /***
370      * Test stable behavior of date formatting under heavy concurrency. 
371      * 
372      * @throws InterruptedException
373      */
374     public static void testDateFormatConcurrency() throws InterruptedException {        
375         final int COUNT = 1000;
376         Thread [] ts = new Thread[COUNT];
377         final Semaphore allDone = new Semaphore(-COUNT+1);
378         final AtomicInteger failures = new AtomicInteger(0); 
379         for (int i = 0; i < COUNT; i++) {
380             Thread t = new Thread() {
381                 public void run() {
382                     long n = System.currentTimeMillis();
383                     final String d = ArchiveUtils.get17DigitDate(n);
384                     for (int i = 0; i < 1000; i++) {
385                         try {
386                             sleep(10);
387                         } catch (InterruptedException e) {
388                             // TODO Auto-generated catch block
389                             e.printStackTrace();
390                         }
391                         String d2 = ArchiveUtils.get17DigitDate(n);
392                         if(!d.equals(d2)) {
393                             failures.incrementAndGet();
394                             break; 
395                         }
396                     }
397                     allDone.release();
398                 }
399             };
400             ts[i] = t;
401             ts[i].setName(Integer.toString(i));
402             ts[i].start();
403             while(!ts[i].isAlive()) /* Wait for thread to spin up*/;
404         }
405         allDone.acquire(); // wait for all threads to finish
406         assertEquals(failures.get()+" format mismatches",0,failures.get()); 
407     }
408     
409     public void testIsTld() {
410         assertTrue("TLD test problem", ArchiveUtils.isTld("com"));
411         assertTrue("TLD test problem", ArchiveUtils.isTld("COM"));
412     }
413 }
414