com.piketec.jenkins.plugins.tpt.TptPluginSlave.java Source code

Java tutorial

Introduction

Here is the source code for com.piketec.jenkins.plugins.tpt.TptPluginSlave.java

Source

/*
 * The MIT License (MIT)
 * 
 * Copyright (c) 2018 PikeTec GmbH
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package com.piketec.jenkins.plugins.tpt;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;

import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;

/**
 * Plugin executes a single given TPT test case. Intended to be used in the job started by
 * {@link TptPluginMasterJobExecutor}.
 */
public class TptPluginSlave extends Builder {

    private String exePaths;

    private String tptBindingName;

    private String tptPort;

    private String tptStartUpWaitTime;

    // ----------- Data Binding --------------

    /**
     * 
     * Those arguments are processed and then passed to the TptPluginSlaveExecutor. This class is used
     * as a wrapper
     * 
     * @param exePaths
     *          the paths to the Tpt Executables
     * @param tptBindingName
     *          the binding name used to connect to the TptApi (for the registry)
     * @param tptPort
     *          the port for binding to the TptApi
     * @param tptStartUpWaitTime
     *          the time it should wait before start tpt
     */
    @DataBoundConstructor
    public TptPluginSlave(String exePaths, String tptBindingName, String tptPort, String tptStartUpWaitTime) {
        this.exePaths = exePaths;
        this.tptBindingName = tptBindingName;
        this.tptPort = tptPort;
        this.tptStartUpWaitTime = tptStartUpWaitTime;
    }

    /**
     * @return the given paths to the tpt executable (tpt.exe)
     */
    public String getExePaths() {
        return exePaths;
    }

    /**
     * @return the given bindingname, used to connect to the api.
     */
    public String getTptBindingName() {
        return tptBindingName;
    }

    /**
     * @return the tpt port , used to make the connection to the TptApi
     */
    public String getTptPort() {
        return tptPort;
    }

    /**
     * @return The time waited before trying to get the API handle after starting TPT
     */
    public String getTptStartUpWaitTime() {
        return tptStartUpWaitTime;
    }

    // --------------------------------------------------------------

    /**
     * It collects the necesary data (tpt exe path, tpt Port, tpt bindingname and tpt
     * expandedTptStartupWaitTime) from the environment. Then collects the necesary data from the
     * workload (put by the TptPluginMasterJobExecutor). After collecting all the necesary data it
     * creates a new TptPluginSlaveExecutor and execute it . This method will be called from Jenkins
     * when a build for a slave is scheduled. @see retryableJob. The logic is that the retryableJob
     * schedules builds for the slaves and those builds will be executed here.
     * 
     * @return true if the slave executed successfully its workload.
     */
    @Override
    public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
            throws InterruptedException, IOException {

        TptLogger logger = new TptLogger(listener.getLogger());
        EnvVars environment;
        try {
            environment = build.getEnvironment(launcher.getListener());
        } catch (IOException e) {
            environment = new EnvVars();
            logger.error(e.getLocalizedMessage());
        } catch (InterruptedException e) {
            logger.error(e.getLocalizedMessage());
            return false;
        }
        String[] expandedStringExePaths = environment.expand(exePaths).split("[,;]");
        FilePath[] expandedExePaths = new FilePath[expandedStringExePaths.length];
        for (int i = 0; i < expandedExePaths.length; i++) {
            expandedExePaths[i] = new FilePath(launcher.getChannel(),
                    environment.expand(expandedStringExePaths[i].trim()));
        }
        int expandedTptPort;
        if (tptPort != null && !tptPort.isEmpty()) {
            try {
                expandedTptPort = Integer.parseInt(environment.expand(tptPort));
            } catch (NumberFormatException e) {
                logger.error("The given port " + environment.expand(tptPort) + " is not an integer."
                        + " Using default value.");
                expandedTptPort = DescriptorImpl.getDefaultTptPort();
            }
        } else {
            expandedTptPort = DescriptorImpl.getDefaultTptPort();
        }
        String expandedTptBindingName;
        if (tptBindingName != null && !tptBindingName.isEmpty()) {
            expandedTptBindingName = environment.expand(tptBindingName);
        } else {
            expandedTptBindingName = DescriptorImpl.getDefaultTptBindingName();
        }
        long expandedTptStartupWaitTime;
        if (tptStartUpWaitTime != null && !tptStartUpWaitTime.isEmpty()) {
            try {
                expandedTptStartupWaitTime = Integer.parseInt(environment.expand(tptStartUpWaitTime)) * 1000;
            } catch (NumberFormatException e) {
                logger.error("The given TPT startup waiting time " + environment.expand(tptStartUpWaitTime)
                        + " is not an integer. Using default value.");
                expandedTptStartupWaitTime = DescriptorImpl.getDefaultTptStartUpWaitTime() * 1000;
            }
        } else {
            expandedTptStartupWaitTime = DescriptorImpl.getDefaultTptStartUpWaitTime() * 1000;
        }

        String jobName = build.getProject().getName();
        WorkLoad workloadToDo = WorkLoad.pollWorkload(jobName);
        if (workloadToDo == null) {
            logger.error("Nothing todo. No work package for \"" + jobName + "\" enqueued.");
            return false;
        }

        String fileNameFromWorkload = workloadToDo.getFileName();
        String exeConfigFromWorkload = workloadToDo.getExeConfig();
        String testDataDirFromWorload = workloadToDo.getDataDir();
        String reportDirFromWorkload = workloadToDo.getReportDir();
        List<String> testCasesFromWorkload = workloadToDo.getTestCases();
        String testSetFromWorkload = workloadToDo.getTestSetName();
        AbstractBuild masterId = workloadToDo.getMasterId();
        FilePath masterWorkspace = workloadToDo.getMasterWorkspace();

        logger.info("File Name :               " + fileNameFromWorkload);
        logger.info("Execution Configuration : " + exeConfigFromWorkload);
        logger.info("Test Data directory :     " + testDataDirFromWorload);
        logger.info("Report directory :        " + reportDirFromWorkload);
        logger.info("Test Cases :              " + testCasesFromWorkload);
        if (StringUtils.isNotEmpty(testSetFromWorkload)) {
            logger.info("Test Set :                " + testSetFromWorkload);
        }

        TptPluginSlaveExecutor executor = new TptPluginSlaveExecutor(launcher, build, listener, expandedExePaths,
                expandedTptPort, expandedTptBindingName, new File(fileNameFromWorkload), exeConfigFromWorkload,
                testDataDirFromWorload, reportDirFromWorkload, testCasesFromWorkload, expandedTptStartupWaitTime,
                masterId, testSetFromWorkload, masterWorkspace);

        boolean result = executor.execute();
        if (!result) {
            // reenqueue for new try if job is configured to try multiple times
            WorkLoad.putWorkLoad(jobName, workloadToDo);
        }
        return result;
    }

    @Override
    public DescriptorImpl getDescriptor() {
        return (DescriptorImpl) super.getDescriptor();
    }

    // --------------------------- Descriptor Class -----------------------------------

    /**
     * The Descriptor of TptPluginSlave
     * 
     * @author jkuhnert, PikeTec GmbH
     */
    @Extension
    public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {

        @Override
        public boolean isApplicable(Class<? extends AbstractProject> jobType) {
            // all project types allowed
            return true;
        }

        @Override
        public String getDisplayName() {
            return "Execute TPT tests slave";
        }

        /**
         * @return "${PIKECTEC_TPT_EXE}"
         */
        public static String getDefaultExePaths() {
            return "${" + Utils.TPT_EXE_VAR + "}";
        }

        /**
         * @return "TptApi"
         */
        public static String getDefaultTptBindingName() {
            return Utils.DEFAULT_TPT_BINDING_NAME;
        }

        /**
         * @return "1099"
         */
        public static int getDefaultTptPort() {
            return Utils.DEFAULT_TPT_PORT;
        }

        /**
         * @return "60" (1 min)
         */
        public static int getDefaultTptStartUpWaitTime() {
            return Utils.DEFAULT_STARTUP_WAIT_TIME;
        }

    }

}