org.jenkinsci.plugins.workflow.cps.SnippetizerTest.java Source code

Java tutorial

Introduction

Here is the source code for org.jenkinsci.plugins.workflow.cps.SnippetizerTest.java

Source

/*
 * The MIT License
 *
 * Copyright 2014 Jesse Glick.
 *
 * 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 org.jenkinsci.plugins.workflow.cps;

import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequestSettings;
import com.gargoylesoftware.htmlunit.WebResponse;
import groovy.lang.GroovyObjectSupport;
import groovy.lang.GroovyShell;
import hudson.model.BooleanParameterDefinition;
import hudson.model.BooleanParameterValue;
import hudson.model.FreeStyleProject;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.StringParameterDefinition;
import hudson.model.StringParameterValue;
import hudson.tasks.ArtifactArchiver;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.apache.commons.httpclient.NameValuePair;
import static org.hamcrest.CoreMatchers.*;
import org.jenkinsci.plugins.workflow.steps.CatchErrorStep;
import org.jenkinsci.plugins.workflow.steps.CoreStep;
import org.jenkinsci.plugins.workflow.steps.EchoStep;
import org.jenkinsci.plugins.workflow.steps.PwdStep;
import org.jenkinsci.plugins.workflow.steps.Step;
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
import org.jenkinsci.plugins.workflow.structs.DescribableHelper;
import org.jenkinsci.plugins.workflow.support.steps.ExecutorStep;
import org.jenkinsci.plugins.workflow.support.steps.StageStep;
import org.jenkinsci.plugins.workflow.support.steps.WorkspaceStep;
import org.jenkinsci.plugins.workflow.support.steps.build.BuildTriggerStep;
import org.jenkinsci.plugins.workflow.support.steps.input.InputStep;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.jvnet.hudson.test.Email;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockFolder;

public class SnippetizerTest {

    @ClassRule
    public static JenkinsRule r = new JenkinsRule();

    private static final Logger logger = Logger.getLogger(DescribableHelper.class.getName());

    @BeforeClass
    public static void logging() {
        logger.setLevel(Level.ALL);
        Handler handler = new ConsoleHandler();
        handler.setLevel(Level.ALL);
        logger.addHandler(handler);
    }

    @Test
    public void basics() throws Exception {
        assertRoundTrip(new EchoStep("hello world"), "echo 'hello world'");
        StageStep s = new StageStep("Build");
        assertRoundTrip(s, "stage 'Build'");
        s.concurrency = 1;
        assertRoundTrip(s, "stage concurrency: 1, name: 'Build'");
    }

    @Email("https://groups.google.com/forum/#!topicsearchin/jenkinsci-users/workflow/jenkinsci-users/DJ15tkEQPw0")
    @Test
    public void noArgStep() throws Exception {
        assertRoundTrip(new PwdStep(), "pwd()");
    }

    @Test
    public void coreStep() throws Exception {
        ArtifactArchiver aa = new ArtifactArchiver("x.jar");
        aa.setAllowEmptyArchive(true);
        assertRoundTrip(new CoreStep(aa),
                "step([$class: 'ArtifactArchiver', allowEmptyArchive: true, artifacts: 'x.jar'])");
    }

    @Test
    public void coreStep2() throws Exception {
        assertRoundTrip(new CoreStep(new ArtifactArchiver("x.jar")),
                "step([$class: 'ArtifactArchiver', artifacts: 'x.jar'])");
    }

    @Test
    public void blockSteps() throws Exception {
        assertRoundTrip(new ExecutorStep(null), "node {\n    // some block\n}");
        assertRoundTrip(new ExecutorStep("linux"), "node('linux') {\n    // some block\n}");
        assertRoundTrip(new WorkspaceStep(null), "ws {\n    // some block\n}");
        assertRoundTrip(new WorkspaceStep("loc"), "ws('loc') {\n    // some block\n}");
    }

    @Test
    public void escapes() throws Exception {
        assertRoundTrip(new EchoStep("Bob's message \\/ here"), "echo 'Bob\\'s message \\\\/ here'");
    }

    @Test
    public void multilineStrings() throws Exception {
        assertRoundTrip(new EchoStep("echo hello\necho 1/2 way\necho goodbye"),
                "echo '''echo hello\necho 1/2 way\necho goodbye'''");
    }

    @Test
    public void buildTriggerStep() throws Exception {
        BuildTriggerStep step = new BuildTriggerStep("downstream");
        assertRoundTrip(step, "build 'downstream'");
        step.setParameters(Arrays.asList(new StringParameterValue("branch", "default"),
                new BooleanParameterValue("correct", true)));
        assertRoundTrip(step,
                "build job: 'downstream', parameters: [[$class: 'StringParameterValue', name: 'branch', value: 'default'], [$class: 'BooleanParameterValue', name: 'correct', value: true]]");
    }

    @Issue("JENKINS-25779")
    @Test
    public void defaultValues() throws Exception {
        assertRoundTrip(new InputStep("Ready?"), "input 'Ready?'");
    }

    private static void assertRoundTrip(Step step, String expected) throws Exception {
        assertEquals(expected, Snippetizer.object2Groovy(step));
        GroovyShell shell = new GroovyShell(r.jenkins.getPluginManager().uberClassLoader);
        final StepDescriptor desc = step.getDescriptor();
        shell.setVariable("steps", new GroovyObjectSupport() {
            @Override
            public Object invokeMethod(String name, Object args) {
                if (name.equals(desc.getFunctionName())) {
                    try {
                        return desc.newInstance(DSL.parseArgs(desc, args).namedArgs);
                    } catch (RuntimeException x) {
                        throw x;
                    } catch (Exception x) {
                        throw new RuntimeException(x);
                    }
                } else {
                    return super.invokeMethod(name, args);
                }
            }
        });
        Step actual = (Step) shell.evaluate("steps." + expected);
        r.assertEqualDataBoundBeans(step, actual);
    }

    @Test
    public void generateSnippet() throws Exception {
        assertGenerateSnippet("{'stapler-class':'" + EchoStep.class.getName() + "', 'message':'hello world'}",
                "echo 'hello world'", null);
    }

    @Issue("JENKINS-26093")
    @Test
    public void generateSnippetForBuildTrigger() throws Exception {
        MockFolder d1 = r.createFolder("d1");
        FreeStyleProject ds = d1.createProject(FreeStyleProject.class, "ds");
        MockFolder d2 = r.createFolder("d2");
        // Really this would be a WorkflowJob, but we cannot depend on that here, and it should not matter since we are just looking for Job:
        FreeStyleProject us = d2.createProject(FreeStyleProject.class, "us");
        ds.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("key", ""),
                new BooleanParameterDefinition("flag", false, "")));
        assertGenerateSnippet("{'stapler-class':'" + BuildTriggerStep.class.getName()
                + "', 'job':'../d1/ds', 'parameter': [{'name':'key', 'value':'stuff'}, {'name':'flag', 'value':true}]}",
                "build job: '../d1/ds', parameters: [[$class: 'StringParameterValue', name: 'key', value: 'stuff'], [$class: 'BooleanParameterValue', name: 'flag', value: true]]",
                us.getAbsoluteUrl() + "configure");
    }

    @Issue("JENKINS-29739")
    @Test
    public void generateSnippetForBuildTriggerSingle() throws Exception {
        FreeStyleProject ds = r.jenkins.createProject(FreeStyleProject.class, "ds1");
        FreeStyleProject us = r.jenkins.createProject(FreeStyleProject.class, "us1");
        ds.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("key", "")));
        assertGenerateSnippet(
                "{'stapler-class':'" + BuildTriggerStep.class.getName()
                        + "', 'job':'ds1', 'parameter': {'name':'key', 'value':'stuff'}}",
                "build job: 'ds1', parameters: [[$class: 'StringParameterValue', name: 'key', value: 'stuff']]",
                us.getAbsoluteUrl() + "configure");
    }

    @Test
    public void generateSnippetForBuildTriggerNone() throws Exception {
        FreeStyleProject ds = r.jenkins.createProject(FreeStyleProject.class, "ds0");
        FreeStyleProject us = r.jenkins.createProject(FreeStyleProject.class, "us0");
        assertGenerateSnippet("{'stapler-class':'" + BuildTriggerStep.class.getName() + "', 'job':'ds0'}",
                "build 'ds0'", us.getAbsoluteUrl() + "configure");
    }

    @Test
    public void generateSnippetAdvancedDeprecated() throws Exception {
        assertGenerateSnippet("{'stapler-class':'" + CatchErrorStep.class.getName() + "'}",
                "// " + Messages.Snippetizer_this_step_should_not_normally_be_used_in()
                        + "\ncatchError {\n    // some block\n}",
                null);
    }

    private void assertGenerateSnippet(@Nonnull String json, @Nonnull String responseText,
            @CheckForNull String referer) throws Exception {
        JenkinsRule.WebClient wc = r.createWebClient();
        WebRequestSettings wrs = new WebRequestSettings(new URL(r.getURL(), Snippetizer.GENERATE_URL),
                HttpMethod.POST);
        if (referer != null) {
            wrs.setAdditionalHeader("Referer", referer);
        }
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new NameValuePair("json", json));
        // WebClient.addCrumb *replaces* rather than *adds*:
        params.add(new NameValuePair(r.jenkins.getCrumbIssuer().getDescriptor().getCrumbRequestField(),
                r.jenkins.getCrumbIssuer().getCrumb(null)));
        wrs.setRequestParameters(params);
        WebResponse response = wc.getPage(wrs).getWebResponse();
        assertEquals("text/plain", response.getContentType());
        assertEquals(responseText, response.getContentAsString().trim());
    }

    @Issue("JENKINS-26126")
    @Test
    public void doDslRef() throws Exception {
        JenkinsRule.WebClient wc = r.createWebClient();
        String html = wc.goTo(Snippetizer.DSL_REF_URL).getWebResponse().getContentAsString();
        assertThat("text from LoadStep/help-path.html is included", html,
                containsString("the Groovy file to load"));
        assertThat(
                "SubversionSCM.workspaceUpdater is mentioned as an attribute of a value of GenericSCMStep.delegate",
                html, containsString("workspaceUpdater"));
        assertThat("CheckoutUpdater is mentioned as an option", html, containsString("CheckoutUpdater"));
        assertThat("text from RunWrapperBinder/help.jelly is included", html,
                containsString("may be used to refer to the currently running build"));
        assertThat("content is written to the end", html, containsString("</body></html>"));
    }

    @Issue("JENKINS-26126")
    @Test
    public void doGdsl() throws Exception {
        JenkinsRule.WebClient wc = r.createWebClient();
        String gdsl = wc.goTo(Snippetizer.GDSL_URL, "text/plain").getWebResponse().getContentAsString();
        assertThat("Description is included as doc", gdsl, containsString("Build a job"));
        assertThat("Timeout step appears", gdsl, containsString("name: 'timeout'"));

        // Verify valid groovy syntax.
        GroovyShell shell = new GroovyShell(r.jenkins.getPluginManager().uberClassLoader);
        shell.parse(gdsl);
    }

    @Issue("JENKINS-26126")
    @Test
    public void doDsld() throws Exception {
        JenkinsRule.WebClient wc = r.createWebClient();
        String dsld = wc.goTo(Snippetizer.DSLD_URL, "text/plain").getWebResponse().getContentAsString();
        assertThat("Description is included as doc", dsld, containsString("Build a job"));
        assertThat("Timeout step appears", dsld, containsString("name: 'timeout'"));

        // Verify valid groovy sntax.
        GroovyShell shell = new GroovyShell(r.jenkins.getPluginManager().uberClassLoader);
        shell.parse(dsld);
    }
}