001package org.eclipse.aether.util;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import static org.eclipse.aether.internal.test.util.TestFileUtils.*;
023import static org.junit.Assert.*;
024
025import java.io.File;
026import java.io.IOException;
027import java.nio.charset.StandardCharsets;
028import java.util.Arrays;
029import java.util.HashMap;
030import java.util.Map;
031import java.util.Map.Entry;
032
033import org.eclipse.aether.util.ChecksumUtils;
034import org.junit.Before;
035import org.junit.BeforeClass;
036import org.junit.Test;
037
038public class ChecksumUtilTest
039{
040    private File emptyFile;
041
042    private File patternFile;
043
044    private File textFile;
045
046    private static Map<String, String> emptyFileChecksums = new HashMap<String, String>();
047
048    private static Map<String, String> patternFileChecksums = new HashMap<String, String>();
049
050    private static Map<String, String> textFileChecksums = new HashMap<String, String>();
051
052    private Map<File, Map<String, String>> sums = new HashMap<File, Map<String, String>>();
053
054    @BeforeClass
055    public static void beforeClass()
056        throws IOException
057    {
058        emptyFileChecksums.put( "MD5", "d41d8cd98f00b204e9800998ecf8427e" );
059        emptyFileChecksums.put( "SHA-1", "da39a3ee5e6b4b0d3255bfef95601890afd80709" );
060        patternFileChecksums.put( "MD5", "14f01d6c7de7d4cf0a4887baa3528b5a" );
061        patternFileChecksums.put( "SHA-1", "feeeda19f626f9b0ef6cbf5948c1ec9531694295" );
062        textFileChecksums.put( "MD5", "12582d1a662cefe3385f2113998e43ed" );
063        textFileChecksums.put( "SHA-1", "a8ae272db549850eef2ff54376f8cac2770745ee" );
064    }
065
066    @Before
067    public void before()
068        throws IOException
069    {
070        sums.clear();
071
072        emptyFile = createTempFile( new byte[] {}, 0 );
073        sums.put( emptyFile, emptyFileChecksums );
074
075        patternFile =
076            createTempFile( new byte[] { 0, 1, 2, 4, 8, 16, 32, 64, 127, -1, -2, -4, -8, -16, -32, -64, -127 }, 1000 );
077        sums.put( patternFile, patternFileChecksums );
078
079        textFile = createTempFile( "the quick brown fox jumps over the lazy dog\n".getBytes( StandardCharsets.UTF_8 ), 500 );
080        sums.put( textFile, textFileChecksums );
081
082    }
083
084    @Test
085    public void testEquality()
086        throws Throwable
087    {
088        Map<String, Object> checksums = null;
089
090        for ( File file : new File[] { emptyFile, patternFile, textFile } )
091        {
092
093            checksums = ChecksumUtils.calc( file, Arrays.asList( "SHA-1", "MD5" ) );
094
095            for ( Entry<String, Object> entry : checksums.entrySet() )
096            {
097                if ( entry.getValue() instanceof Throwable )
098                {
099                    throw (Throwable) entry.getValue();
100                }
101                String actual = entry.getValue().toString();
102                String expected = sums.get( file ).get( entry.getKey() );
103                assertEquals( String.format( "checksums do not match for '%s', algorithm '%s'", file.getName(),
104                                             entry.getKey() ), expected, actual );
105            }
106            assertTrue( "Could not delete file", file.delete() );
107        }
108    }
109
110    @Test
111    public void testFileHandleLeakage()
112        throws IOException
113    {
114        for ( File file : new File[] { emptyFile, patternFile, textFile } )
115        {
116            for ( int i = 0; i < 150; i++ )
117            {
118                ChecksumUtils.calc( file, Arrays.asList( "SHA-1", "MD5" ) );
119            }
120            assertTrue( "Could not delete file", file.delete() );
121        }
122
123    }
124
125    @Test
126    public void testRead()
127        throws IOException
128    {
129        for ( Map<String, String> checksums : sums.values() )
130        {
131            String sha1 = checksums.get( "SHA-1" );
132            String md5 = checksums.get( "MD5" );
133
134            File sha1File = createTempFile( sha1 );
135            File md5File = createTempFile( md5 );
136
137            assertEquals( sha1, ChecksumUtils.read( sha1File ) );
138            assertEquals( md5, ChecksumUtils.read( md5File ) );
139
140            assertTrue( "ChecksumUtils leaks file handles (cannot delete checksums.sha1)", sha1File.delete() );
141            assertTrue( "ChecksumUtils leaks file handles (cannot delete checksums.md5)", md5File.delete() );
142        }
143    }
144
145    @Test
146    public void testReadSpaces()
147        throws IOException
148    {
149        for ( Map<String, String> checksums : sums.values() )
150        {
151            String sha1 = checksums.get( "SHA-1" );
152            String md5 = checksums.get( "MD5" );
153
154            File sha1File = createTempFile( "sha1-checksum = " + sha1 );
155            File md5File = createTempFile( md5 + " test" );
156
157            assertEquals( sha1, ChecksumUtils.read( sha1File ) );
158            assertEquals( md5, ChecksumUtils.read( md5File ) );
159
160            assertTrue( "ChecksumUtils leaks file handles (cannot delete checksums.sha1)", sha1File.delete() );
161            assertTrue( "ChecksumUtils leaks file handles (cannot delete checksums.md5)", md5File.delete() );
162        }
163    }
164
165    @Test
166    public void testReadEmptyFile()
167        throws IOException
168    {
169        File file = createTempFile( "" );
170
171        assertEquals( "", ChecksumUtils.read( file ) );
172
173        assertTrue( "ChecksumUtils leaks file handles (cannot delete checksum.empty)", file.delete() );
174    }
175
176    @Test
177    public void testToHexString()
178    {
179        assertEquals( null, ChecksumUtils.toHexString( null ) );
180        assertEquals( "", ChecksumUtils.toHexString( new byte[] {} ) );
181        assertEquals( "00", ChecksumUtils.toHexString( new byte[] { 0 } ) );
182        assertEquals( "ff", ChecksumUtils.toHexString( new byte[] { -1 } ) );
183        assertEquals( "00017f", ChecksumUtils.toHexString( new byte[] { 0, 1, 127 } ) );
184    }
185
186}