/** Verify that we retain and flowgraph start with the included nodes, which must be in sorted order */ void assertIncludesNodes(List<FlowNode> prefixNodes, WorkflowRun run) throws Exception { List<FlowNode> nodes = new DepthFirstScanner().allNodes(run.getExecution()); nodes.sort(FlowScanningUtils.ID_ORDER_COMPARATOR); // Make sure we have the starting nodes at least assert prefixNodes.size() <= nodes.size(); for (int i=0; i<prefixNodes.size(); i++) { try { FlowNode match = prefixNodes.get(i); FlowNode after = nodes.get(i); Assert.assertEquals(match.getDisplayFunctionName(), after.getDisplayFunctionName()); } catch (Exception ex) { throw new Exception("Error with flownode at index="+i, ex); } } }
/** Verify we didn't lose TimingAction */ static void assertHasTimingAction(FlowExecution exec) throws Exception { DepthFirstScanner scan = new DepthFirstScanner(); for (FlowNode node : scan.allNodes(exec)) { try { if (!(node instanceof FlowStartNode) && !(node instanceof FlowEndNode)) { Assert.assertNotNull("Missing TimingAction on node", node.getPersistentAction(TimingAction.class)); } } catch (Exception ex) { throw new Exception("Error with node: "+node.getId(), ex); } } }
@Override public void evaluate() throws Throwable { WorkflowRun run = createAndRunSleeperJob(story.j.jenkins, "durableAgainstClean", FlowDurabilityHint.PERFORMANCE_OPTIMIZED); Assert.assertEquals(FlowDurabilityHint.PERFORMANCE_OPTIMIZED, run.getExecution().getDurabilityHint()); logStart[0] = JenkinsRule.getLog(run); if (run.getExecution() instanceof CpsFlowExecution) { // Pause and unPause to force persistence CpsFlowExecution cpsFlow = (CpsFlowExecution)(run.getExecution()); cpsFlow.pause(true); long timeout = System.nanoTime()+TimeUnit.NANOSECONDS.convert(5, TimeUnit.SECONDS); while(System.nanoTime() < timeout && !cpsFlow.isPaused()) { Thread.sleep(100L); } nodesOut.addAll(new DepthFirstScanner().allNodes(run.getExecution())); nodesOut.sort(FlowScanningUtils.ID_ORDER_COMPARATOR); cpsFlow.pause(false); timeout = System.nanoTime()+TimeUnit.NANOSECONDS.convert(5, TimeUnit.SECONDS); while(System.nanoTime() < timeout && cpsFlow.isPaused()) { Thread.sleep(100L); } // Ensures we're marked as can-not-resume cpsFlow.persistedClean = false; cpsFlow.saveOwner(); } } });
getFileM.setAccessible(true); List<FlowNode> nodes = new DepthFirstScanner().allNodes(execution.getCurrentHeads()); Collections.sort(nodes, FlowScanningUtils.ID_ORDER_COMPARATOR);
@Override public void evaluate() throws Throwable { Jenkins jenkins = story.j.jenkins; WorkflowRun run = createAndRunSleeperJob(story.j.jenkins, jobName, FlowDurabilityHint.MAX_SURVIVABILITY); run.getParent().setResumeBlocked(true); FlowExecution exec = run.getExecution(); if (exec instanceof CpsFlowExecution) { assert ((CpsFlowExecution) exec).getStorage().isPersistedFully(); } logStart[0] = JenkinsRule.getLog(run); nodesOut.addAll(new DepthFirstScanner().allNodes(run.getExecution())); nodesOut.sort(FlowScanningUtils.ID_ORDER_COMPARATOR); } });
@Override public void evaluate() throws Throwable { Jenkins jenkins = story.j.jenkins; WorkflowRun run = createAndRunSleeperJob(story.j.jenkins, jobName, FlowDurabilityHint.MAX_SURVIVABILITY); run.getParent().setResumeBlocked(false); FlowExecution exec = run.getExecution(); if (exec instanceof CpsFlowExecution) { assert ((CpsFlowExecution) exec).getStorage().isPersistedFully(); } logStart[0] = JenkinsRule.getLog(run); nodesOut.addAll(new DepthFirstScanner().allNodes(run.getExecution())); nodesOut.sort(FlowScanningUtils.ID_ORDER_COMPARATOR); run.getParent().setResumeBlocked(true); } });
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()); }