package org.apache.maven.index.updater;

/*
 * 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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Properties;
import java.util.Set;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.RAMDirectory;
import org.apache.maven.index.ArtifactInfo;
import org.apache.maven.index.FlatSearchRequest;
import org.apache.maven.index.FlatSearchResponse;
import org.apache.maven.index.MAVEN;
import org.apache.maven.index.SearchType;
import org.apache.maven.index.context.IndexUtils;
import org.apache.maven.index.context.IndexingContext;
import org.codehaus.plexus.util.IOUtil;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.api.Invocation;
import org.jmock.lib.action.ReturnValueAction;
import org.jmock.lib.action.VoidAction;
import org.junit.Ignore;

/**
 * @author Eugene Kuleshov
 */
public class DefaultIndexUpdaterTest
    extends AbstractIndexUpdaterTest
{

    SimpleDateFormat df = new SimpleDateFormat( "yyyyMMddHHmmss.SSS Z" );

    public void testReplaceIndex()
        throws Exception
    {
        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
            context );

        Query q = indexer.constructQuery( MAVEN.ARTIFACT_ID, "commons-lang", SearchType.SCORED );

        FlatSearchResponse response1 = indexer.searchFlat( new FlatSearchRequest( q ) );
        Collection<ArtifactInfo> content1 = response1.getResults();

        assertEquals( content1.toString(), 1, content1.size() );

        // updated index

        Directory tempIndexDirectory = new RAMDirectory();

        IndexingContext tempContext =
            indexer.addIndexingContext( repositoryId + "temp", repositoryId, null, tempIndexDirectory, repositoryUrl,
                null, MIN_CREATORS );

        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.3", null ),
            tempContext );

        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.4", null ),
            tempContext );

        FlatSearchResponse response2 = indexer.searchFlat( new FlatSearchRequest( q, tempContext ) );
        Collection<ArtifactInfo> tempContent = response2.getResults();
        assertEquals( tempContent.toString(), 2, tempContent.size() );

        // RAMDirectory is closed with context, forcing timestamp update
        tempContext.updateTimestamp( true );

        // A change in RAMDirectory and Directory behavior in general: it will copy the Index files ONLY
        // So we must make sure that timestamp file is transferred correctly.
        RAMDirectory tempDir2 = new RAMDirectory();
        IndexUtils.copyDirectory( tempContext.getIndexDirectory(), tempDir2 );

        Date newIndexTimestamp = tempContext.getTimestamp();

        indexer.removeIndexingContext( tempContext, false );

        context.replace( tempDir2 );

        assertEquals( newIndexTimestamp, context.getTimestamp() );

        FlatSearchResponse response3 = indexer.searchFlat( new FlatSearchRequest( q ) );
        Collection<ArtifactInfo> content2 = response3.getResults();
        assertEquals( content2.toString(), 2, content2.size() );
    }

    public void testMergeIndex()
        throws Exception
    {
        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
            context );

        Query q = indexer.constructQuery( MAVEN.ARTIFACT_ID, "commons-lang", SearchType.SCORED );

        {
            FlatSearchResponse response1 = indexer.searchFlat( new FlatSearchRequest( q ) );
            Collection<ArtifactInfo> content1 = response1.getResults();

            assertEquals( content1.toString(), 1, content1.size() );
        }

        // updated index

        {
            Directory tempIndexDirectory = new RAMDirectory();

            IndexingContext tempContext =
                indexer.addIndexingContext( repositoryId + "temp", repositoryId, null, tempIndexDirectory,
                    repositoryUrl, null, MIN_CREATORS );

            // indexer.addArtifactToIndex(
            // createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
            // tempContext );

            indexer.addArtifactToIndex(
                createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.3", null ), tempContext );

            indexer.addArtifactToIndex(
                createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.4", null ), tempContext );

            FlatSearchResponse tempResponse = indexer.searchFlat( new FlatSearchRequest( q ) );
            Collection<ArtifactInfo> tempContent = tempResponse.getResults();
            assertEquals( tempContent.toString(), 3, tempContent.size() );

            RAMDirectory tempDir2 = new RAMDirectory( tempContext.getIndexDirectory(), IOContext.DEFAULT );

            indexer.removeIndexingContext( tempContext, false );

            context.merge( tempDir2 );

            FlatSearchResponse response2 = indexer.searchFlat( new FlatSearchRequest( q ) );
            Collection<ArtifactInfo> content2 = response2.getResults();
            assertEquals( content2.toString(), 3, content2.size() );
        }
    }

    public void testMergeIndexDeletes()
        throws Exception
    {
        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
            context );

        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.3", null ),
            context );

        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.4", null ),
            context );

        {
            Directory tempIndexDirectory = new RAMDirectory();

            IndexingContext tempContext =
                indexer.addIndexingContext( repositoryId + "temp", repositoryId, null, tempIndexDirectory,
                    repositoryUrl, null, MIN_CREATORS );

            indexer.addArtifactToIndex(
                createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.4", null ), tempContext );

            indexer.addArtifactToIndex(
                createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ), tempContext );

            indexer.deleteArtifactFromIndex(
                createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ), tempContext );

            indexer.deleteArtifactFromIndex(
                createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.4", null ), tempContext );

            RAMDirectory tempDir2 = new RAMDirectory( tempContext.getIndexDirectory(), IOContext.DEFAULT );

            indexer.removeIndexingContext( tempContext, false );

            context.merge( tempDir2 );
        }

        Query q = indexer.constructQuery( MAVEN.ARTIFACT_ID, "commons-lang", SearchType.SCORED );

        FlatSearchResponse response = indexer.searchFlat( new FlatSearchRequest( q ) );
        Collection<ArtifactInfo> content2 = response.getResults();

        assertEquals( content2.toString(), 1, content2.size() );
    }

    public void testMergeSearch()
        throws Exception
    {
        File repo1 = new File( getBasedir(), "src/test/nexus-658" );
        Directory indexDir1 = new RAMDirectory();

        IndexingContext context1 =
            indexer.addIndexingContext( "nexus-658", "nexus-658", repo1, indexDir1, null, null, DEFAULT_CREATORS );
        indexer.scan( context1 );

        File repo2 = new File( getBasedir(), "src/test/nexus-13" );
        Directory indexDir2 = new RAMDirectory();

        IndexingContext context2 =
            indexer.addIndexingContext( "nexus-13", "nexus-13", repo2, indexDir2, null, null, DEFAULT_CREATORS );
        indexer.scan( context2 );

        context1.merge( indexDir2 );

        Query q = new TermQuery( new Term( ArtifactInfo.SHA1, "b5e9d009320d11b9859c15d3ad3603b455fa1c85" ) );
        FlatSearchRequest request = new FlatSearchRequest( q, context1 );
        FlatSearchResponse response = indexer.searchFlat( request );

        Set<ArtifactInfo> results = response.getResults();
        ArtifactInfo artifactInfo = results.iterator().next();
        assertEquals( artifactInfo.getArtifactId(), "dma.integration.tests" );
    }

    public void testMergeGroups()
        throws Exception
    {
        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
            context );

        indexer.addArtifactToIndex(
            createArtifactContext( repositoryId, "commons-collections", "commons-collections", "1.0", null ), context );

        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "org.slf4j", "slf4j-api", "1.4.2", null ),
            context );

        indexer.addArtifactToIndex( createArtifactContext( repositoryId, "org.slf4j", "slf4j-log4j12", "1.4.2", null ),
            context );

        {
            Directory tempIndexDirectory = new RAMDirectory();

            IndexingContext tempContext =
                indexer.addIndexingContext( repositoryId + "temp", repositoryId, null, tempIndexDirectory,
                    repositoryUrl, null, MIN_CREATORS );

            indexer.addArtifactToIndex(
                createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.4", null ), tempContext );

            indexer.addArtifactToIndex( createArtifactContext( repositoryId, "junit", "junit", "3.8", null ),
                tempContext );

            indexer.addArtifactToIndex(
                createArtifactContext( repositoryId, "org.slf4j.foo", "jcl104-over-slf4j", "1.4.2", null ), context );

            RAMDirectory tempDir2 = new RAMDirectory( tempContext.getIndexDirectory(), IOContext.DEFAULT );

            indexer.removeIndexingContext( tempContext, false );

            context.merge( tempDir2 );
        }

        Set<String> rootGroups = context.getRootGroups();

        assertEquals( rootGroups.toString(), 4, rootGroups.size() );

        Set<String> allGroups = context.getAllGroups();

        assertEquals( allGroups.toString(), 5, allGroups.size() );
    }

    public void testNoIndexUpdate()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081125010000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        final Properties localProps = new Properties();
        localProps.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "1" );
        localProps.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );
        localProps.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081125010000.000 -0600" );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getIndexDirectoryFile();
                will( new IndexDirectoryFileAction( localProps, testBasedir ) );

                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).commit();

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081125010000.000 -0600" );
                        return properties;
                    }
                } );

                allowing( tempContext ).getIndexDirectoryFile();

                oneOf( mockFetcher ).disconnect();
            }
        } );

        // tempContext.updateTimestamp( true, contextTimestamp );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateSucceeded(updateResult);
    }

    public void testFullIndexUpdate()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081125010000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getIndexDirectoryFile();
                will( new ReturnValueAction( testBasedir ) );

                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).commit();

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                allowing( tempContext ).commit();

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081126010000.000 -0600" );
                        return properties;
                    }
                } );

                allowing( tempContext ).getIndexDirectoryFile();

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".gz" ) );
                will( returnValue( newInputStream( "/index-updater/server-root/nexus-maven-repository-index.gz" ) ) );

                oneOf( tempContext ).replace( with( any( Directory.class ) ) );

                oneOf( mockFetcher ).disconnect();
            }
        } );

        // tempContext.updateTimestamp( true, contextTimestamp );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateSucceeded(updateResult);
    }

    public void testIncrementalIndexUpdate()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081128000000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        final Properties localProps = new Properties();
        localProps.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "1" );
        localProps.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).commit();

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081129174241.859 -0600" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "3" );
                        properties.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "0", "3" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "1", "2" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "2", "1" );
                        return properties;
                    }
                } );

                allowing( tempContext ).getIndexDirectoryFile();
                will( new IndexDirectoryFileAction( localProps, testBasedir ) );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".2.gz" ) );
                will( returnValue( newInputStream( "/index-updater/server-root/nexus-maven-repository-index.gz" ) ) );
                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".3.gz" ) );
                will( returnValue( newInputStream( "/index-updater/server-root/nexus-maven-repository-index.gz" ) ) );
                // could create index archive there and verify that it is merged correctly

                oneOf( tempContext ).merge( with( any( Directory.class ) ) );

                oneOf( tempContext ).merge( with( any( Directory.class ) ) );

                oneOf( mockFetcher ).disconnect();
            }
        } );

        // tempContext.updateTimestamp( true, contextTimestamp );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );
        updateRequest.setIncrementalOnly(true);

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateSucceeded(updateResult);
    }

    public void testIncrementalIndexUpdateNoCounter()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081128000000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getIndexDirectoryFile();
                will( new ReturnValueAction( testBasedir ) );

                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).commit();

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081129174241.859 -0600" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "3" );
                        properties.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "0", "3" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "1", "2" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "2", "1" );
                        return properties;
                    }
                } );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".gz" ) );
                will( returnValue( newInputStream( "/index-updater/server-root/nexus-maven-repository-index.gz" ) ) );
                // could create index archive there and verify that it is merged correctly

                oneOf( tempContext ).replace( with( any( Directory.class ) ) );

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".2.gz" ) );

                never( tempContext ).merge( with( any( Directory.class ) ) );

                oneOf( mockFetcher ).disconnect();
            }
        } );

        // tempContext.updateTimestamp( true, contextTimestamp );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateSucceeded(updateResult);
    }
    
    public void testIncrementalOnlyIndexUpdateNoCounter()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081128000000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getIndexDirectoryFile();
                will( new ReturnValueAction( testBasedir ) );

                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081129174241.859 -0600" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "3" );
                        properties.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "0", "3" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "1", "2" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "2", "1" );
                        return properties;
                    }
                } );

                oneOf( mockFetcher ).disconnect();
            }
        } );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );
        updateRequest.setIncrementalOnly(true);

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateFailed(updateResult);
    }

    public void testIncrementalIndexUpdateNoUpdateNecessary()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081128000000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        final Properties localProps = new Properties();
        localProps.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "3" );
        localProps.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                allowing( tempContext ).commit();

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081129174241.859 -0600" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "3" );
                        properties.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "0", "3" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "1", "2" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "2", "1" );
                        return properties;
                    }
                } );

                allowing( tempContext ).getIndexDirectoryFile();
                will( new IndexDirectoryFileAction( localProps, testBasedir ) );

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".gz" ) );
                // could create index archive there and verify that it is merged correctly

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".1.gz" ) );

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".2.gz" ) );

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".3.gz" ) );

                never( tempContext ).merge( with( any( Directory.class ) ) );

                never( tempContext ).replace( with( any( Directory.class ) ) );

                oneOf( mockFetcher ).disconnect();
            }
        } );

        // tempContext.updateTimestamp( true, contextTimestamp );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateSucceeded(updateResult);
    }

    public void testUpdateForceFullUpdate()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081128000000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getIndexDirectoryFile();
                will( new ReturnValueAction( testBasedir ) );

                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).commit();

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_TIMESTAMP, "20081129174241.859 -0600" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_COUNTER, "3" );
                        properties.setProperty( IndexingContext.INDEX_CHAIN_ID, "someid" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "0", "3" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "1", "2" );
                        properties.setProperty( IndexingContext.INDEX_CHUNK_PREFIX + "2", "1" );
                        return properties;
                    }
                } );

                never( tempContext ).getIndexDirectoryFile();

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".1.gz" ) );

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".2.gz" ) );

                never( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_FILE_PREFIX + ".3.gz" ) );

                oneOf( mockFetcher ).retrieve( with( IndexingContext.INDEX_FILE_PREFIX + ".gz" ) );
                will( returnValue( newInputStream( "/index-updater/server-root/nexus-maven-repository-index.gz" ) ) );

                never( tempContext ).merge( with( any( Directory.class ) ) );

                never( tempContext ).merge( with( any( Directory.class ) ) );

                oneOf( tempContext ).replace( with( any( Directory.class ) ) );

                oneOf( mockFetcher ).disconnect();
            }
        } );

        // tempContext.updateTimestamp( true, contextTimestamp );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );

        updateRequest.setForceFullUpdate( true );

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateSucceeded(updateResult);
    }

    @Ignore("Legacy format no longer supported with Lucene 4")
    public void ignoreTestUpdateForceFullUpdateNoGZ()
        throws Exception
    {
        Mockery mockery = new Mockery();

        final String indexUrl = repositoryUrl + ".index";
        final Date contextTimestamp = df.parse( "20081128000000.000 -0600" );

        final ResourceFetcher mockFetcher = mockery.mock( ResourceFetcher.class );

        final IndexingContext tempContext = mockery.mock( IndexingContext.class );

        mockery.checking( new Expectations()
        {
            {
                allowing( tempContext ).getIndexDirectoryFile();
                will( new ReturnValueAction( testBasedir ) );

                allowing( tempContext ).getTimestamp();
                will( returnValue( contextTimestamp ) );

                allowing( tempContext ).commit();

                allowing( tempContext ).getId();
                will( returnValue( repositoryId ) );

                allowing( tempContext ).getIndexUpdateUrl();
                will( returnValue( indexUrl ) );

                allowing( tempContext ).getIndexCreators();
                will( returnValue( DEFAULT_CREATORS ) );

                oneOf( mockFetcher ).connect( repositoryId, indexUrl );

                oneOf( mockFetcher ).retrieve( //
                    with( IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ) );
                will( new PropertiesAction()
                {
                    @Override
                    Properties getProperties()
                    {
                        Properties properties = new Properties();
                        properties.setProperty( IndexingContext.INDEX_ID, "central" );
                        properties.setProperty( IndexingContext.INDEX_LEGACY_TIMESTAMP, "20081129174241.859 -0600" );
                        return properties;
                    }
                } );

                never( tempContext ).getIndexDirectoryFile();

                oneOf( mockFetcher ).retrieve( with( IndexingContext.INDEX_FILE_PREFIX + ".gz" ) );

                will( throwException( new IOException() ) );

                oneOf( mockFetcher ).retrieve( with( IndexingContext.INDEX_FILE_PREFIX + ".zip" ) );

                will( returnValue( newInputStream( "/index-updater/server-root/legacy/nexus-maven-repository-index.zip" ) ) );

                never( tempContext ).merge( with( any( Directory.class ) ) );

                never( tempContext ).merge( with( any( Directory.class ) ) );

                oneOf( tempContext ).replace( with( any( Directory.class ) ) );

                oneOf( mockFetcher ).disconnect();
            }
        } );

        // tempContext.updateTimestamp( true, contextTimestamp );

        IndexUpdateRequest updateRequest = new IndexUpdateRequest( tempContext, mockFetcher );

        updateRequest.setForceFullUpdate( true );

        IndexUpdateResult updateResult = updater.fetchAndUpdateIndex( updateRequest );

        mockery.assertIsSatisfied();
        assertIndexUpdateSucceeded(updateResult);
    }

    protected InputStream newInputStream( String path )
    {
        return getResourceAsStream( path );
    }

    abstract static class PropertiesAction
        extends VoidAction
    {
        @Override
        public Object invoke( Invocation invocation )
            throws Throwable
        {
            Properties properties = getProperties();

            try (ByteArrayOutputStream buf = new ByteArrayOutputStream())
            {
                properties.store( buf, null );
                buf.flush();
                return new ByteArrayInputStream( buf.toByteArray() );
            }

        }

        abstract Properties getProperties();
    }

    private static class IndexDirectoryFileAction
        extends VoidAction
    {
        File file = null;

        public IndexDirectoryFileAction( Properties properties, File basedir )
            throws Exception
        {
            basedir.mkdirs();

            this.file = new File( basedir, IndexingContext.INDEX_UPDATER_PROPERTIES_FILE );

            try ( FileOutputStream fos = new FileOutputStream( this.file ))
            {
                properties.store( fos, "" );
            }
        }

        @Override
        public Object invoke( Invocation invocation )
            throws Throwable
        {
            return this.file.getParentFile();
        }
    }
    
    private void assertIndexUpdateSucceeded(IndexUpdateResult updateResult)
    {
        assertTrue("Index update should have succeeded, but says it failed", updateResult.isSuccessful());
    }
    
    private void assertIndexUpdateFailed(IndexUpdateResult updateResult)
    {
        assertFalse("Index update should have failed, but says it succeeded", updateResult.isSuccessful());
    }
}