package org.apache.maven.model.validation;

/*
 * 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.InputStream;
import java.util.List;

import org.apache.maven.model.Model;
import org.apache.maven.model.building.DefaultModelBuildingRequest;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.SimpleProblemCollector;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.PlexusTestCase;

/**
 * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
 */
public class DefaultModelValidatorTest
    extends PlexusTestCase
{

    private ModelValidator validator;

    private Model read( String pom )
        throws Exception
    {
        String resource = "/poms/validation/" + pom;
        InputStream is = getClass().getResourceAsStream( resource );
        assertNotNull( "missing resource: " + resource, is );
        return new MavenXpp3Reader().read( is );
    }

    private SimpleProblemCollector validate( String pom )
        throws Exception
    {
        return validateEffective( pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT );
    }

    private SimpleProblemCollector validateRaw( String pom )
        throws Exception
    {
        return validateRaw( pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT );
    }

    private SimpleProblemCollector validateEffective( String pom, int level )
        throws Exception
    {
        ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level );

        SimpleProblemCollector problems = new SimpleProblemCollector( read( pom ) );

        validator.validateEffectiveModel( problems.getModel(), request, problems );

        return problems;
    }

    private SimpleProblemCollector validateRaw( String pom, int level )
        throws Exception
    {
        ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level );

        SimpleProblemCollector problems = new SimpleProblemCollector( read( pom ) );

        validator.validateRawModel( problems.getModel(), request, problems );

        return problems;
    }

    private void assertContains( String msg, String substring )
    {
        assertTrue( "\"" + substring + "\" was not found in: " + msg, msg.contains( substring ) );
    }

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

        validator = lookup( ModelValidator.class );
    }

    @Override
    protected void tearDown()
        throws Exception
    {
        this.validator = null;

        super.tearDown();
    }

    private void assertViolations( SimpleProblemCollector result, int fatals, int errors, int warnings )
    {
        assertEquals( String.valueOf( result.getFatals() ), fatals, result.getFatals().size() );
        assertEquals( String.valueOf( result.getErrors() ), errors, result.getErrors().size() );
        assertEquals( String.valueOf( result.getWarnings() ), warnings, result.getWarnings().size() );
    }

    public void testMissingModelVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-modelVersion-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertEquals( "'modelVersion' is missing.", result.getErrors().get( 0 ) );
    }

    public void testBadModelVersion()
        throws Exception
    {
        SimpleProblemCollector result =
            validateRaw( "bad-modelVersion.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "modelVersion" ) );
    }

    public void testMissingArtifactId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-artifactId-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertEquals( "'artifactId' is missing.", result.getErrors().get( 0 ) );
    }

    public void testMissingGroupId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-groupId-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertEquals( "'groupId' is missing.", result.getErrors().get( 0 ) );
    }

    public void testInvalidIds()
        throws Exception
    {
        SimpleProblemCollector result = validate( "invalid-ids-pom.xml" );

        assertViolations( result, 0, 2, 0 );

        assertEquals( "'groupId' with value 'o/a/m' does not match a valid id pattern.", result.getErrors().get( 0 ) );

        assertEquals( "'artifactId' with value 'm$-do$' does not match a valid id pattern.", result.getErrors().get( 1 ) );
    }

    public void testMissingType()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-type-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertEquals( "'packaging' is missing.", result.getErrors().get( 0 ) );
    }

    public void testMissingVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-version-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertEquals( "'version' is missing.", result.getErrors().get( 0 ) );
    }

    public void testInvalidAggregatorPackaging()
        throws Exception
    {
        SimpleProblemCollector result = validate( "invalid-aggregator-packaging-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "Aggregator projects require 'pom' as packaging." ) );
    }

    public void testMissingDependencyArtifactId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-dependency-artifactId-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains(
            "'dependencies.dependency.artifactId' for groupId:null:jar is missing" ) );
    }

    public void testMissingDependencyGroupId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-dependency-groupId-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains(
            "'dependencies.dependency.groupId' for null:artifactId:jar is missing" ) );
    }

    public void testMissingDependencyVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-dependency-version-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains(
            "'dependencies.dependency.version' for groupId:artifactId:jar is missing" ) );
    }

    public void testMissingDependencyManagementArtifactId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-dependency-mgmt-artifactId-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains(
            "'dependencyManagement.dependencies.dependency.artifactId' for groupId:null:jar is missing" ) );
    }

    public void testMissingDependencyManagementGroupId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-dependency-mgmt-groupId-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains(
            "'dependencyManagement.dependencies.dependency.groupId' for null:artifactId:jar is missing" ) );
    }

    public void testMissingAll()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-1-pom.xml" );

        assertViolations( result, 0, 4, 0 );

        List<String> messages = result.getErrors();

        assertTrue( messages.contains( "\'modelVersion\' is missing." ) );
        assertTrue( messages.contains( "\'groupId\' is missing." ) );
        assertTrue( messages.contains( "\'artifactId\' is missing." ) );
        assertTrue( messages.contains( "\'version\' is missing." ) );
        // type is inherited from the super pom
    }

    public void testMissingPluginArtifactId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-plugin-artifactId-pom.xml" );

        assertViolations( result, 0, 1, 0 );

        assertEquals( "'build.plugins.plugin.artifactId' is missing.", result.getErrors().get( 0 ) );
    }

    public void testEmptyPluginVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "empty-plugin-version.xml" );

        assertViolations( result, 0, 1, 0 );

        assertEquals( "'build.plugins.plugin.version' for org.apache.maven.plugins:maven-it-plugin"
            + " must be a valid version but is ''.", result.getErrors().get( 0 ) );
    }

    public void testMissingRepositoryId()
        throws Exception
    {
        SimpleProblemCollector result =
            validateRaw( "missing-repository-id-pom.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT );

        assertViolations( result, 0, 4, 0 );

        assertEquals( "'repositories.repository.id' is missing.", result.getErrors().get( 0 ) );

        assertEquals( "'repositories.repository[null].url' is missing.", result.getErrors().get( 1 ) );

        assertEquals( "'pluginRepositories.pluginRepository.id' is missing.", result.getErrors().get( 2 ) );

        assertEquals( "'pluginRepositories.pluginRepository[null].url' is missing.", result.getErrors().get( 3 ) );
    }

    public void testMissingResourceDirectory()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-resource-directory-pom.xml" );

        assertViolations( result, 0, 2, 0 );

        assertEquals( "'build.resources.resource.directory' is missing.", result.getErrors().get( 0 ) );

        assertEquals( "'build.testResources.testResource.directory' is missing.", result.getErrors().get( 1 ) );
    }

    public void testBadPluginDependencyScope()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-plugin-dependency-scope.xml" );

        assertViolations( result, 0, 3, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "test:d" ) );

        assertTrue( result.getErrors().get( 1 ).contains( "test:e" ) );

        assertTrue( result.getErrors().get( 2 ).contains( "test:f" ) );
    }

    public void testBadDependencyScope()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-dependency-scope.xml" );

        assertViolations( result, 0, 0, 2 );

        assertTrue( result.getWarnings().get( 0 ).contains( "test:f" ) );

        assertTrue( result.getWarnings().get( 1 ).contains( "test:g" ) );
    }

    public void testBadDependencyVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-dependency-version.xml" );

        assertViolations( result, 0, 2, 0 );

        assertContains( result.getErrors().get( 0 ),
                        "'dependencies.dependency.version' for test:b:jar must be a valid version" );
        assertContains( result.getErrors().get( 1 ),
                        "'dependencies.dependency.version' for test:c:jar must not contain any of these characters" );
    }

    public void testDuplicateModule()
        throws Exception
    {
        SimpleProblemCollector result = validate( "duplicate-module.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "child" ) );
    }

    public void testDuplicateProfileId()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "duplicate-profile-id.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "non-unique-id" ) );
    }

    public void testBadPluginVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-plugin-version.xml" );

        assertViolations( result, 0, 4, 0 );

        assertContains( result.getErrors().get( 0 ),
                        "'build.plugins.plugin.version' for test:mip must be a valid version" );
        assertContains( result.getErrors().get( 1 ),
                        "'build.plugins.plugin.version' for test:rmv must be a valid version" );
        assertContains( result.getErrors().get( 2 ),
                        "'build.plugins.plugin.version' for test:lmv must be a valid version" );
        assertContains( result.getErrors().get( 3 ),
                        "'build.plugins.plugin.version' for test:ifsc must not contain any of these characters" );
    }

    public void testDistributionManagementStatus()
        throws Exception
    {
        SimpleProblemCollector result = validate( "distribution-management-status.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "distributionManagement.status" ) );
    }

    public void testIncompleteParent()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "incomplete-parent.xml" );

        assertViolations( result, 3, 0, 0 );

        assertTrue( result.getFatals().get( 0 ).contains( "parent.groupId" ) );
        assertTrue( result.getFatals().get( 1 ).contains( "parent.artifactId" ) );
        assertTrue( result.getFatals().get( 2 ).contains( "parent.version" ) );
    }

    public void testHardCodedSystemPath()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "hard-coded-system-path.xml" );

        assertViolations( result, 0, 0, 1 );

        assertTrue( result.getWarnings().get( 0 ).contains( "test:a:jar" ) );
    }

    public void testEmptyModule()
        throws Exception
    {
        SimpleProblemCollector result = validate( "empty-module.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "'modules.module[0]' has been specified without a path" ) );
    }

    public void testDuplicatePlugin()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "duplicate-plugin.xml" );

        assertViolations( result, 0, 4, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "duplicate declaration of plugin test:duplicate" ) );
        assertTrue( result.getErrors().get( 1 ).contains( "duplicate declaration of plugin test:managed-duplicate" ) );
        assertTrue( result.getErrors().get( 2 ).contains( "duplicate declaration of plugin profile:duplicate" ) );
        assertTrue( result.getErrors().get( 3 ).contains( "duplicate declaration of plugin profile:managed-duplicate" ) );
    }

    public void testDuplicatePluginExecution()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "duplicate-plugin-execution.xml" );

        assertViolations( result, 0, 4, 0 );

        assertContains( result.getErrors().get( 0 ), "duplicate execution with id a" );
        assertContains( result.getErrors().get( 1 ), "duplicate execution with id default" );
        assertContains( result.getErrors().get( 2 ), "duplicate execution with id c" );
        assertContains( result.getErrors().get( 3 ), "duplicate execution with id b" );
    }

    public void testReservedRepositoryId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "reserved-repository-id.xml" );

        assertViolations( result, 0, 4, 0 );

        assertContains( result.getErrors().get( 0 ), "'repositories.repository.id'" + " must not be 'local'" );
        assertContains( result.getErrors().get( 1 ), "'pluginRepositories.pluginRepository.id' must not be 'local'" );
        assertContains( result.getErrors().get( 2 ), "'distributionManagement.repository.id' must not be 'local'" );
        assertContains( result.getErrors().get( 3 ),
                        "'distributionManagement.snapshotRepository.id' must not be 'local'" );
    }

    public void testMissingPluginDependencyGroupId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-plugin-dependency-groupId.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( ":a:" ) );
    }

    public void testMissingPluginDependencyArtifactId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-plugin-dependency-artifactId.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "test:" ) );
    }

    public void testMissingPluginDependencyVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-plugin-dependency-version.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "test:a" ) );
    }

    public void testBadPluginDependencyVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-plugin-dependency-version.xml" );

        assertViolations( result, 0, 1, 0 );

        assertTrue( result.getErrors().get( 0 ).contains( "test:b" ) );
    }

    public void testBadVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-version.xml" );

        assertViolations( result, 0, 1, 0 );

        assertContains( result.getErrors().get( 0 ), "'version' must not contain any of these characters" );
    }

    public void testBadSnapshotVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-snapshot-version.xml" );

        assertViolations( result, 0, 1, 0 );

        assertContains( result.getErrors().get( 0 ), "'version' uses an unsupported snapshot version format" );
    }

    public void testBadRepositoryId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "bad-repository-id.xml" );

        assertViolations( result, 0, 4, 0 );

        assertContains( result.getErrors().get( 0 ),
                        "'repositories.repository.id' must not contain any of these characters" );
        assertContains( result.getErrors().get( 1 ),
                        "'pluginRepositories.pluginRepository.id' must not contain any of these characters" );
        assertContains( result.getErrors().get( 2 ),
                        "'distributionManagement.repository.id' must not contain any of these characters" );
        assertContains( result.getErrors().get( 3 ),
                        "'distributionManagement.snapshotRepository.id' must not contain any of these characters" );
    }

    public void testBadDependencyExclusionId()
        throws Exception
    {
        SimpleProblemCollector result = validateEffective( "bad-dependency-exclusion-id.xml", ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 );

        assertViolations( result, 0, 0, 2 );

        assertContains( result.getWarnings().get( 0 ),
                        "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar" );
        assertContains( result.getWarnings().get( 1 ),
                        "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar" );

        // MNG-3832: Aether (part of M3+) supports wildcard expressions for exclusions

        SimpleProblemCollector result_30 = validate( "bad-dependency-exclusion-id.xml" );

        assertViolations( result_30, 0, 0, 0 );

    }

    public void testMissingDependencyExclusionId()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-dependency-exclusion-id.xml" );

        assertViolations( result, 0, 0, 2 );

        assertContains( result.getWarnings().get( 0 ),
                        "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar is missing" );
        assertContains( result.getWarnings().get( 1 ),
                        "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar is missing" );
    }

    public void testBadImportScopeType()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "bad-import-scope-type.xml" );

        assertViolations( result, 0, 0, 1 );

        assertContains( result.getWarnings().get( 0 ),
                        "'dependencyManagement.dependencies.dependency.type' for test:a:jar must be 'pom'" );
    }

    public void testBadImportScopeClassifier()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "bad-import-scope-classifier.xml" );

        assertViolations( result, 0, 1, 0 );

        assertContains( result.getErrors().get( 0 ),
                        "'dependencyManagement.dependencies.dependency.classifier' for test:a:pom:cls must be empty" );
    }

    public void testSystemPathRefersToProjectBasedir()
        throws Exception
    {
        SimpleProblemCollector result = validateRaw( "basedir-system-path.xml" );

        assertViolations( result, 0, 0, 2 );

        assertContains( result.getWarnings().get( 0 ), "'dependencies.dependency.systemPath' for test:a:jar "
            + "should not point at files within the project directory" );
        assertContains( result.getWarnings().get( 1 ), "'dependencies.dependency.systemPath' for test:b:jar "
            + "should not point at files within the project directory" );
    }

    public void testMissingReportPluginVersion()
        throws Exception
    {
        SimpleProblemCollector result = validate( "missing-report-version-pom.xml" );

        assertViolations( result, 0, 0, 0 );
    }
}
