package org.apache.maven.plugin.assembly.archive.phase;

/*
 * 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 org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.assembly.InvalidAssemblerConfigurationException;
import org.apache.maven.plugin.assembly.archive.ArchiveCreationException;
import org.apache.maven.plugin.assembly.archive.task.testutils.ArtifactMock;
import org.apache.maven.plugin.assembly.archive.task.testutils.MockAndControlForAddArtifactTask;
import org.apache.maven.plugin.assembly.archive.task.testutils.MockAndControlForAddDependencySetsTask;
import org.apache.maven.plugin.assembly.archive.task.testutils.MockAndControlForAddFileSetsTask;
import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
import org.apache.maven.plugin.assembly.model.Assembly;
import org.apache.maven.plugin.assembly.model.DependencySet;
import org.apache.maven.plugin.assembly.model.FileSet;
import org.apache.maven.plugin.assembly.model.ModuleBinaries;
import org.apache.maven.plugin.assembly.model.ModuleSet;
import org.apache.maven.plugin.assembly.model.ModuleSources;
import org.apache.maven.plugin.assembly.resolved.ResolvedAssembly;
import org.apache.maven.plugin.assembly.resolved.ResolvedModuleSet;
import org.apache.maven.plugin.assembly.testutils.TestFileManager;
import org.apache.maven.plugin.assembly.utils.TypeConversionUtils;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import junit.framework.Assert;
import junit.framework.TestCase;
import org.easymock.classextension.EasyMockSupport;

import static java.util.Collections.singleton;
import static org.apache.maven.plugin.assembly.resolved.ResolvedModuleSet.createResolvedModuleSet;


public class ModuleSetAssemblyPhaseTest
    extends TestCase
{

    private final TestFileManager fileManager = new TestFileManager( "module-set-phase.test.", "" );

    private final Logger logger = new ConsoleLogger( Logger.LEVEL_INFO, "test" );

    @Override
    public void tearDown()
        throws IOException
    {
        fileManager.cleanUp();
    }

    public void testIsDeprecatedModuleSourcesConfigPresent_ShouldCatchOutputDir()
    {
        final ModuleSources sources = new ModuleSources();
        sources.setOutputDirectory( "outdir" );

        final ModuleSetAssemblyPhase phase = createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null );

        assertTrue( phase.isDeprecatedModuleSourcesConfigPresent( sources ) );
    }

    public void testIsDeprecatedModuleSourcesConfigPresent_ShouldCatchInclude()
    {
        final ModuleSources sources = new ModuleSources();
        sources.addInclude( "**/included.txt" );

        final ModuleSetAssemblyPhase phase = createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null );

        assertTrue( phase.isDeprecatedModuleSourcesConfigPresent( sources ) );
    }

    public void testIsDeprecatedModuleSourcesConfigPresent_ShouldCatchExclude()
    {
        final ModuleSources sources = new ModuleSources();
        sources.addExclude( "**/excluded.txt" );

        final ModuleSetAssemblyPhase phase = createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null );

        assertTrue( phase.isDeprecatedModuleSourcesConfigPresent( sources ) );
    }

    public void testIsDeprecatedModuleSourcesConfigPresent_ShouldNotCatchFileMode()
    {
        final ModuleSources sources = new ModuleSources();
        sources.setFileMode( "777" );

        final ModuleSetAssemblyPhase phase = createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null );

        assertFalse( phase.isDeprecatedModuleSourcesConfigPresent( sources ) );
    }

    public void testIsDeprecatedModuleSourcesConfigPresent_ShouldNotCatchDirMode()
    {
        final ModuleSources sources = new ModuleSources();
        sources.setDirectoryMode( "777" );

        final ModuleSetAssemblyPhase phase = createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null );

        assertFalse( phase.isDeprecatedModuleSourcesConfigPresent( sources ) );
    }

    public void testCreateFileSet_ShouldUseModuleDirOnlyWhenOutDirIsNull()
        throws AssemblyFormattingException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final Model model = new Model();
        model.setArtifactId( "artifact" );

        final MavenProject project = new MavenProject( model );

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm, project );

        macTask.expectGetFinalName( null );

        final FileSet fs = new FileSet();

        final ModuleSources sources = new ModuleSources();
        sources.setIncludeModuleDirectory( true );

        final File basedir = fileManager.createTempDir();

        final MavenProject artifactProject = new MavenProject( new Model() );

        artifactProject.setFile( new File( basedir, "pom.xml" ) );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", false );

        artifactProject.setArtifact( artifactMock.getArtifact() );

        mm.replayAll();

        final FileSet result =
            createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null ).createFileSet( fs, sources,
                                                                                                artifactProject,
                                                                                                macTask.configSource );

        assertEquals( "artifact/", result.getOutputDirectory() );

        mm.verifyAll();
    }

    public void testCreateFileSet_ShouldPrependModuleDirWhenOutDirIsProvided()
        throws AssemblyFormattingException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final Model model = new Model();
        model.setArtifactId( "artifact" );

        final MavenProject project = new MavenProject( model );

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm, project );

        macTask.expectGetFinalName( null );

        final FileSet fs = new FileSet();
        fs.setOutputDirectory( "out" );

        final ModuleSources sources = new ModuleSources();
        sources.setIncludeModuleDirectory( true );

        final MavenProject artifactProject = new MavenProject( new Model() );

        final File basedir = fileManager.createTempDir();

        artifactProject.setFile( new File( basedir, "pom.xml" ) );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", false );

        artifactProject.setArtifact( artifactMock.getArtifact() );

        mm.replayAll();

        final FileSet result =
            createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null ).createFileSet( fs, sources,
                                                                                                artifactProject,
                                                                                                macTask.configSource );

        assertEquals( "artifact/out/", result.getOutputDirectory() );

        mm.verifyAll();
    }

    public void testCreateFileSet_ShouldAddExcludesForSubModulesWhenExcludeSubModDirsIsTrue()
        throws AssemblyFormattingException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm, null );

        macTask.expectGetFinalName( null );

        final FileSet fs = new FileSet();

        final ModuleSources sources = new ModuleSources();
        sources.setExcludeSubModuleDirectories( true );

        final Model model = new Model();
        model.setArtifactId( "artifact" );

        model.addModule( "submodule" );

        final MavenProject project = new MavenProject( model );

        final File basedir = fileManager.createTempDir();

        project.setFile( new File( basedir, "pom.xml" ) );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", false );

        project.setArtifact( artifactMock.getArtifact() );

        mm.replayAll();

        final FileSet result =
            createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null ).createFileSet( fs, sources, project,
                                                                                                macTask.configSource );

        assertEquals( 1, result.getExcludes()
                               .size() );
        assertEquals( "submodule/**", result.getExcludes()
                                            .get( 0 ) );

        mm.verifyAll();
    }

    public void testExecute_ShouldSkipIfNoModuleSetsFound()
        throws ArchiveCreationException, AssemblyFormattingException, InvalidAssemblerConfigurationException
    {
        final Assembly assembly = new Assembly();
        assembly.setIncludeBaseDirectory( false );

        createPhase( null, null ).execute( ResolvedAssembly.create( assembly), null, null );
    }

    public void testExecute_ShouldAddOneModuleSetWithOneModuleInIt()
        throws ArchiveCreationException, AssemblyFormattingException, IOException,
        InvalidAssemblerConfigurationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MavenProject project = createProject( "group", "artifact", "version", null );

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm, project );

        final MavenProject module = createProject( "group", "module", "version", project );

        final ArtifactMock moduleArtifactMock = new ArtifactMock( mm, "group", "module", "version", "jar", false );
        final File moduleArtifactFile = moduleArtifactMock.setNewFile();
        module.setArtifact( moduleArtifactMock.getArtifact() );

        final List<MavenProject> projects = new ArrayList<MavenProject>();

        projects.add( module );

        macTask.expectGetReactorProjects( projects );
        macTask.expectGetFinalName( "final-name" );
        macTask.expectGetDestFile( new File( "junk" ) );

        final int mode = TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) );

        macTask.expectAddFile( moduleArtifactFile, "out/artifact", mode );

        final Assembly assembly = new Assembly();
        assembly.setIncludeBaseDirectory( false );

        final ModuleSet ms = new ModuleSet();

        final ModuleBinaries bin = new ModuleBinaries();

        bin.setOutputFileNameMapping( "artifact" );
        bin.setOutputDirectory( "out" );
        bin.setFileMode( "777" );
        bin.setUnpack( false );
        bin.setIncludeDependencies( false );

        ms.setBinaries( bin );

        assembly.addModuleSet( ms );

        final Logger logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );

        mm.replayAll();

        final ResolvedAssembly ra = ResolvedAssembly.create( assembly ).withDependencySetArtifacts(
            new HashSet<Artifact>(  ) ).withResolvedModuleSets( Collections.singleton( createResolvedModuleSet( ms ) ) );

        final ModuleSetAssemblyPhase phase = createPhase( logger, null );
        phase.execute( ra, macTask.archiver, macTask.configSource );

        mm.verifyAll();
    }

    public void testAddModuleBinaries_ShouldReturnImmediatelyWhenBinariesIsNull()
        throws ArchiveCreationException, AssemblyFormattingException, InvalidAssemblerConfigurationException
    {
        createPhase( null, null ).addModuleBinaries( null, null, null, null, null );
    }

    public void testAddModuleBinaries_ShouldFilterPomModule()
        throws ArchiveCreationException, AssemblyFormattingException, IOException,
        InvalidAssemblerConfigurationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm );

        final ModuleBinaries binaries = new ModuleBinaries();

        binaries.setUnpack( false );
        binaries.setFileMode( "777" );
        binaries.setOutputDirectory( "out" );
        binaries.setOutputFileNameMapping( "artifact" );

        final MavenProject project = createProject( "group", "artifact", "version", null );
        project.setPackaging( "pom" );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "pom", false );
        project.setArtifact( artifactMock.getArtifact() );

        final Set<MavenProject> projects = singleton( project );

        mm.replayAll();

        createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null ).addModuleBinaries( null, binaries,
                                                                                                projects,
                                                                                                macTask.archiver,
                                                                                                macTask.configSource );

        mm.verifyAll();
    }

    public void testAddModuleBinaries_ShouldAddOneModuleAttachmentArtifactAndNoDeps()
        throws ArchiveCreationException, AssemblyFormattingException, IOException,
        InvalidAssemblerConfigurationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm, null );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", "test", false );
        final File artifactFile = artifactMock.setNewFile();

        macTask.expectGetFinalName( "final-name" );
        macTask.expectGetDestFile( new File( "junk" ) );
        macTask.expectAddFile( artifactFile, "out/artifact",
                               TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) ) );

        final ModuleBinaries binaries = new ModuleBinaries();

        binaries.setIncludeDependencies( false );
        binaries.setUnpack( false );
        binaries.setFileMode( "777" );
        binaries.setOutputDirectory( "out" );
        binaries.setOutputFileNameMapping( "artifact" );
        binaries.setAttachmentClassifier( "test" );

        final MavenProject project = createProject( "group", "artifact", "version", null );
        project.addAttachedArtifact( artifactMock.getArtifact() );

        final Set<MavenProject> projects = singleton( project );

        mm.replayAll();

        final Logger logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );

        ResolvedModuleSet rms = ResolvedModuleSet.empty().withArtifacts( Collections.<Artifact>emptySet() );

        createPhase( logger, null ).addModuleBinaries( rms, binaries, projects, macTask.archiver, macTask.configSource );

        mm.verifyAll();
    }

    public void testAddModuleBinaries_ShouldFailWhenOneModuleDoesntHaveAttachmentWithMatchingClassifier()
        throws ArchiveCreationException, AssemblyFormattingException, IOException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", "test", false );
        artifactMock.setNewFile();

        final ModuleBinaries binaries = new ModuleBinaries();

        binaries.setUnpack( false );
        binaries.setFileMode( "777" );
        binaries.setOutputDirectory( "out" );
        binaries.setOutputFileNameMapping( "artifact" );
        binaries.setAttachmentClassifier( "test" );

        final MavenProject project = createProject( "group", "artifact", "version", null );
        project.setArtifact( artifactMock.getArtifact() );

        final Set<MavenProject> projects = singleton( project );

        mm.replayAll();

        final Logger logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );

        try
        {
            createPhase( logger, null ).addModuleBinaries( null, binaries, projects, macTask.archiver, macTask.configSource );

            fail( "Should throw an invalid configuration exception because of module with missing attachment." );
        }
        catch ( final InvalidAssemblerConfigurationException e )
        {
            // should throw this because of missing attachment.
        }

        mm.verifyAll();
    }

    public void testAddModuleBinaries_ShouldAddOneModuleArtifactAndNoDeps()
        throws ArchiveCreationException, AssemblyFormattingException, IOException,
        InvalidAssemblerConfigurationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", false );
        final File artifactFile = artifactMock.setNewFile();

        macTask.expectGetFinalName( "final-name" );
        macTask.expectGetDestFile( new File( "junk" ) );
        macTask.expectAddFile( artifactFile, "out/artifact",
                               TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) ) );

        final ModuleBinaries binaries = new ModuleBinaries();

        binaries.setIncludeDependencies( false );
        binaries.setUnpack( false );
        binaries.setFileMode( "777" );
        binaries.setOutputDirectory( "out" );
        binaries.setOutputFileNameMapping( "artifact" );

        final MavenProject project = createProject( "group", "artifact", "version", null );
        project.setArtifact( artifactMock.getArtifact() );

        final Set<MavenProject> projects = singleton( project );

        mm.replayAll();

        final Logger logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );

        ResolvedModuleSet ms = ResolvedModuleSet.empty().withArtifacts( Collections.<Artifact>emptySet() );

        createPhase( logger, null ).addModuleBinaries( ms, binaries, projects, macTask.archiver, macTask.configSource );

        mm.verifyAll();
    }

    public void testAddModuleBinaries_ShouldAddOneModuleArtifactAndWithOneDepArtifact()
        throws ArchiveCreationException, AssemblyFormattingException, IOException,
        InvalidAssemblerConfigurationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddDependencySetsTask macTask = new MockAndControlForAddDependencySetsTask( mm );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", false );
        final File artifactFile = artifactMock.setNewFile();

        macTask.expectCSGetFinalName( "final-name" );
        macTask.expectGetDestFile( new File( "junk" ) );
        macTask.expectAddFile( artifactFile, "out/artifact",
                               TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) ) );
        macTask.expectGetSession( null );

        final ModuleBinaries binaries = new ModuleBinaries();

        binaries.setUnpack( false );
        binaries.setFileMode( "777" );
        binaries.setOutputDirectory( "out" );
        binaries.setOutputFileNameMapping( "artifact" );

        final DependencySet ds = new DependencySet();
        ds.setUseProjectArtifact( false );
        ds.setOutputDirectory( binaries.getOutputDirectory() );
        ds.setOutputFileNameMapping( "${artifact.artifactId}" );
        ds.setFileMode( "777" );

        binaries.addDependencySet( ds );

        final MavenProject project = createProject( "group", "artifact", "version", null );
        project.setArtifact( artifactMock.getArtifact() );

        final ArtifactMock depArtifactMock = new ArtifactMock( mm, "group", "dep", "1", "jar", false );
        final File depArtifactFile = depArtifactMock.setNewFile();

        macTask.expectAddFile( depArtifactFile, "out/dep",
                               TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) ) );

        final MavenProject depProject = createProject( "group", "dep", "version", null );
        depProject.setArtifact( depArtifactMock.getArtifact() );

        macTask.expectBuildFromRepository( depProject );

        macTask.expectCSGetRepositories( null, null );

        final Set<MavenProject> projects = singleton( project );

        mm.replayAll();

        final Logger overrideLogger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );

        final ModuleSetAssemblyPhase phase = createPhase( overrideLogger, macTask );

        final ResolvedModuleSet rms = ResolvedModuleSet.empty( ).withArtifacts(
            Collections.singleton( depArtifactMock.getArtifact() ) );


        phase.addModuleBinaries( rms, binaries, projects, macTask.archiver, macTask.configSource );

        mm.verifyAll();
    }

    public void testAddModuleBinaries_ShouldAddOneModuleArtifactAndWithOneDepArtifactUsingImpliedDepSet()
        throws ArchiveCreationException, AssemblyFormattingException, IOException,
        InvalidAssemblerConfigurationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddDependencySetsTask macTask = new MockAndControlForAddDependencySetsTask( mm );

        final ArtifactMock moduleArtifactMock = new ArtifactMock( mm, "group", "artifact", "0", "jar", false );
        final File moduleArtifactFile = moduleArtifactMock.setNewFile();

        macTask.expectCSGetFinalName( "final-name" );
        macTask.expectGetDestFile( new File( "junk" ) );

        final int mode = TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) );

        macTask.expectAddFile( moduleArtifactFile, "out/artifact", mode );
        macTask.expectGetSession( null );

        final ModuleBinaries binaries = new ModuleBinaries();

        binaries.setUnpack( false );
        binaries.setFileMode( "777" );
        binaries.setOutputDirectory( "out" );
        binaries.setOutputFileNameMapping( "${artifact.artifactId}" );
        binaries.setIncludeDependencies( true );

        final MavenProject project = createProject( "group", "artifact", "version", null );
        project.setArtifact( moduleArtifactMock.getArtifact() );

        final ArtifactMock depArtifactMock = new ArtifactMock( mm, "group", "dep", "1", "jar", false );
        final File depArtifactFile = depArtifactMock.setNewFile();

        macTask.expectAddFile( depArtifactFile, "out/dep", mode );

        final MavenProject depProject = createProject( "group", "dep", "version", null );
        depProject.setArtifact( depArtifactMock.getArtifact() );

        macTask.expectBuildFromRepository( depProject );

        macTask.expectCSGetRepositories( null, null );

        final Set<MavenProject> projects = singleton( project );

        mm.replayAll();

        final Logger overrideLogger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );

        final ModuleSetAssemblyPhase phase = createPhase( overrideLogger, macTask );

        ResolvedModuleSet ms = ResolvedModuleSet.empty().withArtifacts( singleton( depArtifactMock.getArtifact() ) );

        phase.addModuleBinaries( ms, binaries, projects, macTask.archiver, macTask.configSource );

        mm.verifyAll();
    }

    // public void testCollectExcludesFromQueuedArtifacts_ShouldAddOneExclusion()
    // {
    // MockManager mm = new MockManager();
    //
    // List excludes = new ArrayList();
    //
    // // nothing up this sleeve...
    // assertTrue( excludes.isEmpty() );
    //
    // mm.replayAll();
    //
    // Set artifactIds = Collections.singleton( "group:artifact:jar" );
    //
    // List result = createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null )
    // .collectExcludesFromQueuedArtifacts( artifactIds, excludes );
    //
    // assertEquals( 1, result.size() );
    //
    // assertEquals( "group:artifact:jar", result.get( 0 ) );
    //
    // mm.verifyAll();
    // }
    //
    // public void testCollectExcludesFromQueuedArtifacts_ShouldHandleNullExcludesList()
    // {
    // MockManager mm = new MockManager();
    //
    // mm.replayAll();
    //
    // Set artifactIds = Collections.singleton( "group:artifact:jar" );
    //
    // List result = createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null )
    // .collectExcludesFromQueuedArtifacts( artifactIds, null );
    //
    // assertEquals( 1, result.size() );
    //
    // assertEquals( "group:artifact:jar", result.get( 0 ) );
    //
    // mm.verifyAll();
    // }

    public void testAddModuleArtifact_ShouldThrowExceptionWhenArtifactFileIsNull()
        throws AssemblyFormattingException, IOException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "type", false );
        artifactMock.setNullFile();

        mm.replayAll();

        try
        {
            createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null ).addModuleArtifact( artifactMock.getArtifact(),
                                                                                                    null, null, null,
                                                                                                    null );

            fail( "Expected ArchiveCreationException since artifact file is null." );
        }
        catch ( final ArchiveCreationException e )
        {
            // expected
        }

        mm.verifyAll();
    }

    public void testAddModuleArtifact_ShouldAddOneArtifact()
        throws AssemblyFormattingException, IOException, ArchiveCreationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddArtifactTask macTask = new MockAndControlForAddArtifactTask( mm );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "type", false );
        final File artifactFile = artifactMock.setNewFile();

        final MavenProject project = createProject( "group", "artifact", "version", null );
        project.setArtifact( artifactMock.getArtifact() );

        macTask.expectGetFinalName( "final-name" );
        macTask.expectGetDestFile( new File( "junk" ) );

        macTask.expectAddFile( artifactFile, "out/artifact",
                               TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) ) );

        final ModuleBinaries binaries = new ModuleBinaries();
        binaries.setOutputDirectory( "out" );
        binaries.setOutputFileNameMapping( "artifact" );
        binaries.setUnpack( false );
        binaries.setFileMode( "777" );

        mm.replayAll();

        createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null ).addModuleArtifact( artifactMock.getArtifact(),
                                                                                                project,
                                                                                                macTask.archiver,
                                                                                                macTask.configSource,
                                                                                                binaries );

        mm.verifyAll();
    }

    public void testAddModuleSourceFileSets_ShouldReturnImmediatelyIfSourcesIsNull()
        throws ArchiveCreationException, AssemblyFormattingException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        mm.replayAll();

        createPhase( new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ), null ).addModuleSourceFileSets( null, null, null,
                                                                                                      null );

        mm.verifyAll();
    }

    public void testAddModuleSourceFileSets_ShouldAddOneSourceDirectory()
        throws ArchiveCreationException, AssemblyFormattingException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MockAndControlForAddFileSetsTask macTask = new MockAndControlForAddFileSetsTask( mm, fileManager );

        final MavenProject project = createProject( "group", "artifact", "version", null );

        macTask.expectGetProject( project );

        final ArtifactMock artifactMock = new ArtifactMock( mm, "group", "artifact", "version", "jar", false );

        project.setArtifact( artifactMock.getArtifact() );

        final Set<MavenProject> projects = singleton( project );

        final ModuleSources sources = new ModuleSources();

        final FileSet fs = new FileSet();
        fs.setDirectory( "/src" );
        fs.setDirectoryMode( "777" );
        fs.setFileMode( "777" );

        sources.addFileSet( fs );

        macTask.expectGetArchiveBaseDirectory();

        final int mode = TypeConversionUtils.modeToInt( "777", new ConsoleLogger( Logger.LEVEL_DEBUG, "test" ) );
        final int[] modes = { -1, -1, mode, mode };

        macTask.expectAdditionOfSingleFileSet( project, "final-name", false, modes, 1, true,
                                               false );

        mm.replayAll();

        final Logger logger = new ConsoleLogger( Logger.LEVEL_DEBUG, "test" );

        createPhase( logger, null ).addModuleSourceFileSets( sources, projects, macTask.archiver, macTask.configSource );

        mm.verifyAll();
    }

    public void testGetModuleProjects_ShouldReturnNothingWhenReactorContainsOnlyCurrentProject()
        throws ArchiveCreationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MavenProject project = createProject( "group", "artifact", "version", null );

        final MockAndControlForAddDependencySetsTask macTask = new MockAndControlForAddDependencySetsTask( mm, project );

        final List<MavenProject> projects = Collections.singletonList( project );

        macTask.expectGetReactorProjects( projects );

        final ModuleSet moduleSet = new ModuleSet();
        moduleSet.setIncludeSubModules( true );

        mm.replayAll();

        final Set<MavenProject> moduleProjects =
            ModuleSetAssemblyPhase.getModuleProjects( moduleSet, macTask.configSource, logger );

        assertTrue( moduleProjects.isEmpty() );

        mm.verifyAll();
    }

    public void testGetModuleProjects_ShouldReturnNothingWhenReactorContainsTwoSiblingProjects()
        throws ArchiveCreationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MavenProject project = createProject( "group", "artifact", "version", null );

        final MockAndControlForAddDependencySetsTask macTask = new MockAndControlForAddDependencySetsTask( mm, project );

        final MavenProject project2 = createProject( "group", "artifact2", "version", null );

        final List<MavenProject> projects = new ArrayList<MavenProject>();
        projects.add( project );
        projects.add( project2 );

        macTask.expectGetReactorProjects( projects );

        final ModuleSet moduleSet = new ModuleSet();
        moduleSet.setIncludeSubModules( true );

        mm.replayAll();

        final Set<MavenProject> moduleProjects =
            ModuleSetAssemblyPhase.getModuleProjects( moduleSet, macTask.configSource, logger );

        assertTrue( moduleProjects.isEmpty() );

        mm.verifyAll();
    }

    public void testGetModuleProjects_ShouldReturnModuleOfCurrentProject()
        throws ArchiveCreationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MavenProject project = createProject( "group", "artifact", "version", null );

        final MockAndControlForAddDependencySetsTask macTask = new MockAndControlForAddDependencySetsTask( mm, project );

        final MavenProject project2 = createProject( "group", "artifact2", "version", project );

        final List<MavenProject> projects = new ArrayList<MavenProject>();
        projects.add( project );
        projects.add( project2 );

        macTask.expectGetReactorProjects( projects );

        final ModuleSet moduleSet = new ModuleSet();
        moduleSet.setIncludeSubModules( true );

        mm.replayAll();

        final Set<MavenProject> moduleProjects =
            ModuleSetAssemblyPhase.getModuleProjects( moduleSet, macTask.configSource, logger );

        assertFalse( moduleProjects.isEmpty() );

        final MavenProject result = moduleProjects.iterator()
                                                  .next();

        assertEquals( "artifact2", result.getArtifactId() );

        mm.verifyAll();
    }

    public void testGetModuleProjects_ShouldReturnDescendentModulesOfCurrentProject()
        throws ArchiveCreationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MavenProject project = createProject( "group", "artifact", "version", null );

        final MockAndControlForAddDependencySetsTask macTask = new MockAndControlForAddDependencySetsTask( mm, project );

        final MavenProject project2 = createProject( "group", "artifact2", "version", project );
        final MavenProject project3 = createProject( "group", "artifact3", "version", project2 );

        final List<MavenProject> projects = new ArrayList<MavenProject>();
        projects.add( project );
        projects.add( project2 );
        projects.add( project3 );

        macTask.expectGetReactorProjects( projects );

        final ModuleSet moduleSet = new ModuleSet();
        moduleSet.setIncludeSubModules( true );

        mm.replayAll();

        final Set<MavenProject> moduleProjects =
            ModuleSetAssemblyPhase.getModuleProjects( moduleSet, macTask.configSource, logger );

        assertEquals( 2, moduleProjects.size() );

        final List<MavenProject> check = new ArrayList<MavenProject>();
        check.add( project2 );
        check.add( project3 );

        verifyResultIs( check, moduleProjects );

        mm.verifyAll();
    }

    public void testGetModuleProjects_ShouldExcludeModuleAndDescendentsTransitively()
        throws ArchiveCreationException
    {
        final EasyMockSupport mm = new EasyMockSupport();

        final MavenProject project = createProject( "group", "artifact", "version", null );

        final MockAndControlForAddDependencySetsTask macTask = new MockAndControlForAddDependencySetsTask( mm, project );

        final List<ArtifactMock> macArtifacts = new ArrayList<ArtifactMock>();

        macArtifacts.add( addArtifact( project, mm, false ) );

        final MavenProject project2 = createProject( "group", "artifact2", "version", project );
        macArtifacts.add( addArtifact( project2, mm, false ) );
        final MavenProject project3 = createProject( "group", "artifact3", "version", project2 );
        macArtifacts.add( addArtifact( project3, mm, true ) );

        final List<MavenProject> projects = new ArrayList<MavenProject>();
        projects.add( project );
        projects.add( project2 );
        projects.add( project3 );

        macTask.expectGetReactorProjects( projects );

        final ModuleSet moduleSet = new ModuleSet();
        moduleSet.setIncludeSubModules( true );

        moduleSet.addExclude( "group:artifact2" );

        mm.replayAll();

        final Set<MavenProject> moduleProjects =
            ModuleSetAssemblyPhase.getModuleProjects( moduleSet, macTask.configSource, logger );

        assertTrue( moduleProjects.isEmpty() );

        mm.verifyAll();
    }

    private ArtifactMock addArtifact( final MavenProject project, final EasyMockSupport mm, final boolean expectDepTrailCheck )
    {
        final ArtifactMock macArtifact =
            new ArtifactMock( mm, project.getGroupId(), project.getArtifactId(), project.getVersion(),
                              project.getPackaging(), false );

        if ( expectDepTrailCheck )
        {
            final LinkedList<String> depTrail = new LinkedList<String>();

            MavenProject parent = project.getParent();
            while ( parent != null )
            {
                depTrail.addLast( parent.getId() );

                parent = parent.getParent();
            }

            macArtifact.setDependencyTrail( depTrail );
        }

        project.setArtifact( macArtifact.getArtifact() );

        return macArtifact;
    }

    private void verifyResultIs( final List<MavenProject> check, final Set<MavenProject> moduleProjects )
    {
        boolean failed = false;

        final Set<MavenProject> checkTooMany = new HashSet<MavenProject>( moduleProjects );
        checkTooMany.removeAll( check );

        if ( !checkTooMany.isEmpty() )
        {
            failed = true;

            System.out.println( "Unexpected projects in output: " );

            for (final MavenProject project : checkTooMany) {
                System.out.println(project.getId());
            }
        }

        final Set<MavenProject> checkTooFew = new HashSet<MavenProject>( check );
        checkTooFew.removeAll( moduleProjects );

        if ( !checkTooFew.isEmpty() )
        {
            failed = true;

            System.out.println( "Expected projects missing from output: " );

            for (final MavenProject project : checkTooMany) {
                System.out.println(project.getId());
            }
        }

        if ( failed )
        {
            Assert.fail( "See system output for more information." );
        }
    }

    private MavenProject createProject( final String groupId, final String artifactId, final String version,
                                        final MavenProject parentProject )
    {
        final Model model = new Model();
        model.setArtifactId( artifactId );
        model.setGroupId( groupId );
        model.setVersion( version );

        final MavenProject project = new MavenProject( model );

        File pomFile;
        if ( parentProject == null )
        {
            final File basedir = fileManager.createTempDir();
            pomFile = new File( basedir, "pom.xml" );
        }
        else
        {
            final File parentBase = parentProject.getBasedir();
            pomFile = new File( parentBase, artifactId + "/pom.xml" );

            parentProject.getModel()
                         .addModule( artifactId );
            project.setParent( parentProject );
        }

        project.setFile( pomFile );

        return project;
    }

    private ModuleSetAssemblyPhase createPhase( final Logger logger,
                                                final MockAndControlForAddDependencySetsTask macTask )
    {
        MavenProjectBuilder projectBuilder = null;

        if ( macTask != null )
        {
            projectBuilder = macTask.projectBuilder;
        }

        return new ModuleSetAssemblyPhase( projectBuilder, logger );
    }

}
