/*
* The MIT License
*
* Copyright (c) 2015, CloudBees, 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 com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger;
import com.sonyericsson.hudson.plugins.gerrit.trigger.GerritServer;
import com.sonyericsson.hudson.plugins.gerrit.trigger.PluginImpl;
import com.sonyericsson.hudson.plugins.gerrit.trigger.config.Config;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.Branch;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.CompareType;
import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject;
import com.sonyericsson.hudson.plugins.gerrit.trigger.mock.Setup;
import com.sonyericsson.hudson.plugins.gerrit.trigger.mock.TestUtils;
import com.sonymobile.tools.gerrit.gerritevents.dto.events.PatchsetCreated;
import hudson.model.RootAction;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
import static org.hamcrest.core.AllOf.allOf;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.Is.isA;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
/**
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class WorkflowTest {
/**
* Jenkins rule.
*/
// CS IGNORE VisibilityModifier FOR NEXT 2 LINES. REASON: JenkinsRule.
@Rule
public final JenkinsRule jenkinsRule = new JenkinsRule();
/**
* Trigger test.
* @throws Exception if there is one.
*/
@Test
public void testTriggerWorkflow() throws Exception {
jenkinsRule.jenkins.setCrumbIssuer(null);
MockGerritServer gerritServer = MockGerritServer.get(jenkinsRule);
gerritServer.start();
try {
PatchsetCreated event = Setup.createPatchsetCreated(gerritServer.getName());
WorkflowJob job = createWorkflowJob(event);
PluginImpl.getHandler_().post(event);
// Now wait for the Gerrit server to trigger the workflow build in Jenkins...
TestUtils.waitForBuilds(job, 1);
WorkflowRun run = job.getBuilds().iterator().next();
jenkinsRule.assertLogContains("Gerrit trigger: patchset-created", run);
// Workflow build was triggered successfully. Now lets check make sure the
// gerrit plugin sent a verified notification back to the Gerrit Server...
JSONObject verifiedMessage = gerritServer.waitForNextVerified();
// System.out.println(gerritServer.lastContent);
String message = verifiedMessage.getString("message");
Assert.assertTrue(message.startsWith("Build Successful"));
Assert.assertTrue(message.contains("job/WFJob/1/"));
JSONObject labels = verifiedMessage.getJSONObject("labels");
assertEquals(1, labels.getInt("Verified"));
} finally {
gerritServer.stop();
}
}
/**
* Tests setting a custom URL from a workflow job.
* @throws Exception if there is one.
*/
@Test
public void testWorkflowStepSetsCustomUrl() throws Exception {
jenkinsRule.jenkins.setCrumbIssuer(null);
MockGerritServer gerritServer = MockGerritServer.get(jenkinsRule);
gerritServer.start();
try {
PatchsetCreated event = Setup.createPatchsetCreated(gerritServer.getName());
WorkflowJob job = createWorkflowJob(event, ""
+ "node {\n"
+ " stage 'Build'\n"
+ " setGerritReview customUrl: 'myCustomUrl'\n"
+ "}\n");
PluginImpl.getHandler_().post(event);
// Now wait for the Gerrit server to trigger the workflow build in Jenkins...
TestUtils.waitForBuilds(job, 1);
WorkflowRun run = job.getBuilds().iterator().next();
jenkinsRule.assertLogContains("setGerritReview", run);
// Workflow build was triggered successfully. Now lets check make sure the
// gerrit plugin sent a verified notification back to the Gerrit Server...
JSONObject verifiedMessage = gerritServer.waitForNextVerified();
// System.out.println(gerritServer.lastContent);
String message = verifiedMessage.getString("message");
Assert.assertTrue(message.startsWith("Build Successful"));
Assert.assertTrue(message.contains("myCustomUrl"));
JSONObject labels = verifiedMessage.getJSONObject("labels");
assertEquals(1, labels.getInt("Verified"));
} finally {
gerritServer.stop();
}
}
/**
* Tests setting an unsuccessful message from a workflow job.
* @throws Exception if there is one.
*/
@Test
public void testWorkflowStepSetsUnsuccessfulMessage() throws Exception {
jenkinsRule.jenkins.setCrumbIssuer(null);
MockGerritServer gerritServer = MockGerritServer.get(jenkinsRule);
gerritServer.start();
try {
PatchsetCreated event = Setup.createPatchsetCreated(gerritServer.getName());
WorkflowJob job = createWorkflowJob(event, ""
+ "node {\n"
+ " stage 'Build'\n"
+ " setGerritReview unsuccessfulMessage: 'myMessage'\n"
+ " currentBuild.setResult('FAILURE')\n"
+ "}\n");
PluginImpl.getHandler_().post(event);
// Now wait for the Gerrit server to trigger the workflow build in Jenkins...
TestUtils.waitForBuilds(job, 1);
WorkflowRun run = job.getBuilds().iterator().next();
jenkinsRule.assertLogContains("setGerritReview", run);
// Workflow build was triggered successfully. Now lets check make sure the
// gerrit plugin sent a verified notification back to the Gerrit Server,
// and the message contains the custom message...
JSONObject verifiedMessage = gerritServer.waitForNextVerified();
// System.out.println(gerritServer.lastContent);
String message = verifiedMessage.getString("message");
Assert.assertTrue(message.startsWith("Build Failed"));
Assert.assertTrue(message.contains("myMessage"));
JSONObject labels = verifiedMessage.getJSONObject("labels");
assertEquals(0, labels.getInt("Verified"));
} finally {
gerritServer.stop();
}
}
/**
* Tests setting am unsuccessful message from a successful workflow job.
* @throws Exception if there is one.
*/
@Test
public void testWorkflowStepSetsUnsuccessfulMessageWithSuccessfulBuild() throws Exception {
jenkinsRule.jenkins.setCrumbIssuer(null);
MockGerritServer gerritServer = MockGerritServer.get(jenkinsRule);
gerritServer.start();
try {
PatchsetCreated event = Setup.createPatchsetCreated(gerritServer.getName());
WorkflowJob job = createWorkflowJob(event, ""
+ "node {\n"
+ " stage 'Build'\n"
+ " setGerritReview unsuccessfulMessage: 'myMessage'\n"
+ "}\n");
PluginImpl.getHandler_().post(event);
// Now wait for the Gerrit server to trigger the workflow build in Jenkins...
TestUtils.waitForBuilds(job, 1);
WorkflowRun run = job.getBuilds().iterator().next();
jenkinsRule.assertLogContains("setGerritReview", run);
// Workflow build was triggered successfully. Now lets check make sure the
// gerrit plugin sent a verified notification back to the Gerrit Server,
// and the message does not contain the custom message...
JSONObject verifiedMessage = gerritServer.waitForNextVerified();
// System.out.println(gerritServer.lastContent);
String message = verifiedMessage.getString("message");
Assert.assertTrue(message.startsWith("Build Successful"));
Assert.assertFalse(message.contains("myMessage"));
JSONObject labels = verifiedMessage.getJSONObject("labels");
assertEquals(1, labels.getInt("Verified"));
} finally {
gerritServer.stop();
}
}
/**
* Tests a {@link JenkinsRule#configRoundtrip(hudson.model.Job)} on the workflow job.
*
* @throws Exception if so.
*/
@Test
public void testConfigRoundTrip() throws Exception {
PatchsetCreated event = Setup.createPatchsetCreated(PluginImpl.DEFAULT_SERVER_NAME);
WorkflowJob job = createWorkflowJob(event);
jenkinsRule.configRoundtrip(job);
job = (WorkflowJob)jenkinsRule.jenkins.getItem("WFJob");
GerritTrigger trigger = GerritTrigger.getTrigger(job);
assertFalse(trigger.isSilentMode());
assertEquals(1, trigger.getGerritBuildSuccessfulCodeReviewValue().intValue());
assertEquals(1, trigger.getGerritBuildSuccessfulVerifiedValue().intValue());
assertEquals(0, trigger.getGerritBuildFailedCodeReviewValue().intValue());
assertThat(trigger.getGerritProjects(), hasItem(
allOf(
isA(GerritProject.class),
hasProperty("compareType", is(CompareType.PLAIN)),
hasProperty("pattern", equalTo(event.getChange().getProject()))
)
));
}
/**
* Creates a {@link WorkflowJob} with a configured {@link GerritTrigger}.
*
* @param event the event to trigger on.
* @return the job
* @throws IOException if so
*/
private WorkflowJob createWorkflowJob(PatchsetCreated event) throws IOException {
return createWorkflowJob(event, ""
+ "node {\n"
+ " stage 'Build'\n"
+ " sh \"echo Gerrit trigger: ${GERRIT_EVENT_TYPE}\"\n"
+ "}\n");
}
/**
* Creates a {@link WorkflowJob} with a configured {@link GerritTrigger} and given workflow DSL script.
*
* @param event the event to trigger on.
* @param script the workflow DSL script.
* @return the job
* @throws IOException if so
*/
private WorkflowJob createWorkflowJob(PatchsetCreated event, String script) throws IOException {
WorkflowJob job = jenkinsRule.jenkins.createProject(WorkflowJob.class, "WFJob");
job.setDefinition(new CpsFlowDefinition(script));
GerritTrigger trigger = Setup.createDefaultTrigger(job);
trigger.setGerritProjects(Collections.singletonList(
new GerritProject(CompareType.PLAIN, event.getChange().getProject(),
Collections.singletonList(new Branch(CompareType.PLAIN, event.getChange().getBranch())),
null, null, null, false)
));
trigger.setSilentMode(false);
trigger.setGerritBuildSuccessfulCodeReviewValue(1);
trigger.setGerritBuildSuccessfulVerifiedValue(1);
return job;
}
/**
* Mock Gerrit server.
*/
@TestExtension
public static class MockGerritServer extends GerritServer implements RootAction {
private String lastContent;
/**
* Create server instance.
*/
public MockGerritServer() {
super(PluginImpl.DEFAULT_SERVER_NAME);
}
/**
* Get the server.
* @param jenkinsRule The Jenkins rule for the test instance.
* @return The Mock Gerrit server.
* @throws IOException if so (as the Gerrit boys seem to say).
*/
private static MockGerritServer get(JenkinsRule jenkinsRule) throws IOException {
MockGerritServer mockGerritServer = jenkinsRule.jenkins.getExtensionList(MockGerritServer.class).get(0);
mockGerritServer.configure(jenkinsRule);
return mockGerritServer;
}
/**
* Config the server.
* @param jenkinsRule The Jenkins rule for the test instance.
* @throws IOException if so (as the Gerrit boys seem to say).
*/
private void configure(JenkinsRule jenkinsRule) throws IOException {
PluginImpl.getInstance().addServer(this);
Config config = (Config)getConfig();
config.setGerritFrontEndURL(jenkinsRule.getURL().toString() + getUrlName() + "/");
config.setUseRestApi(true);
config.setGerritHttpUserName("user");
config.setGerritHttpPassword("passwd");
config.setRestCodeReview(true);
config.setRestVerified(true);
}
/**
* Wait for the Verified label/notification.
* @return The Verified label/notification.
*/
private JSONObject waitForNextVerified() {
long start = System.currentTimeMillis();
while (lastContent == null) {
// CS IGNORE MagicNumber FOR NEXT 1 LINES. REASON: It's magic.
if (System.currentTimeMillis() > start + 20000) {
Assert.fail("Timed out waiting on Verified message from Gerrit Trigger plugin.");
}
try {
// CS IGNORE MagicNumber FOR NEXT 1 LINES. REASON: It's magic.
Thread.sleep(100);
} catch (InterruptedException e) {
Assert.fail("Unexpected interrupt: " + e.getMessage());
}
}
return JSONObject.fromObject(lastContent);
}
@Override
public String getIconFileName() {
return "gear2.png";
}
@Override
public String getDisplayName() {
return "Gerrit";
}
@Override
public String getUrlName() {
return "gerrit";
}
/**
* Retrieves the Gerrit command.
*
* @param request the request
* @param response the response
* @throws IOException if so.
*/
public void doDynamic(StaplerRequest request, StaplerResponse response) throws IOException {
try {
this.lastContent = IOUtils.toString(request.getReader());
} finally {
response.setContentType("application/json");
PrintWriter writer = response.getWriter();
writer.write(new JSONObject(true).toString());
writer.flush();
}
}
}
}