Skip to content

Commit

Permalink
Add a config round trip test with a parameter for the resource.
Browse files Browse the repository at this point in the history
Add a parallel test for resources from a parameter.
  • Loading branch information
cfoote committed Jan 29, 2024
1 parent 3a2d104 commit ef307a1
Showing 1 changed file with 150 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Item;
import hudson.model.ParameterValue;
import hudson.model.ParametersAction;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Queue;
import hudson.model.Result;
Expand All @@ -25,7 +27,7 @@
import hudson.util.OneShotEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Semaphore;
Expand Down Expand Up @@ -147,6 +149,29 @@ public void configRoundTripWithLabel() throws Exception {
assertNull(withLabelProp.getResourceMatchScript());
}

@Test
@Issue("JENKINS-30308")
public void configRoundTripWithParam() throws Exception {
FreeStyleProject withParam = j.createFreeStyleProject("withparam");
withParam.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("param1", "some-resource", "parameter 1")));
withParam.addProperty(new RequiredResourcesProperty("${param1}", null, null, null, null));
FreeStyleProject withParamRoundTrip = j.configRoundtrip(withParam);

ParametersDefinitionProperty paramsProp =
withParamRoundTrip.getProperty(ParametersDefinitionProperty.class);
assertNotNull(paramsProp);

RequiredResourcesProperty resourcesProp =
withParamRoundTrip.getProperty(RequiredResourcesProperty.class);
assertNotNull(resourcesProp);
assertEquals("${param1}", resourcesProp.getResourceNames());
assertNull(resourcesProp.getResourceNamesVar());
assertNull(resourcesProp.getResourceNumber());
assertNull(resourcesProp.getLabelName());
assertNull(resourcesProp.getResourceMatchScript());
}

@Test
public void configRoundTripWithScript() throws Exception {
FreeStyleProject withScript = j.createFreeStyleProject("withScript");
Expand Down Expand Up @@ -233,6 +258,7 @@ public void autoCreateResource() throws IOException, InterruptedException, Execu
}

@Test
@Issue("JENKINS-30308")
public void autoCreateResourceFromParameter() throws Exception {
ParametersDefinitionProperty params = new ParametersDefinitionProperty(
new StringParameterDefinition("param1", "resource1", "parameter 1"));
Expand All @@ -250,24 +276,128 @@ public void autoCreateResourceFromParameter() throws Exception {
assertNull(LockableResourcesManager.get().fromName("resource1"));
}

@Test
@Issue("JENKINS-30308")
public void parallelResourceFromParameter() throws IOException, InterruptedException, ExecutionException, Exception {
LockableResourcesManager lm = LockableResourcesManager.get();
lm.createResource("resource1");
lm.createResource("resource2");
lm.createResource("resource3");

StringParameterDefinition param1Def = new StringParameterDefinition("param1", "", "parameter 1");

FreeStyleProject f = j.createFreeStyleProject("f");
f.setConcurrentBuild(true);
f.addProperty(new ParametersDefinitionProperty(param1Def));
f.addProperty(new RequiredResourcesProperty("${param1}", null, null, null, null));
f.getBuildersList().add(new WaitBuilder());

List<ParameterValue> values1 = new ArrayList<ParameterValue>();
values1.add(param1Def.createValue("resource1"));
FreeStyleBuild fb1 = f.scheduleBuild2(0, new ParametersAction(values1)).waitForStart();
j.waitForMessage("acquired lock on [resource1]", fb1);
j.waitForMessage("Waiting...", fb1);
j.assertLogNotContains("Continue", fb1);
Thread.sleep(100);

List<ParameterValue> values2 = new ArrayList<ParameterValue>();
values2.add(param1Def.createValue("resource2"));
FreeStyleBuild fb2 = f.scheduleBuild2(0, new ParametersAction(values2)).waitForStart();
j.waitForMessage("acquired lock on [resource2]", fb2);
j.waitForMessage("Waiting...", fb2);
j.assertLogNotContains("Continue", fb2);

List<ParameterValue> values3 = new ArrayList<ParameterValue>();
values3.add(param1Def.createValue("resource1"));
QueueTaskFuture<FreeStyleBuild> qt3 = f.scheduleBuild2(0, new ParametersAction(values3));
TestHelpers.waitForQueue(j.jenkins, f, Queue.BlockedItem.class);

Queue.BlockedItem blockedItem = (Queue.BlockedItem)j.jenkins.getQueue().getItem(f);
assertThat(blockedItem.getCauseOfBlockage(), is(instanceOf(LockableResourcesQueueTaskDispatcher.BecauseResourcesLocked.class)));

synchronized (fb2) {
fb2.notifyAll();
}
Thread.sleep(100);

blockedItem = (Queue.BlockedItem)j.jenkins.getQueue().getItem(f);
assertThat(blockedItem.getCauseOfBlockage(), is(instanceOf(LockableResourcesQueueTaskDispatcher.BecauseResourcesLocked.class)));

j.assertLogNotContains("Continue", fb1);
synchronized (fb1) {
fb1.notifyAll();
}
j.assertLogContains("Continue", fb1);
j.waitForMessage("released lock on [resource1]", fb1);
j.waitForCompletion(fb1);

FreeStyleBuild fb3 = qt3.waitForStart();
j.waitForMessage("acquired lock on [resource1]", fb3);
j.waitForMessage("Waiting...", fb3);
j.assertLogNotContains("Continue", fb3);
synchronized (fb3) {
fb3.notifyAll();
}

j.waitUntilNoActivity();
assertTrue(
"#1 build should be started before the build of #2. "
+ "#1 started at " + fb1.getStartTimeInMillis()
+ ", #2 finished at " + fb2.getStartTimeInMillis(),
fb1.getStartTimeInMillis() < fb2.getStartTimeInMillis());

long fb1EndTime = fb1.getStartTimeInMillis() + fb1.getDuration();
long fb2EndTime = fb2.getStartTimeInMillis() + fb2.getDuration();
assertTrue(
"#2 build should be finished before the build of #1. "
+ "#1 finished at " + fb1EndTime
+ ", #2 finished at " + fb2EndTime,
fb2EndTime < fb1EndTime);
assertTrue(
"#3 build should be started after the build of #1. "
+ "#1 finished at " + fb1EndTime
+ ", #3 started at " + fb3.getStartTimeInMillis(),
fb1EndTime < fb3.getStartTimeInMillis());
}

@Test
public void labelFromParameter() throws IOException, InterruptedException, ExecutionException {
LockableResourcesManager lm = LockableResourcesManager.get();
lm.createResourceWithLabel("resource1", "resource");
lm.createResourceWithLabel("resource2", "resource");

ParametersDefinitionProperty params = new ParametersDefinitionProperty(
new StringParameterDefinition("labelParam", "resource", "parameter 1"));

FreeStyleProject f = j.createFreeStyleProject("f");
f.addProperty(params);
f.addProperty(new RequiredResourcesProperty(null, null, null, "${labelParam}", null));

FreeStyleBuild fb1 = f.scheduleBuild2(0).waitForStart();
j.waitForCompletion(fb1);
assertEquals("resource", fb1.getBuildVariableResolver().resolve("labelParam"));
j.assertLogContains("acquired lock on [resource1, resource2]", fb1);
}

@Test
public void resourceNumberFromParameter() throws IOException, InterruptedException, ExecutionException {
LockableResourcesManager lm = LockableResourcesManager.get();
lm.createResourceWithLabel("resource1", "resource");
lm.createResourceWithLabel("resource2", "resource");
lm.reserve(Arrays.asList(lm.fromName("resource1")), "user1");
lm.createResourceWithLabel("resource3", "resource");
lm.reserve(List.of(lm.fromName("resource1")), "user1");

ParametersDefinitionProperty params = new ParametersDefinitionProperty(
new StringParameterDefinition("numParam", "1", "parameter 1"));
new StringParameterDefinition("numParam", "2", "parameter 1"));

FreeStyleProject f = j.createFreeStyleProject("f");
f.addProperty(params);
f.addProperty(new RequiredResourcesProperty(null, null, "${numParam}", "resource", null));

FreeStyleBuild fb1 = f.scheduleBuild2(0).waitForStart();
j.waitForCompletion(fb1);
assertEquals("1", fb1.getBuildVariableResolver().resolve("numParam"));
j.assertLogContains("acquired lock on [resource2]", fb1);
assertEquals("2", fb1.getBuildVariableResolver().resolve("numParam"));
j.assertLogContains("acquired lock on [resource2, resource3]", fb1);
}

@Test
Expand Down Expand Up @@ -323,6 +453,21 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
}
}

private static class WaitBuilder extends TestBuilder {

@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException {
listener.getLogger().println("Waiting...");

synchronized (build) {
build.wait();
}
listener.getLogger().println("Continue");
return true;
}
}

private static class SemaphoreBuilder extends TestBuilder {

private final OneShotEvent event = new OneShotEvent();
Expand Down

0 comments on commit ef307a1

Please sign in to comment.