@Override public boolean apply(@Nullable FlowNode input) { return (input instanceof BlockStartNode && PARALLEL_STEP.apply(input) && input.getPersistentAction(ThreadNameAction.class) == null); } }
static void verifySucceededCleanly(Jenkins j, WorkflowRun run) throws Exception { Assert.assertEquals(Result.SUCCESS, run.getResult()); int outputHash = run.getLog().hashCode(); FlowExecution exec = run.getExecution(); verifyCompletedCleanly(j, run); // Confirm the flow graph is fully navigable and contains the heads with appropriate ending DepthFirstScanner scan = new DepthFirstScanner(); List<FlowNode> allNodes = scan.allNodes(exec); FlowNode endNode = exec.getCurrentHeads().get(0); Assert.assertEquals(FlowEndNode.class, endNode.getClass()); assert allNodes.contains(endNode); Assert.assertEquals(8, allNodes.size()); // Graph structure assertions Assert.assertEquals(2, scan.filteredNodes(endNode, (Predicate)(Predicates.instanceOf(StepStartNode.class))).size()); Assert.assertEquals(2, scan.filteredNodes(endNode, (Predicate)(Predicates.instanceOf(StepEndNode.class))).size()); Assert.assertEquals(1, scan.filteredNodes(endNode, (Predicate)(Predicates.instanceOf(FlowStartNode.class))).size()); Predicate<FlowNode> sleepOrSemaphoreMatch = Predicates.or( new NodeStepNamePredicate(StepDescriptor.byFunctionName("semaphore").getId()), new NodeStepNamePredicate(StepDescriptor.byFunctionName("sleep").getId()) ); Assert.assertEquals(1, scan.filteredNodes(endNode, sleepOrSemaphoreMatch).size()); Assert.assertEquals(1, scan.filteredNodes(endNode, new NodeStepNamePredicate(StepDescriptor.byFunctionName("echo").getId())).size()); for (FlowNode node : (List<FlowNode>)(scan.filteredNodes(endNode, (Predicate)(Predicates.instanceOf(StepNode.class))))) { Assert.assertNotNull("Node: "+node.toString()+" does not have a TimingAction", node.getAction(TimingAction.class)); } assertHasTimingAction(run.getExecution()); }