/*
 * 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.
 */
package org.apache.maven.plugins.javadoc;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
import org.apache.maven.plugins.javadoc.ProxyServer.AuthAsyncProxyServlet;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectBuildingRequest.RepositoryMerging;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Settings;
import org.apache.maven.shared.utils.io.FileUtils;
import org.codehaus.plexus.languages.java.version.JavaVersion;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
import org.eclipse.aether.repository.LocalRepository;
import org.hamcrest.MatcherAssert;
import org.junit.AssumptionViolatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.commons.io.FileUtils.copyDirectory;
import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assume.assumeThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

/**
 * Test {@link org.apache.maven.plugins.javadoc.JavadocReport} class.
 *
 * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 */
public class JavadocReportTest extends AbstractMojoTestCase {

    private static final char LINE_SEPARATOR = ' ';

    public static final String OPTIONS_UMLAUT_ENCODING = "Options Umlaut Encoding ö ä ü ß";

    private Path unit;

    private Path tempDirectory;

    private File localRepo;

    private static final Logger LOGGER = LoggerFactory.getLogger(JavadocReportTest.class);

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

        tempDirectory = Files.createTempDirectory("JavadocReportTest");
        localRepo = tempDirectory.resolve(Paths.get("target/local-repo/")).toFile();
        unit = new File(getBasedir(), "src/test/resources/unit").toPath();

        createTestRepo();
    }

    @Override
    protected void tearDown() throws Exception {
        try {
            deleteDirectory(tempDirectory.toFile());
        } catch (IOException ex) {
            // CI servers can have problems deleting files.
            // It will get cleared out eventually, and since
            // temporary directories have unique names,
            // it shouldn't affect subsequent tests.
        }

        super.tearDown();
    }

    private JavadocReport lookupMojo(Path testPom) throws Exception {
        JavadocReport mojo = (JavadocReport) lookupMojo("javadoc", testPom.toFile());

        Plugin p = new Plugin();
        p.setGroupId("org.apache.maven.plugins");
        p.setArtifactId("maven-javadoc-plugin");
        MojoExecution mojoExecution = new MojoExecution(p, "javadoc", null);

        setVariableValueToObject(mojo, "mojoExecution", mojoExecution);

        MavenProject currentProject = new MavenProjectStub();
        currentProject.setGroupId("GROUPID");
        currentProject.setArtifactId("ARTIFACTID");

        List<MavenProject> reactorProjects =
                mojo.getReactorProjects() != null ? mojo.getReactorProjects() : Collections.emptyList();
        MavenSession session = newMavenSession(currentProject);
        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", session.getRepositorySession());
        setVariableValueToObject(mojo, "reactorProjects", reactorProjects);
        return mojo;
    }

    /**
     * Create test repository in target directory.
     *
     * @throws IOException if any
     */
    private void createTestRepo() throws IOException {
        assertTrue(localRepo.mkdirs());

        // ----------------------------------------------------------------------
        // UMLGraph
        // ----------------------------------------------------------------------

        Path sourceDir = unit.resolve("doclet-test/artifact-doclet");
        assertThat(sourceDir).exists();
        copyDirectory(sourceDir.toFile(), localRepo);

        // ----------------------------------------------------------------------
        // UMLGraph-bis
        // ----------------------------------------------------------------------

        sourceDir = unit.resolve("doclet-path-test/artifact-doclet");
        assertThat(sourceDir).exists();
        copyDirectory(sourceDir.toFile(), localRepo);

        // ----------------------------------------------------------------------
        // commons-attributes-compiler
        // https://www.tullmann.org/pat/taglets/
        // ----------------------------------------------------------------------

        sourceDir = unit.resolve("taglet-test/artifact-taglet");
        assertThat(sourceDir).exists();
        copyDirectory(sourceDir.toFile(), localRepo);

        // ----------------------------------------------------------------------
        // stylesheetfile-test
        // ----------------------------------------------------------------------

        sourceDir = unit.resolve("stylesheetfile-test/artifact-stylesheetfile");
        assertThat(sourceDir).exists();
        copyDirectory(sourceDir.toFile(), localRepo);

        // ----------------------------------------------------------------------
        // helpfile-test
        // ----------------------------------------------------------------------

        sourceDir = unit.resolve("helpfile-test/artifact-helpfile");
        assertThat(sourceDir).exists();
        copyDirectory(sourceDir.toFile(), localRepo);

        // Remove SCM files
        List<String> files = FileUtils.getFileAndDirectoryNames(
                localRepo, FileUtils.getDefaultExcludesAsString(), null, true, true, true, true);
        for (String filename : files) {
            File file = new File(filename);

            if (file.isDirectory()) {
                deleteDirectory(file);
            } else {
                file.delete();
            }
        }
    }

    /**
     * Convenience method that reads the contents of the specified file object into a string with a
     * <code>space</code> as line separator.
     *
     * @see #LINE_SEPARATOR
     * @param file the file to be read
     * @return a String object that contains the contents of the file
     * @throws IOException if any
     */
    private static String readFile(Path file) throws IOException {
        return readFile(file, StandardCharsets.UTF_8);
    }

    /**
     * Convenience method that reads the contents of the specified file object into a string with a
     * <code>space</code> as line separator.
     *
     * @see #LINE_SEPARATOR
     * @param file the file to be read
     * @param cs charset to use
     * @return a String object that contains the contents of the file
     * @throws IOException if any
     */
    private static String readFile(Path file, Charset cs) throws IOException {
        StringBuilder str = new StringBuilder((int) Files.size(file));

        for (String strTmp : Files.readAllLines(file, cs)) {
            str.append(LINE_SEPARATOR);
            str.append(strTmp);
        }

        return str.toString();
    }

    /**
     * Test when default configuration is provided for the plugin
     *
     * @throws Exception if any
     */
    public void testDefaultConfiguration() throws Exception {
        Path testPom = unit.resolve("default-configuration/default-configuration-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        // package level generated javadoc files
        Path apidocs = new File(getBasedir(), "target/test/unit/default-configuration/target/site/apidocs").toPath();

        String appHtml = "def/configuration/App.html";
        Path generatedFile = apidocs.resolve(appHtml);
        assertThat(generatedFile).exists();

        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isBefore("16")) {
            String url = Objects.requireNonNull(mojo.getDefaultJavadocApiLink()).getUrl();
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("HEAD");
            try {
                // only test when URL can be reached
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    try {
                        assumeThat(connection.getURL().toString(), is(url));

                        // https://bugs.openjdk.java.net/browse/JDK-8216497
                        MatcherAssert.assertThat(
                                url + " available, but " + appHtml + " is missing link to java.lang.Object",
                                new String(Files.readAllBytes(generatedFile), StandardCharsets.UTF_8),
                                anyOf(
                                        containsString("/docs/api/java/lang/Object.html"),
                                        containsString("/docs/api/java.base/java/lang/Object.html")));
                    } catch (AssumptionViolatedException e) {
                        LOGGER.warn("ignoring defaultAPI check: {}", e.getMessage());
                    }
                }
            } catch (Exception e) {
                LOGGER.error("error connecting to javadoc URL: {}", url);
                throw e;
            }
        } else {
            MatcherAssert.assertThat(
                    new String(Files.readAllBytes(generatedFile), StandardCharsets.UTF_8),
                    containsString("/docs/api/java.base/java/lang/Object.html"));
        }

        assertThat(apidocs.resolve("def/configuration/AppSample.html")).exists();
        assertThat(apidocs.resolve("def/configuration/package-summary.html")).exists();
        assertThat(apidocs.resolve("def/configuration/package-tree.html")).exists();
        assertThat(apidocs.resolve("def/configuration/package-use.html")).exists();

        // package-frame and allclasses-(no)frame not generated anymore since Java 11
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isBefore("11")) {
            assertThat(apidocs.resolve("def/configuration/package-frame.html")).exists();
            assertThat(apidocs.resolve("allclasses-frame.html"))
                    .exists()
                    .content()
                    .containsOnlyOnce("def/configuration/App.html")
                    .containsOnlyOnce("def/configuration/AppSample.html");
            assertThat(apidocs.resolve("allclasses-noframe.html"))
                    .exists()
                    .content()
                    .containsOnlyOnce("def/configuration/App.html")
                    .containsOnlyOnce("def/configuration/AppSample.html");
        }

        // class level generated javadoc files
        assertThat(apidocs.resolve("def/configuration/class-use/App.html")).exists();
        assertThat(apidocs.resolve("def/configuration/class-use/AppSample.html"))
                .exists();

        // project level generated javadoc files
        assertThat(apidocs.resolve("constant-values.html")).exists();
        assertThat(apidocs.resolve("deprecated-list.html")).exists();
        assertThat(apidocs.resolve("help-doc.html")).exists();
        assertThat(apidocs.resolve("index-all.html")).exists();
        assertThat(apidocs.resolve("index.html")).exists();
        assertThat(apidocs.resolve("overview-tree.html")).exists();
        assertThat(apidocs.resolve("stylesheet.css")).exists();

        if (JavaVersion.JAVA_VERSION.isAtLeast("10")) {
            assertThat(apidocs.resolve("element-list")).exists();
        } else {
            assertThat(apidocs.resolve("package-list")).exists();
        }
    }

    /**
     * Method for testing the subpackages and excludePackageNames parameter
     *
     * @throws Exception if any
     */
    public void testSubpackages() throws Exception {
        Path testPom = unit.resolve("subpackages-test/subpackages-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/subpackages-test/target/site/apidocs").toPath();

        // check the excluded packages
        assertThat(apidocs.resolve("subpackages/test/excluded")).doesNotExist();
        assertThat(apidocs.resolve("subpackages/test/included/exclude")).doesNotExist();

        // check if the classes in the specified subpackages were included
        assertThat(apidocs.resolve("subpackages/test/App.html")).exists();
        assertThat(apidocs.resolve("subpackages/test/AppSample.html")).exists();
        assertThat(apidocs.resolve("subpackages/test/included/IncludedApp.html"))
                .exists();
        assertThat(apidocs.resolve("subpackages/test/included/IncludedAppSample.html"))
                .exists();
    }

    public void testIncludesExcludes() throws Exception {
        Path testPom = unit.resolve("file-include-exclude-test/file-include-exclude-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs =
                new File(getBasedir(), "target/test/unit/file-include-exclude-test/target/site/apidocs").toPath();

        // check if the classes in the specified subpackages were included
        assertThat(apidocs.resolve("subpackages/test/App.html")).exists();
        assertThat(apidocs.resolve("subpackages/test/AppSample.html")).exists();
        assertThat(apidocs.resolve("subpackages/test/included/IncludedApp.html"))
                .exists();
        assertThat(apidocs.resolve("subpackages/test/included/IncludedAppSample.html"))
                .exists();
        assertThat(apidocs.resolve("subpackages/test/PariahApp.html")).doesNotExist();
    }

    /**
     * Test the recursion and exclusion of the doc-files subdirectories.
     *
     * @throws Exception if any
     */
    public void testDocfiles() throws Exception {
        // Should be an assumption, but not supported by TestCase
        // Seems like a bug in Javadoc 9 and above
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("9")) {
            return;
        }

        Path testPom = unit.resolve("docfiles-test/docfiles-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/docfiles-test/target/site/apidocs/").toPath();

        // check if the doc-files subdirectories were copied
        assertThat(apidocs.resolve("docfiles/test/doc-files")).exists();
        assertThat(apidocs.resolve("docfiles/test/doc-files/included-dir1/sample-included1.gif"))
                .exists();
        assertThat(apidocs.resolve("docfiles/test/doc-files/included-dir2/sample-included2.gif"))
                .exists();
        assertThat(apidocs.resolve("docfiles/test/doc-files/excluded-dir1")).doesNotExist();
        assertThat(apidocs.resolve("docfiles/test/doc-files/excluded-dir2")).doesNotExist();

        testPom = unit.resolve("docfiles-with-java-test/docfiles-with-java-test-plugin-config.xml");
        mojo = lookupMojo(testPom);
        mojo.execute();
    }

    /**
     * Test javadoc plugin using custom configuration. noindex, notree and nodeprecated parameters
     * were set to true.
     *
     * @throws Exception if any
     */
    public void testCustomConfiguration() throws Exception {
        Path testPom = unit.resolve("custom-configuration/custom-configuration-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/custom-configuration/target/site/apidocs").toPath();

        // check if there is a tree page generated (notree == true)
        assertThat(apidocs.resolve("overview-tree.html")).doesNotExist();
        assertThat(apidocs.resolve("custom/configuration/package-tree.html")).doesNotExist();

        // check if the main index page was generated (noindex == true)
        assertThat(apidocs.resolve("index-all.html")).doesNotExist();

        // check if the deprecated list and the deprecated api were generated (nodeprecated == true)
        // @todo Fix: the class-use of the deprecated api is still created eventhough the deprecated api of that class
        // is no longer generated
        assertThat(apidocs.resolve("deprecated-list.html")).doesNotExist();
        assertThat(apidocs.resolve("custom/configuration/App.html")).doesNotExist();

        // read the contents of the html files based on some of the parameter values
        // author == false
        String str = readFile(apidocs.resolve("custom/configuration/AppSample.html"));
        assertFalse(str.toLowerCase().contains("author"));

        // bottom
        assertTrue(str.toUpperCase().contains("SAMPLE BOTTOM CONTENT"));

        // offlineLinks
        if (JavaVersion.JAVA_VERSION.isBefore("11.0.2")) {
            assertThat(str)
                    .containsIgnoringCase("href=\"http://java.sun.com/j2se/1.4.2/docs/api/java/lang/string.html");
        } else {
            assertTrue(str.toLowerCase()
                    .contains("href=\"http://java.sun.com/j2se/1.4.2/docs/api/java.base/java/lang/string.html"));
        }

        // header
        assertTrue(str.toUpperCase().contains("MAVEN JAVADOC PLUGIN TEST"));

        // footer
        if (JavaVersion.JAVA_VERSION.isBefore("16-ea")
                && !System.getProperty("java.vm.name").contains("OpenJ9")) {
            assertTrue(str.toUpperCase().contains("MAVEN JAVADOC PLUGIN TEST FOOTER"));
        }

        // nohelp == true
        assertFalse(str.toUpperCase().contains("/HELP-DOC.HTML"));

        // check the wildcard (*) package exclusions -- excludePackageNames parameter
        assertThat(apidocs.resolve("custom/configuration/exclude1/Exclude1App.html"))
                .exists();
        assertThat(apidocs.resolve("custom/configuration/exclude1/subexclude/SubexcludeApp.html"))
                .doesNotExist();
        assertThat(apidocs.resolve("custom/configuration/exclude2/Exclude2App.html"))
                .doesNotExist();

        assertThat(apidocs.resolve("options")).isRegularFile();

        String contentOptions = new String(Files.readAllBytes(apidocs.resolve("options")), StandardCharsets.UTF_8);

        assertNotNull(contentOptions);
        assertThat(contentOptions).contains("-link").contains("http://java.sun.com/j2se/");
    }

    /**
     * Method to test the doclet artifact configuration
     *
     * @throws Exception if any
     */
    public void testDoclets() throws Exception {
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("13")) {
            // As of JDK 13, the com.sun.javadoc API is no longer supported.
            return;
        }

        // ----------------------------------------------------------------------
        // doclet-test: check if the file generated by UmlGraph exists and if
        // doclet path contains the UmlGraph artifact
        // ----------------------------------------------------------------------

        Path testPom = unit.resolve("doclet-test/doclet-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);

        MavenSession session = spy(newMavenSession(mojo.project));
        ProjectBuildingRequest buildingRequest = mock(ProjectBuildingRequest.class);
        when(buildingRequest.getRemoteRepositories()).thenReturn(mojo.project.getRemoteArtifactRepositories());
        when(session.getProjectBuildingRequest()).thenReturn(buildingRequest);
        DefaultRepositorySystemSession repositorySession = new DefaultRepositorySystemSession();
        repositorySession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
                .newInstance(repositorySession, new LocalRepository(localRepo)));
        when(buildingRequest.getRepositorySession()).thenReturn(repositorySession);
        when(session.getRepositorySession()).thenReturn(repositorySession);
        LegacySupport legacySupport = lookup(LegacySupport.class);
        legacySupport.setSession(session);

        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repositorySession);
        mojo.execute();

        Path generatedFile =
                new File(getBasedir(), "target/test/unit/doclet-test/target/site/apidocs/graph.dot").toPath();
        assertThat(generatedFile).exists();

        Path optionsFile = new File(mojo.getPluginReportOutputDirectory(), "options").toPath();
        assertThat(optionsFile).exists();
        String options = readFile(optionsFile);
        assertThat(options).contains("/target/local-repo/umlgraph/UMLGraph/2.1/UMLGraph-2.1.jar");

        // ----------------------------------------------------------------------
        // doclet-path: check if the file generated by UmlGraph exists and if
        // doclet path contains the twice UmlGraph artifacts
        // ----------------------------------------------------------------------

        testPom = unit.resolve("doclet-path-test/doclet-path-test-plugin-config.xml");
        mojo = lookupMojo(testPom);
        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repositorySession);
        mojo.execute();

        generatedFile = new File(getBasedir(), "target/test/unit/doclet-test/target/site/apidocs/graph.dot").toPath();
        assertThat(generatedFile).exists();

        optionsFile = new File(mojo.getPluginReportOutputDirectory(), "options").toPath();
        assertThat(optionsFile).exists();
        options = readFile(optionsFile);
        assertThat(options)
                .contains("/target/local-repo/umlgraph/UMLGraph/2.1/UMLGraph-2.1.jar")
                .contains("/target/local-repo/umlgraph/UMLGraph-bis/2.1/UMLGraph-bis-2.1.jar");
    }

    /**
     * Method to test when the path to the project sources has an apostrophe (')
     *
     * @throws Exception if any
     */
    public void testQuotedPath() throws Exception {
        Path testPom = unit.resolve("quotedpath'test/quotedpath-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/quotedpath'test/target/site/apidocs").toPath();

        // package level generated javadoc files
        assertThat(apidocs.resolve("quotedpath/test/App.html")).exists();
        assertThat(apidocs.resolve("quotedpath/test/AppSample.html")).exists();

        // project level generated javadoc files
        assertThat(apidocs.resolve("index-all.html")).exists();
        assertThat(apidocs.resolve("index.html")).exists();
        assertThat(apidocs.resolve("overview-tree.html")).exists();
        assertThat(apidocs.resolve("stylesheet.css")).exists();

        if (JavaVersion.JAVA_VERSION.isBefore("10")) {
            assertThat(apidocs.resolve("package-list")).exists();
        } else {
            assertThat(apidocs.resolve("element-list")).exists();
        }
    }

    /**
     * Method to test when the options file has umlauts.
     *
     * @throws Exception if any
     */
    public void testOptionsUmlautEncoding() throws Exception {
        Path testPom = unit.resolve("optionsumlautencoding-test/optionsumlautencoding-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path optionsFile = new File(mojo.getPluginReportOutputDirectory(), "options").toPath();
        assertThat(optionsFile).exists();

        // check for a part of the window title
        String content;
        String expected;
        if (JavaVersion.JAVA_VERSION.isAtLeast("9") && JavaVersion.JAVA_VERSION.isBefore("12")) {
            content = readFile(optionsFile, StandardCharsets.UTF_8);
            expected = OPTIONS_UMLAUT_ENCODING;
        } else {
            content = readFile(optionsFile, Charset.defaultCharset());
            expected = new String(OPTIONS_UMLAUT_ENCODING.getBytes(Charset.defaultCharset()));
        }

        assertThat(content).contains(expected);

        Path apidocs =
                new File(getBasedir(), "target/test/unit/optionsumlautencoding-test/target/site/apidocs").toPath();

        // package level generated javadoc files
        assertThat(apidocs.resolve("optionsumlautencoding/test/App.html")).exists();
        assertThat(apidocs.resolve("optionsumlautencoding/test/AppSample.html")).exists();

        // project level generated javadoc files
        assertThat(apidocs.resolve("index-all.html")).exists();
        assertThat(apidocs.resolve("index.html")).exists();
        assertThat(apidocs.resolve("overview-tree.html")).exists();
        assertThat(apidocs.resolve("stylesheet.css")).exists();

        if (JavaVersion.JAVA_VERSION.isBefore("10")) {
            assertThat(apidocs.resolve("package-list")).exists();
        } else {
            assertThat(apidocs.resolve("element-list")).exists();
        }
    }

    /**
     * Method to test the taglet artifact configuration
     *
     * @throws Exception if any
     */
    public void testTaglets() throws Exception {
        // ----------------------------------------------------------------------
        // taglet-test: check if a taglet is used
        // ----------------------------------------------------------------------

        // Should be an assumption, but not supported by TestCase
        // com.sun.tools.doclets.Taglet not supported by Java9 anymore
        // Should be refactored with jdk.javadoc.doclet.Taglet
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("10")) {
            return;
        }

        Path testPom = unit.resolve("taglet-test/taglet-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);

        MavenSession session = spy(newMavenSession(mojo.project));
        ProjectBuildingRequest buildingRequest = mock(ProjectBuildingRequest.class);
        when(buildingRequest.getRemoteRepositories()).thenReturn(mojo.project.getRemoteArtifactRepositories());
        when(session.getProjectBuildingRequest()).thenReturn(buildingRequest);
        DefaultRepositorySystemSession repositorySession = new DefaultRepositorySystemSession();
        repositorySession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
                .newInstance(repositorySession, new LocalRepository(localRepo)));
        when(buildingRequest.getRepositorySession()).thenReturn(repositorySession);
        when(session.getRepositorySession()).thenReturn(repositorySession);
        LegacySupport legacySupport = lookup(LegacySupport.class);
        legacySupport.setSession(session);

        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repositorySession);

        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/taglet-test/target/site/apidocs").toPath();

        assertThat(apidocs.resolve("index.html")).exists();

        Path appFile = apidocs.resolve("taglet/test/App.html");
        assertThat(appFile).exists();
        String appString = readFile(appFile);
        assertThat(appString).contains("<b>To Do:</b>");
    }

    /**
     * Method to test the jdk5 javadoc
     *
     * @throws Exception if any
     */
    public void testJdk5() throws Exception {
        // Should be an assumption, but not supported by TestCase
        // Java 5 not supported by Java9 anymore
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("9")) {
            return;
        }

        Path testPom = unit.resolve("jdk5-test/jdk5-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/jdk5-test/target/site/apidocs").toPath();

        assertThat(apidocs.resolve("index.html")).exists();

        Path overviewSummary = apidocs.resolve("overview-summary.html");
        assertThat(overviewSummary).exists();
        String content = readFile(overviewSummary);
        assertThat(content).contains("<b>Test the package-info</b>");

        Path packageSummary = apidocs.resolve("jdk5/test/package-summary.html");
        assertThat(packageSummary).exists();
        content = readFile(packageSummary);
        assertThat(content).contains("<b>Test the package-info</b>");
    }

    /**
     * Test to find the javadoc executable when <code>java.home</code> is not in the JDK_HOME. In this case, try to
     * use the <code>JAVA_HOME</code> environment variable.
     *
     * @throws Exception if any
     */
    public void testToFindJavadoc() throws Exception {
        String oldJreHome = System.getProperty("java.home");
        System.setProperty("java.home", "foo/bar");

        Path testPom = unit.resolve("javaHome-test/javaHome-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        System.setProperty("java.home", oldJreHome);
    }

    /**
     * Test the javadoc resources.
     *
     * @throws Exception if any
     */
    public void testJavadocResources() throws Exception {
        Path testPom = unit.resolve("resources-test/resources-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/resources-test/target/site/apidocs/").toPath();

        Path app = apidocs.resolve("resources/test/App.html");
        assertThat(app).exists();
        String content = readFile(app);
        assertThat(content).contains("<img src=\"doc-files/maven-feather.png\" alt=\"Maven\">");
        assertThat(apidocs.resolve("resources/test/doc-files/maven-feather.png"))
                .exists();

        Path app2 = apidocs.resolve("resources/test2/App2.html");
        assertThat(app2).exists();
        content = readFile(app2);
        assertThat(content).contains("<img src=\"doc-files/maven-feather.png\" alt=\"Maven\">");
        assertThat(apidocs.resolve("resources/test2/doc-files/maven-feather.png"))
                .doesNotExist();

        // with excludes
        testPom = unit.resolve("resources-with-excludes-test/resources-with-excludes-test-plugin-config.xml");
        mojo = lookupMojo(testPom);
        mojo.execute();

        apidocs = new File(getBasedir(), "target/test/unit/resources-with-excludes-test/target/site/apidocs").toPath();

        app = apidocs.resolve("resources/test/App.html");
        assertThat(app).exists();
        content = readFile(app);
        assertThat(content).contains("<img src=\"doc-files/maven-feather.png\" alt=\"Maven\">");

        JavaVersion javadocVersion = (JavaVersion) getVariableValueFromObject(mojo, "javadocRuntimeVersion");
        if (javadocVersion.isAtLeast("1.8") /* && javadocVersion.isBefore( "14" ) */) {
            // https://bugs.openjdk.java.net/browse/JDK-8032205
            assertThat(apidocs.resolve("resources/test/doc-files/maven-feather.png"))
                    .as("Javadoc runtime version: " + javadocVersion
                            + "\nThis bug appeared in JDK8 and was planned to be fixed in JDK9, see JDK-8032205")
                    .exists();
        } else {
            assertThat(apidocs.resolve("resources/test/doc-files/maven-feather.png"))
                    .doesNotExist();
        }
        assertThat(apidocs.resolve("resources/test2/doc-files/maven-feather.png"))
                .exists();

        app2 = apidocs.resolve("resources/test2/App2.html");
        assertThat(app2).exists();
        content = readFile(app2);
        assertThat(content).contains("<img src=\"doc-files/maven-feather.png\" alt=\"Maven\">");
        assertThat(apidocs.resolve("resources/test2/doc-files/maven-feather.png"))
                .exists();
    }

    /**
     * Test the javadoc for a POM project.
     *
     * @throws Exception if any
     */
    public void testPom() throws Exception {
        Path testPom = unit.resolve("pom-test/pom-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        assertThat(new File(getBasedir(), "target/test/unit/pom-test/target/site"))
                .doesNotExist();
    }

    /**
     * Test the javadoc with tag.
     *
     * @throws Exception if any
     */
    public void testTag() throws Exception {
        Path testPom = unit.resolve("tag-test/tag-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path app = new File(getBasedir(), "target/test/unit/tag-test/target/site/apidocs/tag/test/App.html").toPath();
        assertThat(app).exists();
        String readed = readFile(app);
        assertThat(readed).contains(">To do something:</").contains(">Generator Class:</");

        // In javadoc-options-javadoc-resources.xml tag 'version' has only a name,
        // which is not enough for Java 11 anymore
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isBefore("11")) {
            assertThat(readed).contains(">Version:</");
            assertTrue(readed.toLowerCase().contains("</dt>" + LINE_SEPARATOR + "  <dd>1.0</dd>")
                    || readed.toLowerCase().contains("</dt>" + LINE_SEPARATOR + "<dd>1.0</dd>" /* JDK 8 */));
        }
    }

    /**
     * Test newline in the header/footer parameter
     *
     * @throws Exception if any
     */
    public void testHeaderFooter() throws Exception {
        Path testPom = unit.resolve("header-footer-test/header-footer-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        try {
            mojo.execute();
        } catch (MojoExecutionException e) {
            fail("Doesnt handle correctly newline for header or footer parameter");
        }
    }

    /**
     * Test newline in various string parameters
     *
     * @throws Exception if any
     */
    public void testNewline() throws Exception {
        Path testPom = unit.resolve("newline-test/newline-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        try {
            mojo.execute();
        } catch (MojoExecutionException e) {
            fail("Doesn't handle correctly newline for string parameters. See options and packages files.");
        }
    }

    /**
     * Method to test the jdk6 javadoc
     *
     * @throws Exception if any
     */
    public void testJdk6() throws Exception {
        // Should be an assumption, but not supported by TestCase
        // Java 6 not supported by Java 12 anymore
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("12")) {
            return;
        }

        Path testPom = unit.resolve("jdk6-test/jdk6-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        mojo.execute();

        Path apidocs = new File(getBasedir(), "target/test/unit/jdk6-test/target/site/apidocs").toPath();
        assertThat(apidocs.resolve("index.html")).exists();

        Path overview;
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isBefore("11")) {
            overview = apidocs.resolve("overview-summary.html");
        } else {
            overview = apidocs.resolve("index.html");
        }

        assertThat(overview).exists();
        String content = readFile(overview);
        assertThat(content)
                .contains("Top - Copyright &#169; All rights reserved.")
                .contains("Header - Copyright &#169; All rights reserved.");
        // IBM dist of adopt-openj9 does not support the footer param
        if (!System.getProperty("java.vm.name").contains("OpenJ9")) {
            assertThat(content).contains("Footer - Copyright &#169; All rights reserved.");
        }

        Path packageSummary = apidocs.resolve("jdk6/test/package-summary.html");
        assertThat(packageSummary).exists();
        content = readFile(packageSummary);
        assertThat(content)
                .contains("Top - Copyright &#169; All rights reserved.")
                .contains("Header - Copyright &#169; All rights reserved.");

        // IBM dist of adopt-openj9 does not support the footer param
        if (!System.getProperty("java.vm.name").contains("OpenJ9")) {
            assertThat(content).contains("Footer - Copyright &#169; All rights reserved.");
        }
    }

    /**
     * Method to test proxy support in the javadoc
     *
     * @throws Exception if any
     */
    public void testProxy() throws Exception {
        Settings settings = new Settings();
        Proxy proxy = new Proxy();

        // dummy proxy
        proxy.setActive(true);
        proxy.setHost("127.0.0.1");
        proxy.setPort(80);
        proxy.setProtocol("http");
        proxy.setUsername("toto");
        proxy.setPassword("toto");
        proxy.setNonProxyHosts("www.google.com|*.somewhere.com");
        settings.addProxy(proxy);

        Path testPom =
                new File(getBasedir(), "src/test/resources/unit/proxy-test/proxy-test-plugin-config.xml").toPath();
        JavadocReport mojo = lookupMojo(testPom);

        MavenSession session = spy(newMavenSession(mojo.project));
        ProjectBuildingRequest buildingRequest = mock(ProjectBuildingRequest.class);
        when(buildingRequest.getRemoteRepositories()).thenReturn(mojo.project.getRemoteArtifactRepositories());
        when(buildingRequest.getRepositoryMerging()).thenReturn(RepositoryMerging.POM_DOMINANT);
        when(session.getProjectBuildingRequest()).thenReturn(buildingRequest);
        DefaultRepositorySystemSession repositorySession = new DefaultRepositorySystemSession();
        repositorySession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
                .newInstance(repositorySession, new LocalRepository(localRepo)));
        when(buildingRequest.getRepositorySession()).thenReturn(repositorySession);
        when(session.getRepositorySession()).thenReturn(repositorySession);
        LegacySupport legacySupport = lookup(LegacySupport.class);
        legacySupport.setSession(session);

        setVariableValueToObject(mojo, "settings", settings);
        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repositorySession);
        mojo.execute();

        Path commandLine = new File(
                        getBasedir(),
                        "target/test/unit/proxy-test/target/site/apidocs/javadoc."
                                + (SystemUtils.IS_OS_WINDOWS ? "bat" : "sh"))
                .toPath();
        assertThat(commandLine).exists();
        String readed = readFile(commandLine);
        assertThat(readed).contains("-J-Dhttp.proxyHost=127.0.0.1").contains("-J-Dhttp.proxyPort=80");
        if (SystemUtils.IS_OS_WINDOWS) {
            assertThat(readed).contains(" -J-Dhttp.nonProxyHosts=\"www.google.com^|*.somewhere.com\" ");
        } else {
            assertThat(readed).contains(" \"-J-Dhttp.nonProxyHosts=\\\"www.google.com^|*.somewhere.com\\\"\" ");
        }

        Path options = new File(getBasedir(), "target/test/unit/proxy-test/target/site/apidocs/options").toPath();
        assertThat(options).exists();
        String optionsContent = readFile(options);
        // NO -link expected
        assertThat(optionsContent).doesNotContain("-link");

        // real proxy
        ProxyServer proxyServer = null;
        AuthAsyncProxyServlet proxyServlet;
        try {
            proxyServlet = new AuthAsyncProxyServlet();
            proxyServer = new ProxyServer(proxyServlet);
            proxyServer.start();

            settings = new Settings();
            proxy = new Proxy();
            proxy.setActive(true);
            proxy.setHost(proxyServer.getHostName());
            proxy.setPort(proxyServer.getPort());
            proxy.setProtocol("http");
            settings.addProxy(proxy);

            mojo = lookupMojo(testPom);
            setVariableValueToObject(mojo, "settings", settings);
            setVariableValueToObject(mojo, "session", session);
            setVariableValueToObject(mojo, "repoSession", repositorySession);
            mojo.execute();
            readed = readFile(commandLine);
            assertTrue(readed.contains("-J-Dhttp.proxyHost=" + proxyServer.getHostName()));
            assertTrue(readed.contains("-J-Dhttp.proxyPort=" + proxyServer.getPort()));

            optionsContent = readFile(options);
            // -link expected
            // TODO: This got disabled for now!
            // This test fails since the last commit but I actually think it only ever worked by accident.
            // It did rely on a commons-logging-1.0.4.pom which got resolved by a test which did run previously.
            // But after updating to commons-logging.1.1.1 there is no pre-resolved artifact available in
            // target/local-repo anymore, thus the javadoc link info cannot get built and the test fails
            // I'll for now just disable this line of code, because the test as far as I can see _never_
            // did go upstream. The remoteRepository list used is always empty!.
            //
            //            assertTrue( optionsContent.contains( "-link 'http://commons.apache.org/logging/apidocs'" ) );
        } finally {
            if (proxyServer != null) {
                proxyServer.stop();
            }
        }

        // auth proxy
        Map<String, String> authentications = new HashMap<>();
        authentications.put("foo", "bar");
        try {
            proxyServlet = new AuthAsyncProxyServlet(authentications);
            proxyServer = new ProxyServer(proxyServlet);
            proxyServer.start();

            settings = new Settings();
            proxy = new Proxy();
            proxy.setActive(true);
            proxy.setHost(proxyServer.getHostName());
            proxy.setPort(proxyServer.getPort());
            proxy.setProtocol("http");
            proxy.setUsername("foo");
            proxy.setPassword("bar");
            settings.addProxy(proxy);

            mojo = lookupMojo(testPom);
            setVariableValueToObject(mojo, "settings", settings);
            setVariableValueToObject(mojo, "session", session);
            setVariableValueToObject(mojo, "repoSession", repositorySession);
            mojo.execute();
            readed = readFile(commandLine);
            assertThat(readed)
                    .contains("-J-Dhttp.proxyHost=" + proxyServer.getHostName())
                    .contains("-J-Dhttp.proxyPort=" + proxyServer.getPort());

            optionsContent = readFile(options);
            // -link expected
            // see comment above (line 829)
            //             assertTrue( optionsContent.contains( "-link 'http://commons.apache.org/logging/apidocs'" ) );
        } finally {
            if (proxyServer != null) {
                proxyServer.stop();
            }
        }
    }

    /**
     * Method to test error or conflict in Javadoc options and in standard doclet options.
     *
     * @throws Exception if any
     */
    public void testValidateOptions() throws Exception {
        // encoding
        Path testPom = unit.resolve("validate-options-test/wrong-encoding-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);
        try {
            mojo.execute();
            fail("No wrong encoding catch");
        } catch (MojoExecutionException e) {
            assertTrue("No wrong encoding catch", e.getMessage().contains("Unsupported option <encoding/>"));
        }
        testPom = unit.resolve("validate-options-test/wrong-docencoding-test-plugin-config.xml");
        mojo = lookupMojo(testPom);
        try {
            mojo.execute();
            fail("No wrong docencoding catch");
        } catch (MojoExecutionException e) {
            assertTrue("No wrong docencoding catch", e.getMessage().contains("Unsupported option <docencoding/>"));
        }
        testPom = unit.resolve("validate-options-test/wrong-charset-test-plugin-config.xml");
        mojo = lookupMojo(testPom);
        try {
            mojo.execute();
            fail("No wrong charset catch");
        } catch (MojoExecutionException e) {
            assertTrue("No wrong charset catch", e.getMessage().contains("Unsupported option <charset/>"));
        }

        testPom = unit.resolve("validate-options-test/wrong-locale-with-variant-test-plugin-config.xml");
        mojo = lookupMojo(testPom);
        mojo.execute();
        assertTrue("No wrong locale catch", true);

        // conflict options
        testPom = unit.resolve("validate-options-test/conflict-options-test-plugin-config.xml");
        mojo = lookupMojo(testPom);
        try {
            mojo.execute();
            fail("No conflict catch");
        } catch (MojoExecutionException e) {
            assertTrue("No conflict catch", e.getMessage().contains("Option <nohelp/> conflicts with <helpfile/>"));
        }
    }

    /**
     * Method to test the <code>&lt;tagletArtifacts/&gt;</code> parameter.
     *
     * @throws Exception if any
     */
    public void testTagletArtifacts() throws Exception {
        // Should be an assumption, but not supported by TestCase
        // com.sun.tools.doclets.Taglet not supported by Java 10 anymore
        if (JavaVersion.JAVA_SPECIFICATION_VERSION.isAtLeast("10")) {
            return;
        }

        Path testPom = unit.resolve("tagletArtifacts-test/tagletArtifacts-test-plugin-config.xml");
        JavadocReport mojo = lookupMojo(testPom);

        MavenSession session = newMavenSession(mojo.project);
        DefaultRepositorySystemSession repoSysSession = (DefaultRepositorySystemSession) session.getRepositorySession();
        repoSysSession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
                .newInstance(session.getRepositorySession(), new LocalRepository(new File("target/local-repo"))));
        // Ensure remote repo connection uses SSL
        LegacySupport legacySupport = lookup(LegacySupport.class);
        legacySupport.setSession(session);
        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repoSysSession);
        mojo.execute();

        Path optionsFile = new File(mojo.getPluginReportOutputDirectory(), "options").toPath();
        assertThat(optionsFile).exists();
        String options = readFile(optionsFile);
        // count -taglet
        assertThat(StringUtils.countMatches(options, LINE_SEPARATOR + "-taglet" + LINE_SEPARATOR))
                .isEqualTo(3);
        assertThat(options)
                .contains("org.codehaus.plexus.javadoc.PlexusConfigurationTaglet")
                .contains("org.codehaus.plexus.javadoc.PlexusRequirementTaglet")
                .contains("org.codehaus.plexus.javadoc.PlexusComponentTaglet");
    }

    /**
     * Method to test the <code>&lt;stylesheetfile/&gt;</code> parameter.
     *
     * @throws Exception if any
     */
    public void testStylesheetfile() throws Exception {
        Path testPom = unit.resolve("stylesheetfile-test/pom.xml");

        JavadocReport mojo = lookupMojo(testPom);
        assertNotNull(mojo);

        MavenSession session = spy(newMavenSession(mojo.project));
        ProjectBuildingRequest buildingRequest = mock(ProjectBuildingRequest.class);
        when(buildingRequest.getRemoteRepositories()).thenReturn(mojo.project.getRemoteArtifactRepositories());
        when(session.getProjectBuildingRequest()).thenReturn(buildingRequest);
        DefaultRepositorySystemSession repositorySession = new DefaultRepositorySystemSession();
        repositorySession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
                .newInstance(repositorySession, new LocalRepository(localRepo)));
        when(buildingRequest.getRepositorySession()).thenReturn(repositorySession);
        when(session.getRepositorySession()).thenReturn(repositorySession);
        LegacySupport legacySupport = lookup(LegacySupport.class);
        legacySupport.setSession(session);
        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repositorySession);

        Path apidocs = new File(getBasedir(), "target/test/unit/stylesheetfile-test/target/site/apidocs").toPath();

        Path stylesheetfile = apidocs.resolve("stylesheet.css");
        Path options = apidocs.resolve("options");

        // stylesheet == maven OR java
        setVariableValueToObject(mojo, "stylesheet", "javamaven");

        try {
            mojo.execute();
            fail();
        } catch (MojoExecutionException | MojoFailureException e) {
        }

        // stylesheet == java
        setVariableValueToObject(mojo, "stylesheet", "java");
        mojo.execute();

        String content = readFile(stylesheetfile);
        if (JavaVersion.JAVA_VERSION.isAtLeast("13-ea")) {
            assertTrue(content.contains("/*" + LINE_SEPARATOR + " * Javadoc style sheet" + LINE_SEPARATOR + " */"));
        } else if (JavaVersion.JAVA_VERSION.isAtLeast("10")) {
            assertTrue(content.contains("/* " + LINE_SEPARATOR + " * Javadoc style sheet" + LINE_SEPARATOR + " */"));
        } else {
            assertTrue(content.contains("/* Javadoc style sheet */"));
        }

        String optionsContent = readFile(options);
        assertFalse(optionsContent.contains("-stylesheetfile"));

        // stylesheetfile defined as a project resource
        setVariableValueToObject(mojo, "stylesheet", null);
        setVariableValueToObject(mojo, "stylesheetfile", "com/mycompany/app/javadoc/css/stylesheet.css");
        mojo.execute();

        content = readFile(stylesheetfile);
        assertTrue(content.contains("/* Custom Javadoc style sheet in project */"));

        optionsContent = readFile(options);
        assertTrue(optionsContent.contains("-stylesheetfile"));
        Path stylesheetResource =
                unit.resolve("stylesheetfile-test/src/main/resources/com/mycompany/app/javadoc/css/stylesheet.css");
        assertTrue(optionsContent.contains(
                "'" + stylesheetResource.toFile().getAbsolutePath().replaceAll("\\\\", "/") + "'"));

        // stylesheetfile defined in a javadoc plugin dependency
        setVariableValueToObject(mojo, "stylesheetfile", "com/mycompany/app/javadoc/css2/stylesheet.css");
        mojo.execute();

        content = readFile(stylesheetfile);
        assertTrue(content.contains("/* Custom Javadoc style sheet in artefact */"));

        optionsContent = readFile(options);
        assertTrue(optionsContent.contains("-stylesheetfile"));
        assertTrue(optionsContent.contains(
                "'" + stylesheetfile.toFile().getAbsolutePath().replaceAll("\\\\", "/") + "'"));

        // stylesheetfile defined as file
        Path css = unit.resolve("stylesheetfile-test/src/main/resources/com/mycompany/app/javadoc/css3/stylesheet.css");
        setVariableValueToObject(mojo, "stylesheetfile", css.toFile().getAbsolutePath());
        mojo.execute();

        content = readFile(stylesheetfile);
        assertTrue(content.contains("/* Custom Javadoc style sheet as file */"));

        optionsContent = readFile(options);
        assertTrue(optionsContent.contains("-stylesheetfile"));
        stylesheetResource =
                unit.resolve("stylesheetfile-test/src/main/resources/com/mycompany/app/javadoc/css3/stylesheet.css");
        assertTrue(optionsContent.contains(
                "'" + stylesheetResource.toFile().getAbsolutePath().replaceAll("\\\\", "/") + "'"));
    }

    /**
     * Method to test the <code>&lt;helpfile/&gt;</code> parameter.
     *
     * @throws Exception if any
     */
    public void testHelpfile() throws Exception {
        Path testPom = unit.resolve("helpfile-test/pom.xml");

        JavadocReport mojo = lookupMojo(testPom);
        assertNotNull(mojo);

        MavenSession session = spy(newMavenSession(mojo.project));
        ProjectBuildingRequest buildingRequest = mock(ProjectBuildingRequest.class);
        when(buildingRequest.getRemoteRepositories()).thenReturn(mojo.project.getRemoteArtifactRepositories());
        when(session.getProjectBuildingRequest()).thenReturn(buildingRequest);
        DefaultRepositorySystemSession repositorySession = new DefaultRepositorySystemSession();
        repositorySession.setLocalRepositoryManager(new SimpleLocalRepositoryManagerFactory()
                .newInstance(repositorySession, new LocalRepository(localRepo)));
        when(buildingRequest.getRepositorySession()).thenReturn(repositorySession);
        when(session.getRepositorySession()).thenReturn(repositorySession);
        LegacySupport legacySupport = lookup(LegacySupport.class);
        legacySupport.setSession(session);
        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repositorySession);

        Path apidocs = new File(getBasedir(), "target/test/unit/helpfile-test/target/site/apidocs").toPath();

        Path helpfile = apidocs.resolve("help-doc.html");
        Path options = apidocs.resolve("options");

        // helpfile by default
        mojo.execute();

        String content = readFile(helpfile);
        assertTrue(content.contains("<!-- Generated by javadoc"));

        String optionsContent = readFile(options);
        assertFalse(optionsContent.contains("-helpfile"));

        // helpfile defined in a javadoc plugin dependency
        setVariableValueToObject(mojo, "helpfile", "com/mycompany/app/javadoc/helpfile/help-doc.html");

        setVariableValueToObject(mojo, "session", session);
        setVariableValueToObject(mojo, "repoSession", repositorySession);

        mojo.execute();

        content = readFile(helpfile);
        assertTrue(content.contains("<!--  Help file from artefact -->"));

        optionsContent = readFile(options);
        assertTrue(optionsContent.contains("-helpfile"));
        Path help = apidocs.resolve("help-doc.html");
        assertTrue(optionsContent.contains("'" + help.toFile().getAbsolutePath().replaceAll("\\\\", "/") + "'"));

        // helpfile defined as a project resource
        setVariableValueToObject(mojo, "helpfile", "com/mycompany/app/javadoc/helpfile2/help-doc.html");
        mojo.execute();

        content = readFile(helpfile);
        assertTrue(content.contains("<!--  Help file from file -->"));

        optionsContent = readFile(options);
        assertTrue(optionsContent.contains("-helpfile"));
        help = unit.resolve("helpfile-test/src/main/resources/com/mycompany/app/javadoc/helpfile2/help-doc.html");
        assertTrue(optionsContent.contains("'" + help.toFile().getAbsolutePath().replaceAll("\\\\", "/") + "'"));

        // helpfile defined as file
        help = unit.resolve("helpfile-test/src/main/resources/com/mycompany/app/javadoc/helpfile2/help-doc.html");
        setVariableValueToObject(mojo, "helpfile", help.toFile().getAbsolutePath());
        mojo.execute();

        content = readFile(helpfile);
        assertTrue(content.contains("<!--  Help file from file -->"));

        optionsContent = readFile(options);
        assertTrue(optionsContent.contains("-helpfile"));
        assertTrue(optionsContent.contains("'" + help.toFile().getAbsolutePath().replaceAll("\\\\", "/") + "'"));
    }
}
