package org.apache.archiva.audit;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import junit.framework.TestCase;
import org.apache.archiva.configuration.ManagedRepositoryConfiguration;
import org.apache.archiva.metadata.model.facets.AuditEvent;
import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.test.utils.ArchivaBlockJUnit4ClassRunner;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

@RunWith(ArchivaBlockJUnit4ClassRunner.class)
public class AuditManagerTest
    extends TestCase
{
    private DefaultAuditManager auditManager;

    private IMocksControl metadataRepositoryControl;

    private MetadataRepository metadataRepository;

    private static final String AUDIT_EVENT_BASE = "2010/01/18/123456.";

    private static final String TEST_REPO_ID = "test-repo";

    private static final String TEST_REPO_ID_2 = "repo2";

    private static final String TEST_USER = "test_user";

    private static final String TEST_RESOURCE_BASE = "test/resource";

    private static final String TEST_IP_ADDRESS = "127.0.0.1";

    private static final SimpleDateFormat TIMESTAMP_FORMAT = createTimestampFormat();

    private static final DecimalFormat MILLIS_FORMAT = new DecimalFormat( "000" );

    private static SimpleDateFormat createTimestampFormat()
    {
        SimpleDateFormat fmt = new SimpleDateFormat( AuditEvent.TIMESTAMP_FORMAT );
        fmt.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
        return fmt;
    }

    @Override
    @Before
    public void setUp()
        throws Exception
    {
        super.setUp();

        auditManager = new DefaultAuditManager();

        metadataRepositoryControl = EasyMock.createControl();
        metadataRepository = metadataRepositoryControl.createMock( MetadataRepository.class );

        ManagedRepositoryConfiguration repository = new ManagedRepositoryConfiguration();
        repository.setId( TEST_REPO_ID );
        repository.setLocation( "" );
    }

    @Test
    public void testGetMostRecentEvents()
        throws Exception
    {
        int numEvents = 11;
        List<AuditEvent> expectedEvents = new ArrayList<>( numEvents );
        for ( int i = 0; i < numEvents; i++ )
        {
            AuditEvent event = createEvent( AUDIT_EVENT_BASE + MILLIS_FORMAT.format( i ) );
            expectedEvents.add( event );
        }

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            getEventNames( expectedEvents ) );

        for ( AuditEvent event : expectedEvents.subList( 1, expectedEvents.size() ) )
        {
            EasyMock.expect(
                metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID, event.getName() ) ).andReturn(
                event );
        }
        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getMostRecentAuditEvents( metadataRepository, Collections.singletonList( TEST_REPO_ID ) );
        assertNotNull( events );
        assertEquals( numEvents - 1, events.size() );
        int expectedTimestampCounter = numEvents - 1;
        for ( AuditEvent event : events )
        {
            String num = MILLIS_FORMAT.format( expectedTimestampCounter );
            assertTestEvent( event, AUDIT_EVENT_BASE + num, getDefaultTestResourceName( num ) );
            expectedTimestampCounter--;
        }

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetMostRecentEventsLessThan10()
        throws Exception
    {
        int numEvents = 5;
        List<AuditEvent> expectedEvents = new ArrayList<>( numEvents );
        for ( int i = 0; i < numEvents; i++ )
        {
            expectedEvents.add( createEvent( AUDIT_EVENT_BASE + MILLIS_FORMAT.format( i ) ) );
        }

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            getEventNames( expectedEvents ) );
        for ( AuditEvent event : expectedEvents )
        {
            EasyMock.expect(
                metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID, event.getName() ) ).andReturn(
                event );
        }
        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getMostRecentAuditEvents( metadataRepository, Collections.singletonList( TEST_REPO_ID ) );
        assertNotNull( events );
        assertEquals( numEvents, events.size() );
        int expectedTimestampCounter = numEvents - 1;
        for ( AuditEvent event : events )
        {
            String num = MILLIS_FORMAT.format( expectedTimestampCounter );
            assertTestEvent( event, AUDIT_EVENT_BASE + num, getDefaultTestResourceName( num ) );
            expectedTimestampCounter--;
        }

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetMostRecentEventsInterleavedRepositories()
        throws Exception
    {
        int numEvents = 11;
        Map<String, List<String>> eventNames = new LinkedHashMap<String, List<String>>();
        List<AuditEvent> events = new ArrayList<>();
        eventNames.put( TEST_REPO_ID, new ArrayList<String>() );
        eventNames.put( TEST_REPO_ID_2, new ArrayList<String>() );
        for ( int i = 0; i < numEvents; i++ )
        {
            String repositoryId = i % 2 == 0 ? TEST_REPO_ID : TEST_REPO_ID_2;
            String num = MILLIS_FORMAT.format( i );
            AuditEvent event = createEvent( repositoryId, AUDIT_EVENT_BASE + num, getDefaultTestResourceName( num ) );
            events.add( event );
            eventNames.get( repositoryId ).add( event.getName() );
        }

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            eventNames.get( TEST_REPO_ID ) );
        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID_2, AuditEvent.FACET_ID ) ).andReturn(
            eventNames.get( TEST_REPO_ID_2 ) );

        for ( AuditEvent event : events.subList( 1, events.size() ) )
        {
            EasyMock.expect( metadataRepository.getMetadataFacet( event.getRepositoryId(), AuditEvent.FACET_ID,
                                                                  event.getName() ) ).andReturn( event );
        }
        metadataRepositoryControl.replay();

        events =
            auditManager.getMostRecentAuditEvents( metadataRepository, Arrays.asList( TEST_REPO_ID, TEST_REPO_ID_2 ) );
        assertNotNull( events );
        assertEquals( numEvents - 1, events.size() );
        int expectedTimestampCounter = numEvents - 1;
        for ( AuditEvent event : events )
        {
            String num = MILLIS_FORMAT.format( expectedTimestampCounter );
            String expectedRepoId = expectedTimestampCounter % 2 == 0 ? TEST_REPO_ID : TEST_REPO_ID_2;
            assertTestEvent( event, expectedRepoId, AUDIT_EVENT_BASE + num, getDefaultTestResourceName( num ) );
            expectedTimestampCounter--;
        }

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetMostRecentEventsWhenEmpty()
        throws Exception

    {

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            Collections.<String>emptyList() );
        metadataRepositoryControl.replay();

        assertTrue( auditManager.getMostRecentAuditEvents( metadataRepository,
                                                           Collections.singletonList( TEST_REPO_ID ) ).isEmpty() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testAddAuditEvent()
        throws Exception

    {
        AuditEvent event = createEvent( new Date() );

        metadataRepository.addMetadataFacet( TEST_REPO_ID, event );

        metadataRepositoryControl.replay();

        auditManager.addAuditEvent( metadataRepository, event );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testAddAuditEventNoRepositoryId()
        throws Exception
    {
        AuditEvent event = createEvent( new Date() );
        event.setRepositoryId( null );

        // should just be ignored

        metadataRepositoryControl.replay();

        auditManager.addAuditEvent( metadataRepository, event );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testDeleteStats()
        throws Exception

    {
        metadataRepository.removeMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID );

        metadataRepositoryControl.replay();

        auditManager.deleteAuditEvents( metadataRepository, TEST_REPO_ID );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsRangeInside()
        throws Exception

    {
        Date current = new Date();

        AuditEvent event1 = createEvent( new Date( current.getTime() - 12345 ) );
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        AuditEvent expectedEvent = createEvent( expectedTimestamp );
        AuditEvent event3 = createEvent( new Date( current.getTime() - 1000 ) );

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            Arrays.asList( event1.getName(), expectedEvent.getName(), event3.getName() ) );

        // only match the middle one
        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent.getName() ) ).andReturn( expectedEvent );

        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Collections.singletonList( TEST_REPO_ID ),
                                                new Date( current.getTime() - 4000 ),
                                                new Date( current.getTime() - 2000 ) );

        assertEquals( 1, events.size() );
        assertTestEvent( events.get( 0 ), TIMESTAMP_FORMAT.format( expectedTimestamp ), expectedEvent.getResource() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsRangeUpperOutside()
        throws Exception
    {
        Date current = new Date();

        AuditEvent event1 = createEvent( new Date( current.getTime() - 12345 ) );
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        AuditEvent expectedEvent2 = createEvent( expectedTimestamp );
        Date ts3 = new Date( current.getTime() - 1000 );
        AuditEvent expectedEvent3 = createEvent( ts3 );

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            Arrays.asList( event1.getName(), expectedEvent2.getName(), expectedEvent3.getName() ) );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent2.getName() ) ).andReturn( expectedEvent2 );
        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent3.getName() ) ).andReturn( expectedEvent3 );
        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Collections.singletonList( TEST_REPO_ID ),
                                                new Date( current.getTime() - 4000 ), current );

        assertEquals( 2, events.size() );
        assertTestEvent( events.get( 0 ), TIMESTAMP_FORMAT.format( ts3 ), expectedEvent3.getResource() );
        assertTestEvent( events.get( 1 ), TIMESTAMP_FORMAT.format( expectedTimestamp ), expectedEvent2.getResource() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsRangeLowerOutside()
        throws Exception
    {
        Date current = new Date();

        Date ts1 = new Date( current.getTime() - 12345 );
        AuditEvent expectedEvent1 = createEvent( ts1 );
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        AuditEvent expectedEvent2 = createEvent( expectedTimestamp );
        AuditEvent event3 = createEvent( new Date( current.getTime() - 1000 ) );

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            Arrays.asList( expectedEvent1.getName(), expectedEvent2.getName(), event3.getName() ) );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent1.getName() ) ).andReturn( expectedEvent1 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent2.getName() ) ).andReturn( expectedEvent2 );

        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Collections.singletonList( TEST_REPO_ID ),
                                                new Date( current.getTime() - 20000 ),
                                                new Date( current.getTime() - 2000 ) );

        assertEquals( 2, events.size() );
        assertTestEvent( events.get( 0 ), TIMESTAMP_FORMAT.format( expectedTimestamp ), expectedEvent2.getResource() );
        assertTestEvent( events.get( 1 ), TIMESTAMP_FORMAT.format( ts1 ), expectedEvent1.getResource() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsRangeLowerAndUpperOutside()
        throws Exception
    {
        Date current = new Date();

        Date ts1 = new Date( current.getTime() - 12345 );
        AuditEvent expectedEvent1 = createEvent( ts1 );
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        AuditEvent expectedEvent2 = createEvent( expectedTimestamp );
        Date ts3 = new Date( current.getTime() - 1000 );
        AuditEvent expectedEvent3 = createEvent( ts3 );

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            Arrays.asList( expectedEvent1.getName(), expectedEvent2.getName(), expectedEvent3.getName() ) );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent1.getName() ) ).andReturn( expectedEvent1 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent2.getName() ) ).andReturn( expectedEvent2 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent3.getName() ) ).andReturn( expectedEvent3 );
        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Collections.singletonList( TEST_REPO_ID ),
                                                new Date( current.getTime() - 20000 ), current );

        assertEquals( 3, events.size() );
        assertTestEvent( events.get( 0 ), TIMESTAMP_FORMAT.format( ts3 ), expectedEvent3.getResource() );
        assertTestEvent( events.get( 1 ), TIMESTAMP_FORMAT.format( expectedTimestamp ), expectedEvent2.getResource() );
        assertTestEvent( events.get( 2 ), TIMESTAMP_FORMAT.format( ts1 ), expectedEvent1.getResource() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsWithResource()
        throws Exception
    {
        Date current = new Date();

        Date ts1 = new Date( current.getTime() - 12345 );
        AuditEvent expectedEvent1 = createEvent( ts1 );
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        AuditEvent expectedEvent2 = createEvent( expectedTimestamp );
        expectedEvent2.setResource( "different-resource" );
        Date ts3 = new Date( current.getTime() - 1000 );
        AuditEvent expectedEvent3 = createEvent( ts3 );


        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            Arrays.asList( expectedEvent1.getName(), expectedEvent2.getName(), expectedEvent3.getName() ) );


        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent1.getName() ) ).andReturn( expectedEvent1 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent2.getName() ) ).andReturn( expectedEvent2 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID,
                                                              expectedEvent3.getName() ) ).andReturn( expectedEvent3 );
        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Collections.singletonList( TEST_REPO_ID ),
                                                TEST_RESOURCE_BASE, new Date( current.getTime() - 20000 ), current );

        assertEquals( 2, events.size() );
        assertTestEvent( events.get( 0 ), TIMESTAMP_FORMAT.format( ts3 ), expectedEvent3.getResource() );
        assertTestEvent( events.get( 1 ), TIMESTAMP_FORMAT.format( ts1 ), expectedEvent1.getResource() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsWithNonExistantResource()
        throws Exception
    {
        Date current = new Date();

        AuditEvent expectedEvent1 = createEvent( new Date( current.getTime() - 12345 ) );
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        AuditEvent expectedEvent2 = createEvent( expectedTimestamp );
        expectedEvent2.setResource( "different-resource" );
        AuditEvent expectedEvent3 = createEvent( new Date( current.getTime() - 1000 ) );


        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) ).andReturn(
            Arrays.asList( expectedEvent1.getName(), expectedEvent2.getName(), expectedEvent3.getName() ) );


        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID, expectedEvent1.getName() ) ).andReturn( expectedEvent1 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID, expectedEvent2.getName() ) ).andReturn( expectedEvent2 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID, expectedEvent3.getName() ) ).andReturn( expectedEvent3 );

        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Collections.singletonList( TEST_REPO_ID ), "foo",
                                                new Date( current.getTime() - 20000 ), current );

        assertEquals( 0, events.size() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsRangeMultipleRepositories()
        throws Exception
    {
        Date current = new Date();

        Date ts1 = new Date( current.getTime() - 12345 );
        AuditEvent expectedEvent1 = createEvent( ts1 );
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        AuditEvent expectedEvent2 = createEvent( expectedTimestamp );
        expectedEvent2.setRepositoryId( TEST_REPO_ID_2 );
        Date ts3 = new Date( current.getTime() - 1000 );
        AuditEvent expectedEvent3 = createEvent( ts3 );


        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) )
            .andReturn( Arrays.asList( expectedEvent1.getName(), expectedEvent3.getName() )  );

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID_2, AuditEvent.FACET_ID ) )
            .andReturn( Arrays.asList( expectedEvent2.getName() ) );


        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID, expectedEvent1.getName() ) )
            .andReturn( expectedEvent1 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID_2, AuditEvent.FACET_ID, expectedEvent2.getName() ) )
            .andReturn( expectedEvent2 );

        EasyMock.expect( metadataRepository.getMetadataFacet( TEST_REPO_ID, AuditEvent.FACET_ID, expectedEvent3.getName() ) )
            .andReturn( expectedEvent3 );

        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Arrays.asList( TEST_REPO_ID, TEST_REPO_ID_2 ),
                                                new Date( current.getTime() - 20000 ), current );

        assertEquals( 3, events.size() );
        assertTestEvent( events.get( 0 ), TEST_REPO_ID, TIMESTAMP_FORMAT.format( ts3 ), expectedEvent3.getResource() );
        assertTestEvent( events.get( 1 ), TEST_REPO_ID_2, TIMESTAMP_FORMAT.format( expectedTimestamp ),
                         expectedEvent2.getResource() );
        assertTestEvent( events.get( 2 ), TEST_REPO_ID, TIMESTAMP_FORMAT.format( ts1 ), expectedEvent1.getResource() );

        metadataRepositoryControl.verify();
    }

    @Test
    public void testGetEventsRangeNotInside()
        throws Exception
    {
        Date current = new Date();

        String name1 = createEvent( new Date( current.getTime() - 12345 ) ).getName();
        Date expectedTimestamp = new Date( current.getTime() - 3000 );
        String name2 = createEvent( expectedTimestamp ).getName();
        String name3 = createEvent( new Date( current.getTime() - 1000 ) ).getName();

        EasyMock.expect( metadataRepository.getMetadataFacets( TEST_REPO_ID, AuditEvent.FACET_ID ) )
            .andReturn( Arrays.asList( name1, name2, name3 ) );

        metadataRepositoryControl.replay();

        List<AuditEvent> events =
            auditManager.getAuditEventsInRange( metadataRepository, Collections.singletonList( TEST_REPO_ID ),
                                                new Date( current.getTime() - 20000 ),
                                                new Date( current.getTime() - 16000 ) );

        assertEquals( 0, events.size() );

        metadataRepositoryControl.verify();
    }

    private static String getDefaultTestResourceName( String num )
    {
        return TEST_RESOURCE_BASE + "/" + num + ".xml";
    }

    private static AuditEvent createEvent( Date timestamp )
        throws ParseException
    {
        return createEvent( TIMESTAMP_FORMAT.format( timestamp ) );
    }

    private static AuditEvent createEvent( String ts )
        throws ParseException
    {
        return createEvent( TEST_REPO_ID, ts, getDefaultTestResourceName(
            ts.substring( AUDIT_EVENT_BASE.length(), AUDIT_EVENT_BASE.length() + 3 ) ) );
    }

    private static AuditEvent createEvent( String repositoryId, String timestamp, String resource )
        throws ParseException
    {
        AuditEvent event = new AuditEvent();
        event.setTimestamp( TIMESTAMP_FORMAT.parse( timestamp ) );
        event.setAction( AuditEvent.UPLOAD_FILE );
        event.setRemoteIP( TEST_IP_ADDRESS );
        event.setRepositoryId( repositoryId );
        event.setUserId( TEST_USER );
        event.setResource( resource );
        return event;
    }

    private static void assertTestEvent( AuditEvent event, String timestamp, String resource )
    {
        assertTestEvent( event, TEST_REPO_ID, timestamp, resource );
    }

    private static void assertTestEvent( AuditEvent event, String repositoryId, String timestamp, String resource )
    {
        assertEquals( timestamp, TIMESTAMP_FORMAT.format( event.getTimestamp() ) );
        assertEquals( AuditEvent.UPLOAD_FILE, event.getAction() );
        assertEquals( TEST_IP_ADDRESS, event.getRemoteIP() );
        assertEquals( repositoryId, event.getRepositoryId() );
        assertEquals( TEST_USER, event.getUserId() );
        assertEquals( resource, event.getResource() );
    }

    private List<String> getEventNames( List<AuditEvent> events )
    {
        List<String> names = new ArrayList<>( events.size() );
        for ( AuditEvent event : events )
        {
            names.add( event.getName() );
        }
        return names;
    }
}
