From ad470cff726d800cbf9baa49abd6a9a536781ec0 Mon Sep 17 00:00:00 2001 From: leif stawnyczy Date: Wed, 20 Mar 2024 10:48:00 -0400 Subject: [PATCH] adding spy override --- .../jpa/batch2/JpaJobPersistenceImplTest.java | 3 ++ ...tractIJobPersistenceSpecificationTest.java | 10 +++- .../batch2/test/IJobMaintenanceActions.java | 52 +++++++++++++++++-- .../test/configs/SpyOverrideConfig.java | 27 ++++++++++ 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/configs/SpyOverrideConfig.java diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java index 20b89e74224..999bce20db1 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImplTest.java @@ -27,6 +27,7 @@ import ca.uhn.fhir.testjob.TestJobDefinitionUtils; import ca.uhn.fhir.testjob.models.FirstStepOutput; import ca.uhn.fhir.util.JsonUtil; import ca.uhn.hapi.fhir.batch2.test.AbstractIJobPersistenceSpecificationTest; +import ca.uhn.hapi.fhir.batch2.test.configs.SpyOverrideConfig; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import jakarta.annotation.Nonnull; @@ -38,6 +39,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; @@ -71,6 +73,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @ContextConfiguration(classes = { Batch2FastSchedulerConfig.class }) +@Import(SpyOverrideConfig.class) public class JpaJobPersistenceImplTest extends BaseJpaR4Test { public static final String JOB_DEFINITION_ID = "definition-id"; diff --git a/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/AbstractIJobPersistenceSpecificationTest.java b/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/AbstractIJobPersistenceSpecificationTest.java index c8e475c4af7..303b5b2882a 100644 --- a/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/AbstractIJobPersistenceSpecificationTest.java +++ b/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/AbstractIJobPersistenceSpecificationTest.java @@ -23,6 +23,7 @@ package ca.uhn.hapi.fhir.batch2.test; import ca.uhn.fhir.batch2.api.IJobMaintenanceService; import ca.uhn.fhir.batch2.api.IJobPersistence; import ca.uhn.fhir.batch2.api.RunOutcome; +import ca.uhn.fhir.batch2.channel.BatchJobSender; import ca.uhn.fhir.batch2.coordinator.JobDefinitionRegistry; import ca.uhn.fhir.batch2.model.JobDefinition; import ca.uhn.fhir.batch2.model.JobDefinitionStep; @@ -77,6 +78,9 @@ public abstract class AbstractIJobPersistenceSpecificationTest implements IJobMa @Autowired private IJobMaintenanceService myMaintenanceService; + @Autowired + private BatchJobSender myBatchJobSender; + public PlatformTransactionManager getTransactionManager() { return myTransactionManager; } @@ -110,7 +114,7 @@ public abstract class AbstractIJobPersistenceSpecificationTest implements IJobMa public JobInstance createInstance(JobDefinition theJobDefinition) { JobDefinition jobDefinition = theJobDefinition == null ? withJobDefinition(false) : theJobDefinition; - if (myJobDefinitionRegistry.getJobDefinition(theJobDefinition.getJobDefinitionId(), theJobDefinition.getJobDefinitionVersion()).isEmpty()) { + if (myJobDefinitionRegistry.getJobDefinition(jobDefinition.getJobDefinitionId(), jobDefinition.getJobDefinitionVersion()).isEmpty()) { myJobDefinitionRegistry.addJobDefinition(jobDefinition); } @@ -185,6 +189,10 @@ public abstract class AbstractIJobPersistenceSpecificationTest implements IJobMa myMaintenanceService.enableMaintenancePass(theToEnable); } + public BatchJobSender getBatchJobSender() { + return myBatchJobSender; + } + public void createChunksInStates(JobMaintenanceStateInformation theJobMaintenanceStateInformation) { // should have as many input workchunks as output workchunks // unless we have newly created ones somewhere diff --git a/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/IJobMaintenanceActions.java b/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/IJobMaintenanceActions.java index 54e154e3d56..a03ee9c95c8 100644 --- a/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/IJobMaintenanceActions.java +++ b/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/IJobMaintenanceActions.java @@ -1,6 +1,8 @@ package ca.uhn.hapi.fhir.batch2.test; +import ca.uhn.fhir.batch2.channel.BatchJobSender; import ca.uhn.fhir.batch2.model.JobDefinition; +import ca.uhn.fhir.batch2.model.JobWorkNotification; import ca.uhn.fhir.batch2.model.WorkChunk; import ca.uhn.hapi.fhir.batch2.test.models.JobMaintenanceStateInformation; import org.junit.jupiter.api.Test; @@ -16,6 +18,11 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; public interface IJobMaintenanceActions extends IWorkChunkCommon, WorkChunkTestConstants { @@ -25,6 +32,8 @@ public interface IJobMaintenanceActions extends IWorkChunkCommon, WorkChunkTestC void createChunksInStates(JobMaintenanceStateInformation theInitialState); + BatchJobSender getBatchJobSender(); + @Test default void test_gatedJob_stepReady_advances() { // given @@ -35,12 +44,13 @@ public interface IJobMaintenanceActions extends IWorkChunkCommon, WorkChunkTestC 2|READY,2|QUEUED """; enableMaintenanceRunner(false); - JobMaintenanceStateInformation result = setupGatedWorkChunkTransitionTest(initialState); + JobMaintenanceStateInformation result = setupGatedWorkChunkTransitionTest(initialState, true); // setup createChunksInStates(result); // TEST run job maintenance - force transition + doNothing().when(getBatchJobSender()).sendWorkChannelMessage(any(JobWorkNotification.class)); enableMaintenanceRunner(true); runMaintenancePass(); @@ -112,13 +122,15 @@ public interface IJobMaintenanceActions extends IWorkChunkCommon, WorkChunkTestC default void testGatedStep2NotReady_notAdvance(String theChunkState) { // given enableMaintenanceRunner(false); - JobMaintenanceStateInformation result = setupGatedWorkChunkTransitionTest(theChunkState); + JobMaintenanceStateInformation result = setupGatedWorkChunkTransitionTest(theChunkState, true); // setup createChunksInStates(result); // TEST run job maintenance - force transition enableMaintenanceRunner(true); + lenient().doNothing().when(getBatchJobSender()).sendWorkChannelMessage(any(JobWorkNotification.class)); + runMaintenancePass(); // verify @@ -151,7 +163,7 @@ public interface IJobMaintenanceActions extends IWorkChunkCommon, WorkChunkTestC """ }) default void testGatedStep2ReadyToAdvance_advanceToStep3(String theChunkState) { - JobMaintenanceStateInformation result = setupGatedWorkChunkTransitionTest(theChunkState); + JobMaintenanceStateInformation result = setupGatedWorkChunkTransitionTest(theChunkState, true); // setup enableMaintenanceRunner(false); @@ -159,16 +171,46 @@ public interface IJobMaintenanceActions extends IWorkChunkCommon, WorkChunkTestC // TEST run job maintenance - force transition enableMaintenanceRunner(true); + lenient().doNothing().when(getBatchJobSender()).sendWorkChannelMessage(any(JobWorkNotification.class)); + runMaintenancePass(); // verify verifyWorkChunkFinalStates(result); } + @ParameterizedTest + @ValueSource(strings = { + """ + # READY chunks should transition; others should stay + 1|COMPLETED + 2|READY,2|QUEUED + 2|READY,2|QUEUED + 2|COMPLETED + 2|IN_PROGRESS + 3|IN_PROGRESS + """ + }) + default void test_ungatedJob_advancesSteps(String theChunkState) { + JobMaintenanceStateInformation result = setupGatedWorkChunkTransitionTest(theChunkState, false); - private JobMaintenanceStateInformation setupGatedWorkChunkTransitionTest(String theChunkState) { + // setup + enableMaintenanceRunner(false); + createChunksInStates(result); + + // TEST run job maintenance - force transition + enableMaintenanceRunner(true); + lenient().doNothing().when(getBatchJobSender()).sendWorkChannelMessage(any(JobWorkNotification.class)); + + runMaintenancePass(); + + // verify + verifyWorkChunkFinalStates(result); + } + + private JobMaintenanceStateInformation setupGatedWorkChunkTransitionTest(String theChunkState, boolean theIsGated) { // get the job def and store the instance - JobDefinition definition = withJobDefinition(true); + JobDefinition definition = withJobDefinition(theIsGated); String instanceId = createAndStoreJobInstance(definition); JobMaintenanceStateInformation stateInformation = new JobMaintenanceStateInformation(instanceId, definition); stateInformation.initialize(theChunkState); diff --git a/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/configs/SpyOverrideConfig.java b/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/configs/SpyOverrideConfig.java new file mode 100644 index 00000000000..46331d1c219 --- /dev/null +++ b/hapi-fhir-storage-batch2-test-utilities/src/main/java/ca/uhn/hapi/fhir/batch2/test/configs/SpyOverrideConfig.java @@ -0,0 +1,27 @@ +package ca.uhn.hapi.fhir.batch2.test.configs; + +import ca.uhn.fhir.batch2.channel.BatchJobSender; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import static org.mockito.Mockito.spy; + +/** + * Provides spying overrides of beans we want to spy on. + * + * We spy the BatchJobSender so we can test state transitions without + * actually sending messages onto the queue + */ +@Configuration +public class SpyOverrideConfig { + @Autowired + BatchJobSender myRealJobSender; + + @Primary + @Bean + public BatchJobSender batchJobSenderSpy() { + return spy(myRealJobSender); + } +}