001package org.eclipse.aether.internal.impl;
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.junit.Assert.*;
023
024import java.io.File;
025import java.nio.charset.StandardCharsets;
026import java.util.ArrayList;
027import java.util.Collections;
028import java.util.HashMap;
029import java.util.List;
030import java.util.Map;
031import java.util.Properties;
032
033import org.eclipse.aether.internal.impl.TrackingFileManager;
034import org.eclipse.aether.internal.test.util.TestFileUtils;
035import org.junit.Test;
036
037/**
038 */
039public class TrackingFileManagerTest
040{
041
042    @Test
043    public void testRead()
044        throws Exception
045    {
046        TrackingFileManager tfm = new TrackingFileManager();
047
048        File propFile = TestFileUtils.createTempFile( "#COMMENT\nkey1=value1\nkey2 : value2" );
049        Properties props = tfm.read( propFile );
050
051        assertNotNull( props );
052        assertEquals( String.valueOf( props ), 2, props.size() );
053        assertEquals( "value1", props.get( "key1" ) );
054        assertEquals( "value2", props.get( "key2" ) );
055
056        assertTrue( "Leaked file: " + propFile, propFile.delete() );
057
058        props = tfm.read( propFile );
059        assertNull( String.valueOf( props ), props );
060    }
061
062    @Test
063    public void testReadNoFileLeak()
064        throws Exception
065    {
066        TrackingFileManager tfm = new TrackingFileManager();
067
068        for ( int i = 0; i < 1000; i++ )
069        {
070            File propFile = TestFileUtils.createTempFile( "#COMMENT\nkey1=value1\nkey2 : value2" );
071            assertNotNull( tfm.read( propFile ) );
072            assertTrue( "Leaked file: " + propFile, propFile.delete() );
073        }
074    }
075
076    @Test
077    public void testUpdate()
078        throws Exception
079    {
080        TrackingFileManager tfm = new TrackingFileManager();
081
082        // NOTE: The excessive repetitions are to check the update properly truncates the file
083        File propFile = TestFileUtils.createTempFile( "key1=value1\nkey2 : value2\n".getBytes( StandardCharsets.UTF_8 ), 1000 );
084
085        Map<String, String> updates = new HashMap<String, String>();
086        updates.put( "key1", "v" );
087        updates.put( "key2", null );
088
089        tfm.update( propFile, updates );
090
091        Properties props = tfm.read( propFile );
092
093        assertNotNull( props );
094        assertEquals( String.valueOf( props ), 1, props.size() );
095        assertEquals( "v", props.get( "key1" ) );
096        assertNull( String.valueOf( props.get( "key2" ) ), props.get( "key2" ) );
097    }
098
099    @Test
100    public void testUpdateNoFileLeak()
101        throws Exception
102    {
103        TrackingFileManager tfm = new TrackingFileManager();
104
105        Map<String, String> updates = new HashMap<String, String>();
106        updates.put( "k", "v" );
107
108        for ( int i = 0; i < 1000; i++ )
109        {
110            File propFile = TestFileUtils.createTempFile( "#COMMENT\nkey1=value1\nkey2 : value2" );
111            assertNotNull( tfm.update( propFile, updates ) );
112            assertTrue( "Leaked file: " + propFile, propFile.delete() );
113        }
114    }
115
116    @Test
117    public void testLockingOnCanonicalPath()
118        throws Exception
119    {
120        final TrackingFileManager tfm = new TrackingFileManager();
121
122        final File propFile = TestFileUtils.createTempFile( "#COMMENT\nkey1=value1\nkey2 : value2" );
123
124        final List<Throwable> errors = Collections.synchronizedList( new ArrayList<Throwable>() );
125
126        Thread[] threads = new Thread[4];
127        for ( int i = 0; i < threads.length; i++ )
128        {
129            String path = propFile.getParent();
130            for ( int j = 0; j < i; j++ )
131            {
132                path += "/.";
133            }
134            path += "/" + propFile.getName();
135            final File file = new File( path );
136
137            threads[i] = new Thread()
138            {
139                public void run()
140                {
141                    try
142                    {
143                        for ( int i = 0; i < 1000; i++ )
144                        {
145                            assertNotNull( tfm.read( file ) );
146                        }
147                    }
148                    catch ( Throwable e )
149                    {
150                        errors.add( e );
151                    }
152                }
153            };
154        }
155
156        for ( Thread thread1 : threads )
157        {
158            thread1.start();
159        }
160
161        for ( Thread thread : threads )
162        {
163            thread.join();
164        }
165
166        assertEquals( Collections.emptyList(), errors );
167    }
168
169}