diff --git a/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/artifacts/specialized/ExecutionCountBatchlet.java b/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/artifacts/specialized/ExecutionCountBatchlet.java new file mode 100644 index 0000000..110cdbc --- /dev/null +++ b/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/artifacts/specialized/ExecutionCountBatchlet.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016 International Business Machines Corp. + * + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. Licensed under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ +package com.ibm.jbatch.tck.artifacts.specialized; + +import javax.batch.api.AbstractBatchlet; +import javax.batch.api.BatchProperty; +import javax.batch.runtime.context.JobContext; +import javax.inject.Inject; + +@javax.inject.Named("executionCountBatchlet") +public class ExecutionCountBatchlet extends AbstractBatchlet { + + @Inject + JobContext jobCtx; + + @Inject + @BatchProperty (name="executionCount.number") + String executionNumber; + + @Override + public String process() throws Exception { + + Integer executionCount; + + if(executionNumber!=null){ + executionCount=Integer.parseInt(executionNumber); + } + else{ + executionCount=0; + } + + jobCtx.setTransientUserData(1); + + return "EXECUTION "+executionCount; + } + + @Override + public void stop() throws Exception { + + } + +} diff --git a/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/artifacts/specialized/TransitionDeciderWithFlag.java b/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/artifacts/specialized/TransitionDeciderWithFlag.java new file mode 100644 index 0000000..f359ca1 --- /dev/null +++ b/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/artifacts/specialized/TransitionDeciderWithFlag.java @@ -0,0 +1,54 @@ +/** + * Copyright 2016 International Business Machines Corp. + * + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. Licensed under the Apache License, + * Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ibm.jbatch.tck.artifacts.specialized; + +import javax.batch.api.BatchProperty; +import javax.batch.api.Decider; +import javax.batch.runtime.StepExecution; +import javax.batch.runtime.context.JobContext; +import javax.inject.Inject; + +@javax.inject.Named("transitionDeciderWithFlag") +public class TransitionDeciderWithFlag implements Decider { + + @Inject + JobContext jobCtx; + + final public static String firstExecution ="First Execution of Transition Decider with Flag"; + final public static String secondExecution="Second Execution of Transition Decider with Flag"; + + @Override + public String decide(StepExecution[] executions) throws Exception { + + Integer deciderCount = jobCtx.getTransientUserData() == null ? 0 : (Integer)jobCtx.getTransientUserData(); + + String deciderExitStatus = null; + + if (deciderCount==0){ + deciderExitStatus = firstExecution; + jobCtx.setExitStatus(firstExecution); + jobCtx.setTransientUserData(1); + } else{ + jobCtx.setExitStatus(secondExecution); + deciderExitStatus = secondExecution; + } + + return deciderExitStatus; + + } + +} diff --git a/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/tests/jslxml/JobExecutableSequenceTests.java b/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/tests/jslxml/JobExecutableSequenceTests.java index 21595fd..0014d60 100755 --- a/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/tests/jslxml/JobExecutableSequenceTests.java +++ b/com.ibm.jbatch.tck/src/main/java/com/ibm/jbatch/tck/tests/jslxml/JobExecutableSequenceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 International Business Machines Corp. + * Copyright 2016 International Business Machines Corp. * * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. Licensed under the Apache License, @@ -16,15 +16,20 @@ */ package com.ibm.jbatch.tck.tests.jslxml; +import static com.ibm.jbatch.tck.utils.AssertionUtils.assertObjEquals; import static com.ibm.jbatch.tck.utils.AssertionUtils.assertWithMessage; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.List; import java.util.Properties; import javax.batch.operations.JobStartException; import javax.batch.runtime.BatchStatus; import javax.batch.runtime.JobExecution; +import javax.batch.runtime.Metric; +import javax.batch.runtime.StepExecution; +import javax.crypto.CipherInputStream; import org.junit.Before; import org.testng.Reporter; @@ -32,6 +37,10 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.ibm.jbatch.tck.annotations.APIRef; +import com.ibm.jbatch.tck.annotations.SpecRef; +import com.ibm.jbatch.tck.annotations.TCKTest; +import com.ibm.jbatch.tck.artifacts.specialized.TransitionDeciderWithFlag; import com.ibm.jbatch.tck.utils.JobOperatorBridge; public class JobExecutableSequenceTests { @@ -50,6 +59,17 @@ public class JobExecutableSequenceTests { * @throws IOException * @throws InterruptedException */ + + @TCKTest( + specRefs={ + @SpecRef(section="5.3",version="1.0", notes={""}) + }, + apiRefs={ + @APIRef(className="") + }, + versions="1.1.WORKING", + assertions={"Section 5.3 Flow"} + ) @Test @org.junit.Test public void testJobExecutableSequenceToUnknown() throws Exception { @@ -79,6 +99,92 @@ public void testJobExecutableSequenceToUnknown() throws Exception { handleException(METHOD, e); } } + + /** + * @testName: testJobTransitionLoopWithRestart + * @assertion: Section 10.8 restart processing + * @test_Strategy: 1. setup a job consisting of 2 steps (step1 next to step2, step2 fail, restart @ step1, transition to step 2, back to step 1) + * 2. start job + * 3. job should fail because it shouldn't be able to transition twice to step 1 in the same execution + * + * @throws JobStartException + * @throws FileNotFoundException + * @throws IOException + * @throws InterruptedException + */ + @TCKTest( + specRefs={ + @SpecRef(section="10.8",version="1.0", citations={"...for restart we need: a definition of where in the job definition to begin; rules for deciding whether or not to execute the current execution element; and rules for performing transitioning, especially taking into account that all steps relevant to transitioning may not have executed on this (restart) execution."}), + @SpecRef(section="8.9.3",version="1.0", notes={""}) + }, + apiRefs={ + @APIRef(className="") + }, + versions="1.1.WORKING", + assertions={"A step is not executed more than once on job restart if not set with \"allow-start-if-complete\"", + "A step may be executed more than once on job restart if set with \"allow-start-if-complete\""}, + issueRefs={"Bugzilla 5691", "Github 31"}) + + @Test + @org.junit.Test + public void testJobTransitionLoopWithRestart() throws Exception { + + String METHOD = "testJobTransitionLoopWithRestart"; + + try { + JobExecution jobExec = null; + try{ + Properties jobParams = new Properties(); + jobParams.put("executionCount.number", "1"); + jobExec = jobOp.startJobAndWaitForResult("job_restart_second_transition", null); + } catch (JobStartException e) { + Reporter.log("Caught JobStartException: " + e.getLocalizedMessage()); + return; //Since the job will be invalid when it loops, if the job fails to start because of that, the test should pass. + } + Reporter.log("First Job execution getBatchStatus()="+jobExec.getBatchStatus()+"

"); + assertObjEquals(BatchStatus.FAILED, jobExec.getBatchStatus()); + + Reporter.log("Obtaining StepExecutions for execution id: " + jobExec.getExecutionId() + "

"); + List steps = jobOp.getStepExecutions(jobExec.getExecutionId()); + + assertObjEquals(2, steps.size()); + + for (StepExecution step : steps) { + showStepState(step); + assertObjEquals(BatchStatus.COMPLETED, step.getBatchStatus()); + } + + JobExecution restartedJobExec =null; + try{ + Properties jobParams = new Properties(); + jobParams.put("executionCount.number", "2"); + restartedJobExec = jobOp.restartJobAndWaitForResult(jobExec.getExecutionId(),jobParams); + } catch(JobStartException e) { + Reporter.log("Caught JobStartException: " + e.getLocalizedMessage()); + return; + } + + Reporter.log("Obtaining StepExecutions for execution id: " + restartedJobExec.getExecutionId() + "

"); + List steps2 = jobOp.getStepExecutions(restartedJobExec.getExecutionId()); + + final String message="Number of steps in this execution: "; + + assertObjEquals(message+"1", message+steps2.size()); + StepExecution step=steps2.get(0); + showStepState(step); + assertObjEquals(BatchStatus.COMPLETED, step.getBatchStatus()); + assertObjEquals("step2", step.getStepName()); + + Reporter.log("Second Job execution getExitStatus()="+restartedJobExec.getExitStatus()+"

"); + assertObjEquals(TransitionDeciderWithFlag.firstExecution, restartedJobExec.getExitStatus()); + + Reporter.log("Second Job execution getBatchStatus()="+restartedJobExec.getBatchStatus()+"

"); + assertObjEquals(BatchStatus.FAILED, restartedJobExec.getBatchStatus()); + + } catch (Exception e) { + handleException(METHOD, e); + } + } private static void handleException(String methodName, Exception e) throws Exception { Reporter.log("Caught exception: " + e.getMessage()+"

"); @@ -113,4 +219,22 @@ public void beforeTest() throws ClassNotFoundException { public void afterTest() { jobOp = null; } + + private void showStepState(StepExecution step) { + Reporter.log("---------------------------

"); + Reporter.log("getStepName(): " + step.getStepName() + " - "); + Reporter.log("getStepExecutionId(): " + step.getStepExecutionId() + " - "); + Metric[] metrics = step.getMetrics(); + + for (int i = 0; i < metrics.length; i++) { + Reporter.log(metrics[i].getType() + ": " + metrics[i].getValue() + " - "); + } + + Reporter.log("getStartTime(): " + step.getStartTime() + " - "); + Reporter.log("getEndTime(): " + step.getEndTime() + " - "); + Reporter.log("getBatchStatus(): " + step.getBatchStatus() + " - "); + Reporter.log("getExitStatus(): " + step.getExitStatus()+"

"); + Reporter.log("---------------------------

"); + } } + diff --git a/com.ibm.jbatch.tck/src/main/resources/META-INF/batch-jobs/job_restart_second_transition.xml b/com.ibm.jbatch.tck/src/main/resources/META-INF/batch-jobs/job_restart_second_transition.xml new file mode 100644 index 0000000..fd178cf --- /dev/null +++ b/com.ibm.jbatch.tck/src/main/resources/META-INF/batch-jobs/job_restart_second_transition.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/com.ibm.jbatch.tck/src/main/resources/META-INF/batch.xml b/com.ibm.jbatch.tck/src/main/resources/META-INF/batch.xml index 05e74b0..0b05ad8 100755 --- a/com.ibm.jbatch.tck/src/main/resources/META-INF/batch.xml +++ b/com.ibm.jbatch.tck/src/main/resources/META-INF/batch.xml @@ -56,6 +56,7 @@ + @@ -127,5 +128,6 @@ +