com.sonar.it.scanner.msbuild.TestUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.sonar.it.scanner.msbuild.TestUtils.java

Source

/*
 * Scanner for MSBuild :: Integration Tests
 * Copyright (C) 2016-2016 SonarSource SA
 * mailto:contact AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package com.sonar.it.scanner.msbuild;

import com.sonar.orchestrator.Orchestrator;
import com.sonar.orchestrator.build.ScannerForMSBuild;
import com.sonar.orchestrator.config.Configuration;
import com.sonar.orchestrator.locator.FileLocation;
import com.sonar.orchestrator.locator.Locators;
import com.sonar.orchestrator.locator.MavenLocation;
import com.sonar.orchestrator.util.Command;
import com.sonar.orchestrator.util.CommandExecutor;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.CheckForNull;
import org.apache.commons.io.FileUtils;
import org.junit.rules.TemporaryFolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class TestUtils {
    public static final String MSBUILD_PATH = "msbuild.path";
    private final static Logger LOG = LoggerFactory.getLogger(ScannerMSBuildTest.class);

    public static Path prepareCSharpPlugin(TemporaryFolder temp) {
        Path t;
        try {
            t = temp.newFolder("CSharpPlugin").toPath();
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
        Configuration configuration = Orchestrator.builderEnv().build().getConfiguration();
        Locators locators = new Locators(configuration);
        String pluginVersion = TestSuite.getCSharpVersion();
        MavenLocation csharp = MavenLocation.create("org.sonarsource.dotnet", "sonar-csharp-plugin", pluginVersion);
        Path modifiedCs = t.resolve("modified-chsarp.jar");
        if (locators.copyToFile(csharp, modifiedCs.toFile()) == null) {
            throw new IllegalStateException(
                    "Couldn't locate csharp plugin in the local maven repository: " + csharp);
        }

        String scannerPayloadVersion = getScannerPayloadVersion();

        Path scannerImpl;
        if (scannerPayloadVersion != null) {
            LOG.info("Updating C# plugin ({}) with Scanner For MSBuild implementation ({})", pluginVersion,
                    scannerPayloadVersion);
            MavenLocation scannerImplLocation = MavenLocation.builder()
                    .setGroupId("org.sonarsource.scanner.msbuild").setArtifactId("sonar-scanner-msbuild")
                    .setVersion(scannerPayloadVersion).setClassifier("impl").withPackaging("zip").build();
            scannerImpl = t.resolve("sonar-scanner-msbuild-impl.zip");
            if (locators.copyToFile(scannerImplLocation, scannerImpl.toFile()) == null) {
                throw new IllegalStateException("Unable to find sonar-scanner-msbuild " + scannerPayloadVersion
                        + " in local Maven repository");
            }
        } else {
            // Run locally
            LOG.info("Updating C# plugin ({}) with local build of Scanner For MSBuild implementation",
                    pluginVersion);
            scannerImpl = Paths.get(
                    "../DeploymentArtifacts/CSharpPluginPayload/Release/SonarQube.MSBuild.Runner.Implementation.zip");
        }

        replaceInZip(modifiedCs.toUri(), scannerImpl, "/static/SonarQube.MSBuild.Runner.Implementation.zip");
        return modifiedCs;
    }

    @CheckForNull
    public static String getScannerVersion() {
        Configuration configuration = Orchestrator.builderEnv().build().getConfiguration();
        return configuration.getString("scannerForMSBuild.version");
    }

    public static ScannerForMSBuild newScanner(Path projectDir) {
        String scannerVersion = getScannerVersion();

        if (scannerVersion != null) {
            LOG.info("Using Scanner for MSBuild " + scannerVersion);
            return ScannerForMSBuild.create(projectDir.toFile()).setScannerVersion(scannerVersion);
        } else {
            // run locally
            LOG.info("Using Scanner for MSBuild from the local build");
            Path scannerZip = Paths
                    .get("../DeploymentArtifacts/BuildAgentPayload/Release/SonarQube.Scanner.MSBuild.zip");
            return ScannerForMSBuild.create(projectDir.toFile())
                    .setScannerLocation(FileLocation.of(scannerZip.toFile()));
        }
    }

    /**
     * Try to get version of the Scanner for MSBuild to embed in the C# plugin (use as payload).
     * If no version is found, null is returned.
     */
    @CheckForNull
    public static String getScannerPayloadVersion() {
        Configuration configuration = Orchestrator.builderEnv().build().getConfiguration();
        return configuration.getString("scannerForMSBuildPayload.version");
    }

    public static Path getCustomRoslynPlugin() {
        Path customPluginDir = Paths.get("").resolve("analyzers");

        DirectoryStream.Filter<Path> jarFilter = new DirectoryStream.Filter<Path>() {
            public boolean accept(Path file) throws IOException {
                return Files.isRegularFile(file) && file.toString().endsWith(".jar");
            }
        };
        List<Path> jars = new ArrayList<>();
        try {
            Files.newDirectoryStream(customPluginDir, jarFilter).forEach(p -> jars.add(p));
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
        if (jars.isEmpty()) {
            throw new IllegalStateException("No jars found in " + customPluginDir.toString());
        } else if (jars.size() > 1) {
            throw new IllegalStateException("Several jars found in " + customPluginDir.toString());
        }

        return jars.get(0);
    }

    public static Path projectDir(TemporaryFolder temp, String projectName) throws IOException {
        Path projectDir = Paths.get("projects").resolve(projectName);
        FileUtils.deleteDirectory(new File(temp.getRoot(), projectName));
        Path tmpProjectDir = temp.newFolder(projectName).toPath();
        FileUtils.copyDirectory(projectDir.toFile(), tmpProjectDir.toFile());
        return tmpProjectDir;
    }

    public static void runMSBuild(Orchestrator orch, Path projectDir, String... arguments) {
        String msBuildPathStr = orch.getConfiguration().getString(MSBUILD_PATH,
                "C:\\Program Files (x86)\\MSBuild\\14.0\\bin\\MSBuild.exe");
        Path msBuildPath = Paths.get(msBuildPathStr).toAbsolutePath();
        if (!Files.exists(msBuildPath)) {
            throw new IllegalStateException("Unable to find MSBuild at " + msBuildPath.toString()
                    + ". Please configure property '" + MSBUILD_PATH + "'");
        }

        int r = CommandExecutor.create().execute(
                Command.create(msBuildPath.toString()).addArguments(arguments).setDirectory(projectDir.toFile()),
                60 * 1000);
        assertThat(r).isEqualTo(0);
    }

    private static void replaceInZip(URI zipUri, Path src, String dest) {
        Map<String, String> env = new HashMap<>();
        env.put("create", "true");
        // locate file system by using the syntax
        // defined in java.net.JarURLConnection
        URI uri = URI.create("jar:" + zipUri);
        try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
            Path pathInZipfile = zipfs.getPath(dest);
            LOG.info("Replacing the file " + pathInZipfile + " in the zip " + zipUri + " with " + src);
            Files.copy(src, pathInZipfile, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    protected static String parseVersion() {
        try {
            String content = FileUtils.readFileToString(new File("../AssemblyInfo.Shared.cs"),
                    StandardCharsets.UTF_8);
            return parseVersion(content);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    private static String parseVersion(String content) {
        Pattern p = Pattern.compile("(?s).*\\[assembly: AssemblyVersion\\(\"(.*?)\"\\)].*");
        Matcher matcher = p.matcher(content);
        if (matcher.matches()) {
            return matcher.group(1);
        }
        throw new IllegalStateException("Unable to parse version from " + content);
    }
}