View Javadoc

    1   /* ArchiveUtilsTest
    2    *
    3    * $Id: ArchiveUtilsTest.java 5052 2007-04-10 02:26:52Z 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.LinkedList;
    30  import java.util.concurrent.Semaphore;
    31  import java.util.concurrent.atomic.AtomicInteger;
    32  import java.text.ParseException;
    33
    34  import junit.framework.Test;
    35  import junit.framework.TestCase;
    36  import junit.framework.TestSuite;
    37
    38  /***
    39   * JUnit test suite for ArchiveUtils
    40   *
    41   * @author <a href="mailto:me@jamesc.net">James Casey</a>
    42   * @version $Id: ArchiveUtilsTest.java 5052 2007-04-10 02:26:52Z 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