hudson.tasks.AntTest.java Source code

Java tutorial

Introduction

Here is the source code for hudson.tasks.AntTest.java

Source

/*
 * The MIT License
 * 
 * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Yahoo! Inc.
 * 
 * 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 hudson.tasks;

import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.Functions;
import hudson.matrix.Axis;
import hudson.matrix.AxisList;
import hudson.matrix.MatrixProject;
import hudson.matrix.MatrixRun;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.PasswordParameterDefinition;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.StringParameterDefinition;
import hudson.tasks.Ant.AntInstallation;
import hudson.tasks.Ant.AntInstallation.DescriptorImpl;
import hudson.tasks.Ant.AntInstaller;
import hudson.tools.InstallSourceProperty;
import hudson.tools.ToolProperty;
import hudson.tools.ToolPropertyDescriptor;
import hudson.util.DescribableList;
import hudson.util.VersionNumber;
import java.io.IOException;
import java.io.StringWriter;
import jenkins.model.Jenkins;
import org.apache.commons.lang.SystemUtils;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.ExtractResourceSCM;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.SingleFileSCM;
import org.jvnet.hudson.test.ToolInstallations;

/**
 * @author Kohsuke Kawaguchi
 */
public class AntTest {

    @Rule
    public JenkinsRule r = new JenkinsRule();
    @Rule
    public TemporaryFolder tmp = new TemporaryFolder();

    /**
     * Tests the round-tripping of the configuration.
     */
    @Test
    public void testConfigRoundtrip() throws Exception {
        FreeStyleProject p = r.createFreeStyleProject();
        p.getBuildersList().add(new Ant("a", null, "-b", "c.xml", "d=e"));

        WebClient webClient = r.createWebClient();
        HtmlPage page = webClient.getPage(p, "configure");

        HtmlForm form = page.getFormByName("config");
        r.submit(form);

        Ant a = p.getBuildersList().get(Ant.class);
        assertNotNull(a);
        assertEquals("a", a.getTargets());
        assertNull(a.getAnt());
        assertEquals("-b", a.getAntOpts());
        assertEquals("c.xml", a.getBuildFile());
        assertEquals("d=e", a.getProperties());
    }

    /**
     * Simulates the addition of the new Ant via UI and makes sure it works.
     */
    @Test
    public void testGlobalConfigAjax() throws Exception {
        HtmlPage p = Jenkins.getVersion().toString().startsWith("2") ? r.createWebClient().goTo("configureTools")
                : r.createWebClient().goTo("configure");
        HtmlForm f = p.getFormByName("config");
        HtmlButton b = r.getButtonByCaption(f, "Add Ant");
        b.click();
        r.findPreviousInputElement(b, "name").setValueAttribute("myAnt");
        r.findPreviousInputElement(b, "home").setValueAttribute("/tmp/foo");
        r.submit(f);
        verify();

        // another submission and verify it survives a roundtrip
        p = r.createWebClient().goTo("configure");
        f = p.getFormByName("config");
        r.submit(f);
        verify();
    }

    private void verify() throws Exception {
        AntInstallation[] l = r.get(DescriptorImpl.class).getInstallations();
        assertEquals(1, l.length);
        r.assertEqualBeans(l[0], new AntInstallation("myAnt", "/tmp/foo", JenkinsRule.NO_PROPERTIES), "name,home");

        // by default we should get the auto installer
        DescribableList<ToolProperty<?>, ToolPropertyDescriptor> props = l[0].getProperties();
        assertEquals(1, props.size());
        InstallSourceProperty isp = props.get(InstallSourceProperty.class);
        assertEquals(1, isp.installers.size());
        assertNotNull(isp.installers.get(AntInstaller.class));
    }

    @Test
    public void testSensitiveParameters() throws Exception {
        FreeStyleProject project = r.createFreeStyleProject();
        ParametersDefinitionProperty pdb = new ParametersDefinitionProperty(
                new StringParameterDefinition("string", "defaultValue", "string description"),
                new PasswordParameterDefinition("password", "12345", "password description"),
                new StringParameterDefinition("string2", "Value2", "string description"));
        project.addProperty(pdb);
        project.setScm(new SingleFileSCM("build.xml",
                hudson.tasks._ant.AntTargetAnnotationTest.class.getResource("simple-build.xml")));

        project.getBuildersList().add(new Ant("foo", null, null, null, null));

        FreeStyleBuild build = project.scheduleBuild2(0).get();
        // Due to bug JENKINS-28790. Password should not be shown but it is.
        if (SystemUtils.IS_OS_WINDOWS && Jenkins.getVersion().isOlderThan(new VersionNumber("1.653"))) {
            r.assertLogContains("-Dpassword=12345", build);
        } else {
            r.assertLogNotContains("-Dpassword=12345", build);
        }
    }

    @Test
    public void testParameterExpansion() throws Exception {
        if (!SystemUtils.IS_OS_WINDOWS) {
            String antName = configureDefaultAnt().getName();
            // Use a matrix project so we have env stuff via builtins, parameters and matrix axis.
            MatrixProject project = r.createProject(MatrixProject.class, "test project");// Space in name
            project.setAxes(new AxisList(new Axis("AX", "is")));
            project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", "bar", "")));
            project.setScm(new ExtractResourceSCM(getClass().getResource("ant-job.zip")));
            project.getBuildersList().add(new Ant("", antName, null, null,
                    "vNUM=$BUILD_NUMBER\nvID=$BUILD_ID\nvJOB=$JOB_NAME\nvTAG=$BUILD_TAG\nvEXEC=$EXECUTOR_NUMBER\n"
                            + "vNODE=$NODE_NAME\nvLAB=$NODE_LABELS\nvJAV=$JAVA_HOME\nvWS=$WORKSPACE\nvHURL=$HUDSON_URL\n"
                            + "vBURL=$BUILD_URL\nvJURL=$JOB_URL\nvHH=$HUDSON_HOME\nvJH=$JENKINS_HOME\nvFOO=$FOO\nvAX=$AX"));
            r.assertBuildStatusSuccess(project.scheduleBuild2(0));
            MatrixRun build = project.getItem("AX=is").getLastBuild();
            String log = JenkinsRule.getLog(build);
            assertTrue("Missing $BUILD_NUMBER: " + log, log.contains("vNUM=1"));
            // TODO 1.597+: assertTrue("Missing $BUILD_ID: " + log, log.contains("vID=1"));
            assertTrue("Missing $JOB_NAME: " + log, log.contains(project.getName()));
            // Odd build tag, but it's constructed with getParent().getName() and the parent is the
            // matrix configuration, not the project.. if matrix build tag ever changes, update
            // expected value here:
            assertTrue("Missing $BUILD_TAG: " + log, log.contains("vTAG=jenkins-test project-AX\\=is-1"));
            assertTrue("Missing $EXECUTOR_NUMBER: " + log, log.matches("(?s).*vEXEC=\\d.*"));
            // $NODE_NAME is expected to be empty when running on master.. not checking.
            assertTrue("Missing $NODE_LABELS: " + log, log.contains("vLAB=master"));
            assertTrue("Missing $JAVA_HOME: " + log, log.matches("(?s).*vJH=[^\\r\\n].*"));
            assertTrue("Missing $WORKSPACE: " + log, log.matches("(?s).*vWS=[^\\r\\n].*"));
            assertTrue("Missing $HUDSON_URL: " + log, log.contains("vHURL=http"));
            assertTrue("Missing $BUILD_URL: " + log, log.contains("vBURL=http"));
            assertTrue("Missing $JOB_URL: " + log, log.contains("vJURL=http"));
            assertTrue("Missing $HUDSON_HOME: " + log, log.matches("(?s).*vHH=[^\\r\\n].*"));
            assertTrue("Missing $JENKINS_HOME: " + log, log.matches("(?s).*vJH=[^\\r\\n].*"));
            assertTrue("Missing build parameter $FOO: " + log, log.contains("vFOO=bar"));
            assertTrue("Missing matrix axis $AX: " + log, log.contains("vAX=is"));
        }
    }

    private AntInstallation configureDefaultAnt() throws Exception {
        return ToolInstallations.configureDefaultAnt(tmp);
    }

    @Test
    public void testParameterExpansionByShell() throws Exception {
        String antName = configureDefaultAnt().getName();
        FreeStyleProject project = r.createFreeStyleProject();
        project.setScm(new ExtractResourceSCM(getClass().getResource("ant-job.zip")));
        String homeVar = Functions.isWindows() ? "%HOME%" : "$HOME";
        project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("vFOO", homeVar, ""),
                new StringParameterDefinition("vBAR", "Home sweet " + homeVar + ".", "")));
        project.getBuildersList()
                .add(new Ant("", antName, null, null, "vHOME=" + homeVar + "\nvFOOHOME=Foo " + homeVar + "\n"));
        FreeStyleBuild build = project.scheduleBuild2(0).get();
        r.assertBuildStatusSuccess(build);
        String log = JenkinsRule.getLog(build);
        if (!Functions.isWindows())
            homeVar = "\\" + homeVar; // Regex escape for $
        assertTrue("Missing simple HOME parameter: " + log, log.matches("(?s).*vFOO=(?!" + homeVar + ").*"));
        assertTrue("Missing HOME parameter with other text: " + log,
                log.matches("(?s).*vBAR=Home sweet (?!" + homeVar + ")[^\\r\\n]*\\..*"));
        assertTrue("Missing HOME ant property: " + log, log.matches("(?s).*vHOME=(?!" + homeVar + ").*"));
        assertTrue("Missing HOME ant property with other text: " + log,
                log.matches("(?s).*vFOOHOME=Foo (?!" + homeVar + ").*"));
    }

    @Issue("JENKINS-7108")
    @Test
    public void testEscapeXmlInParameters() throws Exception {
        String antName = configureDefaultAnt().getName();
        FreeStyleProject project = r.createFreeStyleProject();
        project.setScm(new ExtractResourceSCM(getClass().getResource("ant-job.zip")));
        project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("vFOO", "<xml/>", "")));
        project.getBuildersList().add(new Ant("", antName, null, null, "vBAR=<xml/>\n"));
        FreeStyleBuild build = project.scheduleBuild2(0).get();
        r.assertBuildStatusSuccess(build);
        r.assertLogContains("vFOO=<xml/>", build);
        r.assertLogContains("vBAR=<xml/>", build);
    }

    @Test
    public void invokeCustomTargetTest() throws Exception {
        FreeStyleProject project = createSimpleAntProject("clean compile", null, null, null);

        FreeStyleBuild build = project.scheduleBuild2(0).get();

        assertEquals(Result.SUCCESS, build.getResult());

        assertHtmlLogContains(build, "<b class=ant-target>clean</b>");
        assertHtmlLogContains(build, "<b class=ant-target>compile</b>");
        assertHtmlLogNotContains(build, "<b class=ant-target>jar</b>");
        assertHtmlLogNotContains(build, "<b class=ant-target>run</b>");
        assertHtmlLogNotContains(build, "<b class=ant-target>main</b>");
    }

    @Test
    public void invokeDefaultTargetTest() throws Exception {
        FreeStyleProject project = createSimpleAntProject("", null, null, null);

        FreeStyleBuild build = project.scheduleBuild2(0).get();

        assertEquals(Result.SUCCESS, build.getResult());

        assertHtmlLogContains(build, "<b class=ant-target>clean</b>");
        assertHtmlLogContains(build, "<b class=ant-target>compile</b>");
        assertHtmlLogContains(build, "<b class=ant-target>jar</b>");
        assertHtmlLogContains(build, "<b class=ant-target>run</b>");
        assertHtmlLogContains(build, "<b class=ant-target>main</b>");
    }

    @Test
    public void jenkinsEnvVarsFromBuildScriptTest() throws Exception {
        String testPropertyValue = "FooBar";

        FreeStyleProject project = createSimpleAntProject("", null, "build-properties.xml",
                "testProperty=" + testPropertyValue);

        FreeStyleBuild build = project.scheduleBuild2(0).get();

        assertEquals(Result.SUCCESS, build.getResult());
        r.assertLogContains("[echo] My test property: FooBar", build);
    }

    @Test
    public void optionsInTargetFieldTest() throws Exception {
        FreeStyleProject project = createSimpleAntProject("-projecthelp", null, null, null);

        FreeStyleBuild build = project.scheduleBuild2(0).get();

        assertEquals(Result.SUCCESS, build.getResult());
        r.assertLogContains("Default target: main", build);
    }

    @Test
    public void customBuildFileTest() throws Exception {
        FreeStyleProject project = createSimpleAntProject("", null, "build-custom-name.xml", null);

        FreeStyleBuild build = project.scheduleBuild2(0).get();

        assertEquals(Result.SUCCESS, build.getResult());

        assertHtmlLogContains(build, "<b class=ant-target>clean-custom</b>");
        assertHtmlLogContains(build, "<b class=ant-target>compile-custom</b>");
        assertHtmlLogContains(build, "<b class=ant-target>jar-custom</b>");
        assertHtmlLogContains(build, "<b class=ant-target>run-custom</b>");
        assertHtmlLogContains(build, "<b class=ant-target>main-custom</b>");
    }

    @Test
    public void unexistingCustomBuildFileTest() throws Exception {
        FreeStyleProject project = createSimpleAntProject("", null, "unexsisting.xml", null);

        FreeStyleBuild build = project.scheduleBuild2(0).get();

        assertEquals(Result.FAILURE, build.getResult());
        r.assertLogContains("Unable to find build script", build);
    }

    @Test
    @Issue("JENKINS-33712")
    public void emptyParameterTest() throws Exception {
        FreeStyleProject project = createSimpleAntProject("", null, null, "property=");

        FreeStyleBuild build = project.scheduleBuild2(0).get();

        assertEquals(Result.SUCCESS, build.getResult());
    }

    /**
     * Creates a FreeStyleProject with an Ant build step with parameters passed as parameter.
     * The Project to use is always the same (sample-helloworld-ant.zip)
     * 
     * @param targets targets to invoke
     * @param (optional) ops ant ops to use
     * @param (optional) buildFile build file to use. 
     * @param (optional) properties properties to pass to the build
     * 
     * @return a FreeStyleProject with an Ant build step
     * @throws Exception
     */
    private FreeStyleProject createSimpleAntProject(String targets, String ops, String buildFile, String properties)
            throws Exception {
        if (targets == null) {
            fail("Ant targets must be different from null");
        }
        String antName = configureDefaultAnt().getName();
        FreeStyleProject project = r.createFreeStyleProject();
        project.setScm(new ExtractResourceSCM(getClass().getResource("sample-helloworld-ant.zip")));
        project.getBuildersList().add(new Ant(targets, antName, ops, buildFile, properties));
        return project;
    }

    // TODO consider inclusion in JenkinsRule; can use WebClient to obtain /console but is slow and contains other junk
    private static String getHtmlLog(Run<?, ?> build) throws IOException {
        StringWriter w = new StringWriter();
        build.getLogText().writeHtmlTo(0, w);
        return w.toString();
    }

    private static void assertHtmlLogContains(Run<?, ?> build, String text) throws IOException {
        assertThat(getHtmlLog(build), containsString(text));
    }

    private static void assertHtmlLogNotContains(Run<?, ?> build, String text) throws IOException {
        assertThat(getHtmlLog(build), not(containsString(text)));
    }

}