Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
[JENKINS-26399] JenkinsRuleExt.waitForCompletion/Message
Browse files Browse the repository at this point in the history
  • Loading branch information
jglick committed Mar 18, 2015
1 parent 6c6a851 commit fac5ce6
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 92 deletions.
@@ -0,0 +1,61 @@
/*
* The MIT License
*
* Copyright 2015 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;

import hudson.model.Run;
import java.io.IOException;
import org.jvnet.hudson.test.JenkinsRule;

/**
* Utilities that could be added to {@link JenkinsRule} in the future but are not yet available in our baseline version.
*/
public class JenkinsRuleExt {

/**
* Waits for a build to complete.
* @return the same build, once done
*/
public static <R extends Run<?,?>> R waitForCompletion(R r) throws InterruptedException {
// Could be using com.jayway.awaitility:awaitility but it seems like overkill here.
while (r.isBuilding()) {
Thread.sleep(100);
}
return r;
}

/**
* Waits for a build log to contain a specified string.
* @return the same build, once it does
*/
public static <R extends Run<?,?>> R waitForMessage(String message, R r) throws IOException, InterruptedException {
while (!JenkinsRule.getLog(r).contains(message)) {
Thread.sleep(100);
}
return r;
}

private JenkinsRuleExt() {}

}
Expand Up @@ -86,6 +86,7 @@ public void assertThatWorkflowIsSuspended(WorkflowRun b, CpsFlowExecution e) thr
assert b.isBuilding();
}

/** @deprecated use {@link JenkinsRuleExt#waitForCompletion} instead */
public void waitForWorkflowToComplete() throws Exception {
do {
waitForWorkflowToSuspend(e);
Expand Down
Expand Up @@ -327,10 +327,7 @@ private void startJnlpProc() throws Exception {
while (f2.isFile()) {
Thread.sleep(100);
}
while (b.isBuilding()) {
Thread.sleep(100);
}
assertBuildCompletedSuccessfully();
story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b));
story.j.assertLogContains("finished waiting", b);
story.j.assertLogContains("OK, done", b);
killJnlpProc();
Expand Down Expand Up @@ -380,10 +377,7 @@ private void startJnlpProc() throws Exception {
while (f2.isFile()) {
Thread.sleep(100);
}
while (b.isBuilding()) {
Thread.sleep(100);
}
assertBuildCompletedSuccessfully();
story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b));
story.j.assertLogContains("finished waiting", b);
story.j.assertLogContains("OK, done", b);
killJnlpProc();
Expand Down Expand Up @@ -541,27 +535,21 @@ private void startJnlpProc() throws Exception {
startBuilding();
waitForWorkflowToSuspend();
assertTrue(b.isBuilding());
Thread.sleep(1500); // TODO how else to ensure that WorkflowRun.waitForCompletion has called copyLogs? (it flushes logs when a step finishes but cannot tell when start() returns, and it cannot listen for LogAction being added or written)
story.j.assertLogContains("running as someone", b);
JenkinsRuleExt.waitForMessage("running as someone", b);
CheckAuth.finish(false);
waitForWorkflowToSuspend();
assertTrue(b.isBuilding());
Thread.sleep(1500); // TODO
story.j.assertLogContains("still running as someone", b);
JenkinsRuleExt.waitForMessage("still running as someone", b);
}
});
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
assertEquals(JenkinsRule.DummySecurityRealm.class, jenkins().getSecurityRealm().getClass());
rebuildContext(story.j);
assertThatWorkflowIsSuspended();
Thread.sleep(1500); // TODO
story.j.assertLogContains("again running as someone", b);
JenkinsRuleExt.waitForMessage("again running as someone", b);
CheckAuth.finish(true);
waitForWorkflowToComplete();
Thread.sleep(1500); // TODO
assertBuildCompletedSuccessfully();
story.j.assertLogContains("finally running as someone", b);
story.j.assertLogContains("finally running as someone", story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b)));
}
});
}
Expand Down Expand Up @@ -656,20 +644,14 @@ public static void finish(final boolean terminate) {
p = jenkins().createProject(WorkflowJob.class, "demo");
p.setDefinition(new CpsFlowDefinition("node('special') {echo 'OK ran'}"));
startBuilding();
while (!JenkinsRule.getLog(b).contains("Still waiting to schedule task")) {
Thread.sleep(100);
}
JenkinsRuleExt.waitForMessage("Still waiting to schedule task", b);
}
});
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
story.j.createSlave("special", null);
rebuildContext(story.j);
while (b.isBuilding()) {
Thread.sleep(100);
}
assertBuildCompletedSuccessfully();
story.j.assertLogContains("OK ran", b);
story.j.assertLogContains("OK ran", story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b)));
}
});
}
Expand Down
Expand Up @@ -26,17 +26,21 @@

import hudson.Functions;
import java.io.File;
import org.jenkinsci.plugins.workflow.BuildWatcher;
import org.jenkinsci.plugins.workflow.JenkinsRuleExt;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.Rule;
import org.junit.runners.model.Statement;
import org.jvnet.hudson.test.RestartableJenkinsRule;

public class PushdStepTest {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public RestartableJenkinsRule story = new RestartableJenkinsRule();

private String pwdStep() {
Expand Down Expand Up @@ -66,10 +70,7 @@ private String pwdStep() {
@Override public void evaluate() throws Throwable {
SemaphoreStep.success("restarting/1", null);
WorkflowRun b = story.j.jenkins.getItemByFullName("p", WorkflowJob.class).getLastBuild();
while (b.isBuilding()) { // TODO JENKINS-26399
Thread.sleep(100);
}
story.j.assertLogContains(File.separator + "subdir", story.j.assertBuildStatusSuccess(b));
story.j.assertLogContains(File.separator + "subdir", story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b)));
}
});
}
Expand Down
Expand Up @@ -25,6 +25,8 @@
package org.jenkinsci.plugins.workflow.steps;

import java.util.List;
import org.jenkinsci.plugins.workflow.BuildWatcher;
import org.jenkinsci.plugins.workflow.JenkinsRuleExt;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.cps.CpsFlowExecution;
import org.jenkinsci.plugins.workflow.cps.nodes.StepAtomNode;
Expand All @@ -33,13 +35,15 @@
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
import static org.junit.Assert.*;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runners.model.Statement;
import org.jvnet.hudson.test.RestartableJenkinsRule;

public class SleepStepTest {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public RestartableJenkinsRule r = new RestartableJenkinsRule();

@Test public void sleepAndRestart() {
Expand All @@ -61,10 +65,7 @@ public class SleepStepTest {
@Override public void evaluate() throws Throwable {
WorkflowJob p = r.j.jenkins.getItemByFullName("p", WorkflowJob.class);
WorkflowRun b = p.getLastBuild();
while (b.isBuilding()) {
Thread.sleep(100);
}
r.j.assertBuildStatusSuccess(b);
r.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b));
}
});
}
Expand Down
Expand Up @@ -29,6 +29,7 @@
import jenkins.model.CauseOfInterruption;
import jenkins.model.InterruptedBuildAction;
import org.jenkinsci.plugins.workflow.BuildWatcher;
import org.jenkinsci.plugins.workflow.JenkinsRuleExt;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.cps.CpsFlowExecution;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
Expand Down Expand Up @@ -118,9 +119,7 @@ public class StageTest {
assertTrue(b1.isBuilding());
e2.waitForSuspension();
e3.waitForSuspension();
Thread.sleep(1000); // TODO why is this necessary?
assertFalse(b2.isBuilding());
assertEquals(Result.NOT_BUILT, b2.getResult());
story.j.assertBuildStatus(Result.NOT_BUILT, JenkinsRuleExt.waitForCompletion(b2));
InterruptedBuildAction iba = b2.getAction(InterruptedBuildAction.class);
assertNotNull(iba);
List<CauseOfInterruption> causes = iba.getCauses();
Expand Down Expand Up @@ -183,24 +182,13 @@ public class StageTest {
WorkflowRun b1 = p.scheduleBuild2(0).waitForStart();
SemaphoreStep.waitForStart("serializability/1", b1);
WorkflowRun b2 = p.scheduleBuild2(0).waitForStart();
while (!JenkinsRule.getLog(b2).contains("Waiting for builds [1]")) {
// TODO similar to JENKINS-26399 though waiting for a particular message rather than completion
Thread.sleep(100);
}
JenkinsRuleExt.waitForMessage("Waiting for builds [1]", b2);
WorkflowRun b3 = p.scheduleBuild2(0).waitForStart();
while (!JenkinsRule.getLog(b3).contains("Waiting for builds [1]")) {
Thread.sleep(100);
}
JenkinsRuleExt.waitForMessage("Waiting for builds [1]", b3);
SemaphoreStep.success("serializability/1", null); // b1
while (b1.isBuilding()) {
Thread.sleep(100);
}
story.j.assertBuildStatusSuccess(b1);
story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b1));
SemaphoreStep.success("serializability/2", null); // b3
while (b3.isBuilding()) {
Thread.sleep(100);
}
story.j.assertBuildStatusSuccess(b3);
story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b3));
story.j.assertBuildStatus(Result.NOT_BUILT, b2);
story.j.assertLogContains("Canceled since #3 got here", b2);
story.j.assertLogContains("in finally", b2);
Expand All @@ -222,16 +210,12 @@ public class StageTest {
WorkflowRun b1 = p.scheduleBuild2(0).waitForStart();
SemaphoreStep.waitForStart("holdingAfterUnblockA/1", b1); // about to leave A
WorkflowRun b2 = p.scheduleBuild2(0).waitForStart();
while (!JenkinsRule.getLog(b2).contains("Waiting for builds [1]")) {
Thread.sleep(100);
}
JenkinsRuleExt.waitForMessage("Waiting for builds [1]", b2);
SemaphoreStep.success("holdingAfterUnblockA/1", null);
SemaphoreStep.waitForStart("holdingAfterUnblockB/1", b1); // now in B
SemaphoreStep.waitForStart("holdingAfterUnblockA/2", b2); // b2 unblocked, now in A
WorkflowRun b3 = p.scheduleBuild2(0).waitForStart();
while (!JenkinsRule.getLog(b3).contains("Waiting for builds [2]")) {
Thread.sleep(100);
}
JenkinsRuleExt.waitForMessage("Waiting for builds [2]", b3);
}
});
}
Expand All @@ -248,18 +232,12 @@ public class StageTest {
WorkflowRun b1 = p.scheduleBuild2(0).waitForStart();
SemaphoreStep.waitForStart("holdingAfterExitUnblock/1", b1); // about to leave
WorkflowRun b2 = p.scheduleBuild2(0).waitForStart();
while (!JenkinsRule.getLog(b2).contains("Waiting for builds [1]")) {
Thread.sleep(100);
}
JenkinsRuleExt.waitForMessage("Waiting for builds [1]", b2);
SemaphoreStep.success("holdingAfterExitUnblock/1", null);
while (b1.isBuilding()) {
Thread.sleep(100);
}
JenkinsRuleExt.waitForCompletion(b1);
SemaphoreStep.waitForStart("holdingAfterExitUnblock/2", b2); // b2 unblocked
WorkflowRun b3 = p.scheduleBuild2(0).waitForStart();
while (!JenkinsRule.getLog(b3).contains("Waiting for builds [2]")) {
Thread.sleep(100);
}
JenkinsRuleExt.waitForMessage("Waiting for builds [2]", b3);
}
});
}
Expand Down
Expand Up @@ -26,17 +26,21 @@

import hudson.slaves.DumbSlave;
import java.io.File;
import org.jenkinsci.plugins.workflow.BuildWatcher;
import org.jenkinsci.plugins.workflow.JenkinsRuleExt;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.Rule;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;

public class WorkspaceStepTest {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public JenkinsRule r = new JenkinsRule();

@Issue("JENKINS-26072")
Expand All @@ -59,11 +63,8 @@ public class WorkspaceStepTest {
SemaphoreStep.waitForStart("customWorkspace/2", b3);
SemaphoreStep.success("customWorkspace/1", null);
SemaphoreStep.success("customWorkspace/2", null);
while (b2.isBuilding() || b3.isBuilding()) {
Thread.sleep(100);
}
r.assertBuildStatusSuccess(b2);
r.assertBuildStatusSuccess(b3);
r.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b2));
r.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(b3));
String location = new File(r.jenkins.getRootDir(), "custom-location").getAbsolutePath();
r.assertLogContains(location, b2);
r.assertLogNotContains("custom-location@", b2);
Expand Down
Expand Up @@ -27,6 +27,7 @@
import java.util.List;
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
import org.jenkinsci.plugins.workflow.BuildWatcher;
import org.jenkinsci.plugins.workflow.JenkinsRuleExt;
import org.junit.ClassRule;
import org.jvnet.hudson.test.FailureBuilder;
import org.jvnet.hudson.test.Issue;
Expand Down Expand Up @@ -119,11 +120,7 @@ public void abortBuild() throws Exception {
}
fb.getExecutor().interrupt();

while (fb.isBuilding()) {
Thread.sleep(100);
}

assertEquals(Result.ABORTED, fb.getResult());
j.assertBuildStatus(Result.ABORTED, JenkinsRuleExt.waitForCompletion(fb));
j.assertBuildStatus(Result.FAILURE,q.get());
}

Expand Down Expand Up @@ -175,13 +172,10 @@ public void cancelBuildQueue() throws Exception {
// Should be the same as, e.g., GerritTrigger.RunningJobs.cancelJob, which calls Executor.interrupt directly.
// (Not if the Executor.currentExecutable is an AfterRestartTask.Body, though in that case probably the FreeStyleBuild would have been killed by restart anyway!)
usb.doStop();
while (usb.isBuilding() || ds1b.isBuilding() || ds2b.isBuilding() || ds3b.isBuilding()) {
Thread.sleep(100);
}
assertEquals(Result.ABORTED, usb.getResult());
assertEquals(Result.ABORTED, ds1b.getResult());
assertEquals(Result.ABORTED, ds2b.getResult());
assertEquals(Result.ABORTED, ds3b.getResult());
j.assertBuildStatus(Result.ABORTED, JenkinsRuleExt.waitForCompletion(usb));
j.assertBuildStatus(Result.ABORTED, JenkinsRuleExt.waitForCompletion(ds1b));
j.assertBuildStatus(Result.ABORTED, JenkinsRuleExt.waitForCompletion(ds2b));
j.assertBuildStatus(Result.ABORTED, JenkinsRuleExt.waitForCompletion(ds3b));
}

@SuppressWarnings("deprecation")
Expand Down

0 comments on commit fac5ce6

Please sign in to comment.