ch.ivyteam.ivy.maven.TestInstallEngineMojo.java Source code

Java tutorial

Introduction

Here is the source code for ch.ivyteam.ivy.maven.TestInstallEngineMojo.java

Source

/*
 * Copyright (C) 2015 AXON IVY AG
 *
 * Licensed 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 ch.ivyteam.ivy.maven;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;

import org.apache.commons.io.IOUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.wink.client.MockHttpServer;
import org.junit.Rule;
import org.junit.Test;

import ch.ivyteam.ivy.maven.InstallEngineMojo.EngineDownloader;
import ch.ivyteam.ivy.maven.engine.EngineVersionEvaluator;
import mockit.Mock;
import mockit.MockUp;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;

public class TestInstallEngineMojo {
    private InstallEngineMojo mojo;

    @Rule
    public ProjectMojoRule<InstallEngineMojo> rule = new ProjectMojoRule<InstallEngineMojo>(
            new File("src/test/resources/base"), InstallEngineMojo.GOAL) {
        @Override
        protected void before() throws Throwable {
            super.before();
            TestInstallEngineMojo.this.mojo = getMojo();
        }
    };

    @Test
    public void testEngineDownload_defaultBehaviour() throws Exception {
        MockHttpServer mockServer = new MockHttpServer(3333);
        try {
            mockServer.startServer();
            String baseUrl = "http://localhost:" + mockServer.getServerPort();
            MockHttpServer.MockHttpServerResponse listPageResponse = new MockHttpServer.MockHttpServerResponse();
            String defaultEngineName = "AxonIvyEngine" + AbstractEngineMojo.DEFAULT_VERSION + ".46949_OSGi_All_x64";
            listPageResponse.setMockResponseContent(
                    "<a href=\"" + baseUrl + "/" + defaultEngineName + ".zip\">the engine!</a>");
            File engineZip = createFakeEngineZip(mojo.ivyVersion);
            MockHttpServer.MockHttpServerResponse engineZipResponse = createFakeZipResponse(engineZip);
            mockServer.setMockHttpServerResponses(listPageResponse, engineZipResponse);

            // test setup can not expand expression ${settings.localRepository}: so we setup an explicit temp dir!
            mojo.engineCacheDirectory = Files.createTempDirectory("tmpRepo").toFile();
            mojo.engineListPageUrl = new URL(baseUrl + "/listPageUrl.html");

            File defaultEngineDir = new File(mojo.engineCacheDirectory, AbstractEngineMojo.DEFAULT_VERSION);
            assertThat(defaultEngineDir).doesNotExist();
            assertThat(mojo.engineDownloadUrl)
                    .as("Default config should favour to download an engine from the 'list page url'.").isNull();
            assertThat(mojo.autoInstallEngine).isTrue();

            mojo.execute();

            assertThat(defaultEngineDir).as("Engine must be automatically downloaded").exists().isDirectory();
            assertThat(defaultEngineDir)
                    .as("Engine directory should automatically be set to subdir of the local repository cache.")
                    .isEqualTo(mojo.getRawEngineDirectory());
        } finally {
            mockServer.stopServer();
        }
    }

    private static MockHttpServer.MockHttpServerResponse createFakeZipResponse(File zip)
            throws IOException, FileNotFoundException {
        MockHttpServer.MockHttpServerResponse engineZipResponse = new MockHttpServer.MockHttpServerResponse();
        engineZipResponse.setMockResponseContentType("application/zip");
        FileInputStream fis = new FileInputStream(zip);
        byte[] zipBytes = IOUtils.toByteArray(fis);
        engineZipResponse.setMockResponseContent(zipBytes);
        return engineZipResponse;
    }

    private static File createFakeEngineZip(String ivyVersion) throws IOException, ZipException {
        File zipDir = createFakeEngineDir(ivyVersion);
        File zipFile = new File(zipDir, "fake.zip");
        ZipFile zip = new ZipFile(zipFile);
        zip.createZipFileFromFolder(new File(zipDir, "plugins"), new ZipParameters(), false, 0);
        return zipFile;
    }

    private static File createFakeEngineDir(String ivyVersion) throws IOException {
        File fakeDir = createTempDir("fake");
        File fakeLibToDeclareVersion = new File(fakeDir, getFakeLibraryPath(ivyVersion));
        fakeLibToDeclareVersion.getParentFile().mkdirs();
        fakeLibToDeclareVersion.createNewFile();
        return fakeDir;
    }

    private static File createTempDir(String namePrefix) throws IOException {
        File tmpDir = Files.createTempDirectory(namePrefix).toFile();
        tmpDir.deleteOnExit();
        return tmpDir;
    }

    @Test
    public void testEngineDownload_alreadyInstalledVersionWithinRange() throws Exception {
        final String version = "7.1.0";
        mojo.engineDirectory = createFakeEngineDir(version);
        assertThat(mojo.engineDirectory).isDirectory();
        assertThat(new File(mojo.engineDirectory, getFakeLibraryPath(version))).exists();

        mojo.ivyVersion = "[7.0.0,8.0.0)";
        mojo.autoInstallEngine = true;
        mojo.engineDownloadUrl = new MockUp<java.net.URL>() {
            @Mock(maxInvocations = 0)
            public String toExternalForm() {
                return null;
            }

            @Mock(maxInvocations = 0)
            public InputStream openStream() {
                return null;
            }
        }.getMockInstance();

        mojo.execute();
        assertThat(mojo.engineDirectory.listFiles()).isNotEmpty();
        assertThat(new File(mojo.engineDirectory, getFakeLibraryPath(version))).exists();
    }

    @Test
    public void testEngineDownload_alreadyInstalledVersionTooOld() throws Exception {
        final String outdatedVersion = "6.5.1";
        mojo.engineDirectory = createFakeEngineDir(outdatedVersion);
        assertThat(mojo.engineDirectory).isDirectory();
        assertThat(new File(mojo.engineDirectory, getFakeLibraryPath(outdatedVersion))).exists();

        mojo.ivyVersion = "[7.0.0,8.0.0)";
        mojo.autoInstallEngine = true;
        final String downloadVersion = "7.2.0";
        mojo.engineDownloadUrl = new MockedIvyEngineDownloadUrl(downloadVersion).getMockInstance();

        mojo.execute();
        assertThat(mojo.engineDirectory.listFiles()).isNotEmpty();
        assertThat(new File(mojo.engineDirectory, getFakeLibraryPath(outdatedVersion))).doesNotExist();
        assertThat(new File(mojo.engineDirectory, getFakeLibraryPath(downloadVersion))).exists();
    }

    @Test
    public void testEngineDownload_ifNotExisting() throws Exception {
        mojo.engineDirectory = createTempDir("tmpEngine");
        assertThat(mojo.engineDirectory).isDirectory();
        assertThat(mojo.engineDirectory.listFiles()).isEmpty();

        mojo.autoInstallEngine = true;
        mojo.engineDownloadUrl = new MockedIvyEngineDownloadUrl(mojo.ivyVersion).getMockInstance();

        mojo.execute();
        assertThat(mojo.engineDirectory.listFiles()).isNotEmpty();
    }

    @Test
    public void testEngineDownload_existingTmpFileNotOverwritten() throws Exception {
        mojo.engineDirectory = createTempDir("tmpEngine");

        File alreadyExistingFile = new File(mojo.getDownloadDirectory(),
                MockedIvyEngineDownloadUrl.ENGINE_FILE_NAME);
        alreadyExistingFile.createNewFile();

        mojo.autoInstallEngine = true;
        mojo.engineDownloadUrl = new MockedIvyEngineDownloadUrl(mojo.ivyVersion).getMockInstance();

        mojo.execute();

        assertThat(alreadyExistingFile).exists();
    }

    @Test
    public void testEngineDownload_validatesDownloadedVersion() throws Exception {
        mojo.engineDirectory = createTempDir("tmpEngine");
        mojo.autoInstallEngine = true;
        mojo.ivyVersion = "9999.0.0";
        mojo.engineDownloadUrl = new MockedIvyEngineDownloadUrl(AbstractEngineMojo.DEFAULT_VERSION)
                .getMockInstance();

        try {
            mojo.execute();
            failBecauseExceptionWasNotThrown(MojoExecutionException.class);
        } catch (MojoExecutionException ex) {
            assertThat(ex).hasMessageStartingWith("Automatic installation of an ivyEngine failed.");
        }
    }

    @Test
    public void testEngineDownload_canDisableAutoDownload() throws Exception {
        mojo.engineDirectory = createTempDir("tmpEngine");
        mojo.autoInstallEngine = false;

        try {
            mojo.execute();
            failBecauseExceptionWasNotThrown(MojoExecutionException.class);
        } catch (MojoExecutionException ex) {
            assertThat(ex).hasMessageContaining("no valid ivy Engine is available");
        }
    }

    private static class MockedIvyEngineDownloadUrl extends MockUp<java.net.URL> {
        private static final String ENGINE_FILE_NAME = "fakeEngine.zip";
        private String ivyVersion;

        private MockedIvyEngineDownloadUrl(String ivyVersion) {
            this.ivyVersion = ivyVersion;
        }

        @Mock
        public InputStream openStream() {
            try {
                return new FileInputStream(createFakeEngineZip(ivyVersion));
            } catch (Exception ex) {
                fail("Mock URL error", ex);
                return null;
            }
        }

        @Mock
        public String toExternalForm() {
            return "http://localhost/" + ENGINE_FILE_NAME;
        }
    }

    @Test
    public void testEngineLinkFinder_absolute() throws Exception {
        mojo.ivyVersion = "6.5.1";
        mojo.osArchitecture = "Windows_x86";
        assertThat(findLink(
                "<a href=\"http://developer.axonivy.com/download/6.5.1/AxonIvyEngine6.5.1.46949_Windows_x86.zip\">the latest engine</a>"))
                        .isEqualTo(
                                "http://developer.axonivy.com/download/6.5.1/AxonIvyEngine6.5.1.46949_Windows_x86.zip");
    }

    @Test
    public void testEngineLinkFinder_relative() throws Exception {
        mojo.ivyVersion = "6.5.1";
        mojo.osArchitecture = "Windows_x86";
        mojo.engineListPageUrl = new URL("http://localhost/");
        assertThat(findLink("<a href=\"6.5.1/AxonIvyEngine6.5.1.46949_Windows_x86.zip\">the latest engine</a>"))
                .isEqualTo("http://localhost/6.5.1/AxonIvyEngine6.5.1.46949_Windows_x86.zip");
    }

    @Test
    public void testEngineLinkFinder_sprintVersionQualifier() throws Exception {
        mojo.ivyVersion = "6.5.1";
        mojo.osArchitecture = "Windows_x64";
        assertThat(findLink(
                "<a href=\"http://www.ivyteam.ch/downloads/XIVY/Saentis/6.5.1-S2/AxonIvyEngine6.5.1.47245.S2_Windows_x64.zip\">Axon.ivy Engine Windows x64</a>"))
                        .isEqualTo(
                                "http://www.ivyteam.ch/downloads/XIVY/Saentis/6.5.1-S2/AxonIvyEngine6.5.1.47245.S2_Windows_x64.zip");
    }

    @Test
    public void testEngineLinkFinder_wrongVersion() throws Exception {
        mojo.ivyVersion = "6.5.1";
        mojo.osArchitecture = "Windows_x86";
        try {
            findLink("<a href=\"6.2.0/AxonIvyEngine6.2.0.46949_Windows_x86.zip\">the latest engine</a>");
            failBecauseExceptionWasNotThrown(MojoExecutionException.class);
        } catch (MojoExecutionException ex) {
            assertThat(ex).hasMessageStartingWith("Could not find a link to engine for version '6.5.1'");
        }
    }

    @Test
    public void testEngineLinkFinder_wrongArchitecture() throws Exception {
        mojo.ivyVersion = "6.5.1";
        mojo.osArchitecture = "Linux_x86";
        try {
            findLink("<a href=\"6.5.1/AxonIvyEngine6.5.1.46949_Windows_x86.zip\">the latest engine</a>");
            failBecauseExceptionWasNotThrown(MojoExecutionException.class);
        } catch (MojoExecutionException ex) {
            assertThat(ex).hasMessageStartingWith("Could not find a link to engine for version '6.5.1'");
        }
    }

    @Test
    public void testEngineLinkFinder_multipleLinks() throws Exception {
        mojo.ivyVersion = "6.5.1";
        mojo.osArchitecture = "Linux_x86";
        mojo.engineListPageUrl = new URL("http://localhost/");

        assertThat(findLink("<a href=\"6.5.1/AxonIvyEngine6.5.1.46949_Windows_x86.zip\">the latest engine</a>" // windows
                + "<a href=\"6.5.1/AxonIvyEngine6.5.1.46949_Linux_x86.zip\">the latest engine</a>")) // linux
                        .isEqualTo("http://localhost/6.5.1/AxonIvyEngine6.5.1.46949_Linux_x86.zip");
    }

    private String findLink(String html) throws MojoExecutionException, MalformedURLException {
        EngineDownloader engineDownloader = mojo.new EngineDownloader();
        return engineDownloader.findEngineDownloadUrl(IOUtils.toInputStream(html)).toExternalForm();
    }

    @Test
    public void testDefaultListPage_isAvailable() throws Exception {
        if (Boolean.parseBoolean(System.getProperty("skip.public.download.test", Boolean.FALSE.toString()))) {
            mojo.getLog().warn(
                    "SKIPPING test 'testDefaultListPage_isAvailable'. As property 'skip.public.download.test' is set.");
            return;
        }

        EngineDownloader engineDownloader = mojo.new EngineDownloader();
        String engineUrl = engineDownloader.findEngineDownloadUrl(mojo.engineListPageUrl.openStream())
                .toExternalForm();
        assertThat(engineUrl).as("The default engine list page url '" + mojo.engineListPageUrl.toExternalForm()
                + "' " + "must provide an engine for the current default engine version '" + mojo.ivyVersion + "'.")
                .contains(mojo.ivyVersion);
    }

    @Test
    public void testIvyVersion_mustMatchMinimalPluginVersion() {
        mojo.ivyVersion = "5.1.0";
        try {
            mojo.execute();
            failBecauseExceptionWasNotThrown(MojoExecutionException.class);
        } catch (MojoExecutionException ex) {
            assertThat(ex).hasMessageContaining("'5.1.0' is lower than the minimal compatible version");
        }
    }

    @Test
    public void testZipFileEngineVersionParser() {
        assertThat(InstallEngineMojo.ivyEngineVersionOfZip("AxonIvyEngine6.1.1.51869_Linux_x64.zip"))
                .isEqualTo("6.1.1");
        assertThat(InstallEngineMojo.ivyEngineVersionOfZip("AxonIvyEngine6.2_Windows_x64.zip")).isEqualTo("6.2");
        assertThat(InstallEngineMojo
                .ivyEngineVersionOfZip("AxonIvyDesigner6.1.1-SNAPSHOT.51869-win32.win32.x86_64.zip"))
                        .isEqualTo("6.1.1");
        assertThat(InstallEngineMojo.ivyEngineVersionOfZip("AxonIvyEngine_Linux_x64.zip"))
                .isEqualTo("AxonIvyEngine_Linux_x64.zip"); // do not return null!
    }

    private static String getFakeLibraryPath(final String version) {
        return "plugins/" + EngineVersionEvaluator.LIBRARY_ID + "_" + version + ".51869.jar";
    }

}