Skip to content

Commit

Permalink
Extend mock tests to cover more branches
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkEWaite committed Jan 27, 2025
1 parent 76865f3 commit 6e05ea9
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 70 deletions.
15 changes: 15 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@
<version>1.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
package jenkins.advancedqueue;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import hudson.model.Action;
import hudson.model.Descriptor;
import hudson.model.FreeStyleProject;
import hudson.model.ParametersAction;
import hudson.model.Cause;
import hudson.model.Queue;
import hudson.model.StringParameterValue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.List;
import jenkins.advancedqueue.priority.PriorityStrategy;
import jenkins.advancedqueue.sorter.SorterStrategy;
import jenkins.advancedqueue.sorter.SorterStrategyCallback;
import jenkins.advancedqueue.sorter.strategy.MultiBucketStrategy;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.support.steps.ExecutorStepExecution;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
Expand All @@ -28,98 +34,187 @@ public class PriorityConfigurationPlaceholderTaskHelperTest {
@ClassRule
public static JenkinsRule j = new JenkinsRule();

private static PriorityStrategy strategy;
private static Queue.Item item;
private static FreeStyleProject project;
private static Action action;
private static PriorityConfigurationCallback callback;
private static PriorityConfigurationPlaceholderTaskHelper helper;
private static Queue.Task ownerTask;
private static ExecutorStepExecution.PlaceholderTask task;
private static Queue.Item pipelineItemInQuietPeriod;
private static DecisionLogger decisionLogger;
private static List<String> loggedMessages;

@BeforeClass
public static void setUp() throws IOException {
project = j.createFreeStyleProject();
helper = new PriorityConfigurationPlaceholderTaskHelper();
task = mock(ExecutorStepExecution.PlaceholderTask.class);
ownerTask = mock(Queue.Task.class);
public static void startPipelineJobWithQuietPeriod() throws Exception {
// Start a Pipeline with a quiet period of 37 seconds before it runs
String pipelineName = "my-pipeline-in-the-quiet-period";
WorkflowJob pipeline = j.createProject(WorkflowJob.class, pipelineName);
String pipelineDefinition =
"""
node {
echo 'Hello from a node'
sleep 41
}
""";
pipeline.setDefinition(new CpsFlowDefinition(pipelineDefinition, true));
pipeline.scheduleBuild(37, new Cause.UserIdCause());
pipelineItemInQuietPeriod = findQueueItem(pipelineName);
assertNotNull("Pipeline in quiet period not in Queue", pipelineItemInQuietPeriod);
// Check the item is blocked due to the 37 second quiet period
assertThat(
pipelineItemInQuietPeriod.getCauseOfBlockage().getShortDescription(),
startsWith("In the quiet period."));
}

@BeforeClass
public static void createActionAndItem() {
action = new ParametersAction(new StringParameterValue("priority", "5"));
item = new Queue.WaitingItem(Calendar.getInstance(), project, Arrays.asList(action));
}

@BeforeClass
public static void createStrategy() {
strategy = new PriorityStrategy() {
@Override
public boolean isApplicable(Queue.Item item) {
return false;
}

@Override
public int getPriority(Queue.Item item) {
return 3;
}

@Override
public void numberPrioritiesUpdates(int oldNumberOfPriorities, int newNumberOfPriorities) {}

@Override
public Descriptor<PriorityStrategy> getDescriptor() {
return null;
private static Queue.Item findQueueItem(String name) {
Queue.Item found = null;
Queue.Item[] items = j.jenkins.getQueue().getItems();
for (Queue.Item item : items) {
if (item.getDisplayName().equals(name)) {
found = item;
}
};
}
return found;
}

@BeforeClass
public static void createCallback() {
callback = new PriorityConfigurationCallback() {
public static void createDecisionLogger() {
decisionLogger = new DecisionLogger() {
@Override
public DecisionLogger addDecisionLog(int indent, String log) {
return null;
}

@Override
public PriorityConfigurationCallback setPrioritySelection(int priority) {
return null;
loggedMessages.add(log);
return this;
}
};
}

@Override
public PriorityConfigurationCallback setPrioritySelection(
int priority, int jobGroupId, PriorityStrategy reason) {
return null;
}
@Before
public void clearLoggedMessages() throws Exception {
loggedMessages = new ArrayList<>();
}

@Override
public PriorityConfigurationCallback setPrioritySelection(
int priority, long sortAsInQueueSince, int jobGroupId, PriorityStrategy reason) {
return null;
}
};
@Test
public void testGetPriorityAssignsGlobalDefault() {
PriorityConfiguration configuration = new PriorityConfiguration();
PriorityConfigurationCallbackImpl callback = new PriorityConfigurationCallbackImpl();
assertThat(callback.getPrioritySelection(), is(-1)); // Before callback is used
configuration.getPriority(pipelineItemInQuietPeriod, callback);
assertThat(loggedMessages, hasItem("Assigning global default priority"));
assertThat(callback.getPrioritySelection(), is(MultiBucketStrategy.DEFAULT_PRIORITY)); // After callback is used
}

@Test
public void testIsPlaceholderTask() {
Queue.Task myTask = mock(ExecutorStepExecution.PlaceholderTask.class);
assertTrue(helper.isPlaceholderTask(myTask));
PriorityConfigurationPlaceholderTaskHelper helper = new PriorityConfigurationPlaceholderTaskHelper();
// Pipeline task is not a placeholder task
assertFalse(helper.isPlaceholderTask(pipelineItemInQuietPeriod.getTask()));
}

@Test
public void testGetPriority() {
// Could not find an easy way to generate a placeholder task
// Use a mock object for better test coverage
ExecutorStepExecution.PlaceholderTask task = mock(ExecutorStepExecution.PlaceholderTask.class);
when(task.getOwnerTask()).thenReturn(pipelineItemInQuietPeriod.getTask());

PriorityConfigurationPlaceholderTaskHelper helper = new PriorityConfigurationPlaceholderTaskHelper();
PriorityConfigurationCallbackImpl callback = new PriorityConfigurationCallbackImpl();
assertThat(callback.getPrioritySelection(), is(-1)); // Before callback is used
callback.expectPrioritySelection(3);
PriorityConfigurationCallback result = helper.getPriority(task, callback);
assertNotNull(result);

// Verify that the default priority from the MultiBucketStrategy is returned by the strategy for the given item
assertEquals(MultiBucketStrategy.DEFAULT_PRIORITY, callback.getPrioritySelection());
}

@Test
public void testGetPriorityNonJobTask() {
// Could not find an easy way to generate a placeholder task
// Use a mock object for better test coverage
ExecutorStepExecution.PlaceholderTask task = mock(ExecutorStepExecution.PlaceholderTask.class);
Queue.Task ownerTask = mock(Queue.Task.class);
when(task.getOwnerTask()).thenReturn(ownerTask);

// Use a custom sorter strategy
SorterStrategyImpl strategy = new SorterStrategyImpl();
PrioritySorterConfiguration.get().setStrategy(strategy);

PriorityConfigurationPlaceholderTaskHelper helper = new PriorityConfigurationPlaceholderTaskHelper();
PriorityConfigurationCallbackImpl callback = new PriorityConfigurationCallbackImpl();
assertThat(callback.getPrioritySelection(), is(-1)); // Before callback is used
// Check that default priority of custom strategy is different than system-wide default priority
assertThat(strategy.getDefaultPriority(), is(not(MultiBucketStrategy.DEFAULT_PRIORITY)));
callback.expectPrioritySelection(strategy.getDefaultPriority());
PriorityConfigurationCallback result = helper.getPriority(task, callback);
assertNotNull(result);

// Verify that the default priority from the MultiBucketStrategy is returned by the strategy for the given item
assertEquals(MultiBucketStrategy.DEFAULT_PRIORITY, strategy.getPriority(item));
// Verify that the default priority from the strategy is returned
assertEquals(strategy.getDefaultPriority(), callback.getPrioritySelection());
}

@Test
public void testIsPlaceholderTaskUsed() {
assertTrue(PriorityConfigurationPlaceholderTaskHelper.isPlaceholderTaskUsed());
}

private static class PriorityConfigurationCallbackImpl implements PriorityConfigurationCallback {

private int prioritySelection = -1;
private int expectedPrioritySelection = -1;

public PriorityConfigurationCallbackImpl() {}

private int getPrioritySelection() {
return prioritySelection;
}

@Override
public PriorityConfigurationCallback setPrioritySelection(int priority) {
prioritySelection = priority;
if (expectedPrioritySelection != -1) {
assertThat(priority, is(expectedPrioritySelection));
}
return this;
}

@Override
public PriorityConfigurationCallback setPrioritySelection(
int priority, int jobGroupId, PriorityStrategy reason) {
throw new UnsupportedOperationException("Not supported.");
}

@Override
public PriorityConfigurationCallback setPrioritySelection(
int priority, long sortAsInQueueSince, int jobGroupId, PriorityStrategy reason) {
throw new UnsupportedOperationException("Not supported.");
}

@Override
public DecisionLogger addDecisionLog(int indent, String log) {
decisionLogger.addDecisionLog(indent, log);
return decisionLogger;
}

private void expectPrioritySelection(int priority) {
expectedPrioritySelection = priority;
}
}

/* A sorter strategy that is intentionally different than the default */
private static class SorterStrategyImpl extends SorterStrategy {

private final int NUMBER_OF_PRIORITIES = 4 + MultiBucketStrategy.DEFAULT_PRIORITIES_NUMBER;

public SorterStrategyImpl() {}

@Override
public SorterStrategyCallback onNewItem(Queue.Item item, SorterStrategyCallback weightCallback) {
throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public int getNumberOfPriorities() {
return NUMBER_OF_PRIORITIES;
}

@Override
public int getDefaultPriority() {
return NUMBER_OF_PRIORITIES / 2;
}
}
}

0 comments on commit 6e05ea9

Please sign in to comment.