public async Task GivenNullMetadata_WhenRequestIsPrepared_ThenItShouldNotCreateEntryComponent() { var context = new FhirTransactionContext(ChangeFeedGenerator.Generate()); await _patientPipeline.PrepareRequestAsync(context, DefaultCancellationToken); Assert.Null(context.Request.Patient); }
private async Task ExecuteAndValidateRetryThenThrowTimeOut(Exception ex) { ChangeFeedEntry changeFeedEntry = ChangeFeedGenerator.Generate(); _fhirTransactionPipeline.ProcessAsync(changeFeedEntry, DefaultCancellationToken).Throws(ex); await Assert.ThrowsAsync <TimeoutRejectedException>(() => _retryableFhirTransactionPipeline.ProcessAsync(changeFeedEntry, DefaultCancellationToken)); }
public void GivenNoUpdateToExistingPatient_WhenResponseIsProcessed_ThenItShouldBeNoOp() { // Simulate there is no update to patient resource (and therefore no response). var context = new FhirTransactionContext(ChangeFeedGenerator.Generate()); context.Response.Patient = null; _patientPipeline.ProcessResponse(context); }
private async Task ExecuteAndValidate(Exception ex, int expectedNumberOfCalls) { ChangeFeedEntry changeFeedEntry = ChangeFeedGenerator.Generate(); _fhirTransactionPipeline.ProcessAsync(changeFeedEntry, DefaultCancellationToken).Throws(ex); await Assert.ThrowsAsync(ex.GetType(), () => _retryableFhirTransactionPipeline.ProcessAsync(changeFeedEntry, DefaultCancellationToken)); await _fhirTransactionPipeline.Received(expectedNumberOfCalls).ProcessAsync(changeFeedEntry, DefaultCancellationToken); }
public async Task GivenAnExistingEndpointWithDifferentAddress_WhenRequestIsPrepared_ThenFhirResourceValidationExceptionShouldBeThrown() { var context = new FhirTransactionContext(ChangeFeedGenerator.Generate()); Endpoint endpoint = FhirResourceBuilder.CreateEndpointResource(address: "https://dicom2"); _fhirService.RetrieveEndpointAsync(Arg.Any <string>(), DefaultCancellationToken).Returns(endpoint); await Assert.ThrowsAsync <FhirResourceValidationException>(() => _endpointPipeline.PrepareRequestAsync(context, DefaultCancellationToken)); }
private async Task <FhirTransactionRequestEntry> BuildImagingStudyEntryComponent(string studyInstanceUid, string seriesInstanceUid, string sopInstanceUid, string patientResourceId, bool addMetadata = true) { ChangeFeedEntry changeFeedEntry = ChangeFeedGenerator.Generate( action: ChangeFeedAction.Create, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, sopInstanceUid: sopInstanceUid, metadata: addMetadata ? FhirTransactionContextBuilder.CreateDicomDataset() : null); return(await PrepareRequestAsync(changeFeedEntry, patientResourceId)); }
public async Task GivenNoResourceToProcess_WhenProcessed_ThenTransactionShouldBeExecuted() { // Setup the pipeline step to simulate no requests. IFhirTransactionPipelineStep pipelineStep = Substitute.For <IFhirTransactionPipelineStep>(); _fhirTransactionPipelineSteps.Add(pipelineStep); // Process await _fhirTransactionPipeline.ProcessAsync(ChangeFeedGenerator.Generate(), DefaultCancellationToken); // There should not be any response. pipelineStep.DidNotReceiveWithAnyArgs().ProcessResponse(default);
public static FhirTransactionContext DefaultFhirTransactionContext(DicomDataset metadata = null) { var context = new FhirTransactionContext(ChangeFeedGenerator.Generate(metadata: metadata ?? CreateDicomDataset())) { UtcDateTimeOffset = TimeSpan.Zero, }; context.Request.Patient = FhirTransactionRequestEntryGenerator.GenerateDefaultCreateRequestEntry <Patient>(); context.Request.ImagingStudy = FhirTransactionRequestEntryGenerator.GenerateDefaultCreateRequestEntry <ImagingStudy>(); context.Request.Endpoint = FhirTransactionRequestEntryGenerator.GenerateDefaultCreateRequestEntry <Endpoint>(); return(context); }
public async Task GivenAnExistingEndpointWithMatchingAddress_WhenRequestIsPrepared_ThenCorrectRequestEntryShouldBeCreated() { var context = new FhirTransactionContext(ChangeFeedGenerator.Generate()); Endpoint endpoint = FhirResourceBuilder.CreateEndpointResource(address: DefaultDicomWebEndpoint); _fhirService.RetrieveEndpointAsync(Arg.Any <string>(), DefaultCancellationToken).Returns(endpoint); await _endpointPipeline.PrepareRequestAsync(context, DefaultCancellationToken); FhirTransactionRequestEntry actualEndPointEntry = context.Request.Endpoint; ValidationUtility.ValidateRequestEntryMinimumRequirementForNoChange(endpoint.ToServerResourceId(), actualEndPointEntry); }
public async Task GivenMultipleChangeFeedEntries_WhenProcessed_ThenEachChangeFeedEntryShouldBeProcessed() { ChangeFeedEntry[] changeFeeds = new[] { ChangeFeedGenerator.Generate(1), ChangeFeedGenerator.Generate(2), ChangeFeedGenerator.Generate(3), }; _changeFeedRetrieveService.RetrieveChangeFeedAsync(0, DefaultCancellationToken).Returns(changeFeeds); await ExecuteProcessAsync(); await _fhirTransactionPipeline.ReceivedWithAnyArgs(3).ProcessAsync(default, default);
public void GivenARequestToCreateAPatient_WhenResponseIsOK_ThenResourceConflictExceptionShouldBeThrown() { var response = new Bundle.ResponseComponent(); response.AddAnnotation(HttpStatusCode.OK); var context = new FhirTransactionContext(ChangeFeedGenerator.Generate()); context.Request.Patient = FhirTransactionRequestEntryGenerator.GenerateDefaultCreateRequestEntry <Patient>(); context.Response.Patient = new FhirTransactionResponseEntry(response, new Patient()); Assert.Throws <ResourceConflictException>(() => _patientPipeline.ProcessResponse(context)); }
public void GivenARequestToUpdateAPatient_WhenResponseIsOK_ThenItShouldBeNoOp() { var response = new Bundle.ResponseComponent(); response.AddAnnotation(HttpStatusCode.OK); var context = new FhirTransactionContext(ChangeFeedGenerator.Generate()); context.Request.Patient = FhirTransactionRequestEntryGenerator.GenerateDefaultUpdateRequestEntry <Patient>( new ServerResourceId(ResourceType.Patient, "123")); context.Response.Patient = new FhirTransactionResponseEntry(response, new Patient()); _patientPipeline.ProcessResponse(context); }
public async Task GivenAValidCreateChangeFeed_WhenBuilt_ThenCorrectEntryComponentShouldBeCreated() { const string studyInstanceUid = "1"; const string seriesInstanceUid = "2"; const string sopInstanceUid = "3"; const string patientResourceId = "p1"; ChangeFeedEntry changeFeedEntry = ChangeFeedGenerator.Generate( action: ChangeFeedAction.Create, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, sopInstanceUid: sopInstanceUid); FhirTransactionRequestEntry entry = await BuildImagingStudyEntryComponent(studyInstanceUid, seriesInstanceUid, sopInstanceUid, patientResourceId); ValidationUtility.ValidateRequestEntryMinimumRequirementForWithChange(FhirTransactionRequestMode.Create, "ImagingStudy", Bundle.HTTPVerb.POST, entry); ImagingStudy imagingStudy = Assert.IsType <ImagingStudy>(entry.Resource); string jsonString; jsonString = JsonSerializer.Serialize(entry); Assert.IsType <ClientResourceId>(entry.ResourceId); Assert.Equal(ImagingStudy.ImagingStudyStatus.Available, imagingStudy.Status); Assert.Null(entry.Request.IfMatch); ValidationUtility.ValidateResourceReference("Patient/p1", imagingStudy.Subject); Assert.Collection( imagingStudy.Identifier, identifier => ValidationUtility.ValidateIdentifier("urn:dicom:uid", $"urn:oid:{studyInstanceUid}", identifier), identifier => ValidationUtility.ValidateAccessionNumber(null, FhirTransactionContextBuilder.DefaultAccessionNumber, identifier)); Assert.Collection( imagingStudy.Series, series => { Assert.Equal(seriesInstanceUid, series.Uid); Assert.Collection( series.Instance, instance => Assert.Equal(sopInstanceUid, instance.Uid)); }); ValidateDicomFilePropertiesAreCorrectlyMapped(imagingStudy, series: imagingStudy.Series.First(), instance: imagingStudy.Series.First().Instance.First()); }
public async Task WhenDoesNotEnforceAllFields_AndPropertyNotRequired_DoesNotThrowError() { _dicomCastConfig.Features.EnforceValidationOfTagValues = false; _propertySynchronizer.When(synchronizer => synchronizer.Synchronize(Arg.Any <DicomDataset>(), Arg.Any <Patient>(), isNewPatient: false)).Do(synchronizer => { throw new InvalidDicomTagValueException("invalid tag", "invalid tag"); }); IEnumerable <IPatientPropertySynchronizer> patientPropertySynchronizers = new List <IPatientPropertySynchronizer>() { _propertySynchronizer, }; PatientSynchronizer patientSynchronizer = new PatientSynchronizer(patientPropertySynchronizers, Options.Create(_dicomCastConfig), _exceptionStore); FhirTransactionContext context = new FhirTransactionContext(ChangeFeedGenerator.Generate(metadata: DefaultDicomDataset)); var patient = new Patient(); await patientSynchronizer.SynchronizeAsync(context, patient, false, DefaultCancellationToken); }
public async Task GivenAChangeFeedEntryForCreate_WhenPreparingTheRequest_ThenCreateHandlerIsCalled() { const string studyInstanceUid = "1"; const string seriesInstanceUid = "2"; const string sopInstanceUid = "3"; ChangeFeedEntry changeFeed = ChangeFeedGenerator.Generate( action: ChangeFeedAction.Create, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, sopInstanceUid: sopInstanceUid); var fhirTransactionContext = new FhirTransactionContext(changeFeed); await _imagingStudyPipeline.PrepareRequestAsync(fhirTransactionContext, DefaultCancellationToken); await _imagingStudyUpsertHandler.Received(1).BuildAsync(fhirTransactionContext, DefaultCancellationToken); }
public async Task WhenPatialValidationDisabled_AndError_ThrowsError() { _dicomCastConfig.Features.IgnoreSyncOfInvalidTagValue = false; _propertySynchronizer.When(synchronizer => synchronizer.Synchronize(Arg.Any <DicomDataset>(), Arg.Any <Patient>(), isNewPatient: false)).Do(synchronizer => { throw new InvalidDicomTagValueException("invalid tag", "invalid tag"); }); IEnumerable <IPatientPropertySynchronizer> patientPropertySynchronizers = new List <IPatientPropertySynchronizer>() { _propertySynchronizer, }; PatientSynchronizer patientSynchronizer = new PatientSynchronizer(patientPropertySynchronizers, Options.Create(_dicomCastConfig), _exceptionStore); FhirTransactionContext context = new FhirTransactionContext(ChangeFeedGenerator.Generate(metadata: DefaultDicomDataset)); var patient = new Patient(); await Assert.ThrowsAsync <InvalidDicomTagValueException>(() => patientSynchronizer.SynchronizeAsync(context, patient, false, DefaultCancellationToken)); }
public async Task GivenAChangeFeedEntryForDelete_WhenBuilt_ThenDeleteHandlerIsCalled() { const string studyInstanceUid = "1"; const string seriesInstanceUid = "2"; const string sopInstanceUid = "3"; const string patientResourceId = "p1"; ChangeFeedEntry changeFeed = ChangeFeedGenerator.Generate( action: ChangeFeedAction.Delete, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, sopInstanceUid: sopInstanceUid); var fhirTransactionContext = new FhirTransactionContext(changeFeed); fhirTransactionContext.Request.Patient = FhirTransactionRequestEntryGenerator.GenerateDefaultNoChangeRequestEntry <Patient>( new ServerResourceId(ResourceType.Patient, patientResourceId)); await _imagingStudyPipeline.PrepareRequestAsync(fhirTransactionContext, DefaultCancellationToken); await _imagingStudyDeleteHandler.Received(1).BuildAsync(fhirTransactionContext, DefaultCancellationToken); }
public async Task GivenEndpointDoesNotAlreadyExist_WhenRequestIsPrepared_ThenCorrentRequestEntryShouldBeCreated() { var context = new FhirTransactionContext(ChangeFeedGenerator.Generate()); await _endpointPipeline.PrepareRequestAsync(context, DefaultCancellationToken); FhirTransactionRequestEntry actualEndpointEntry = context.Request.Endpoint; ValidationUtility.ValidateRequestEntryMinimumRequirementForWithChange(FhirTransactionRequestMode.Create, "Endpoint", Bundle.HTTPVerb.POST, actualEndpointEntry); Assert.Equal($"name={EndpointName}&connection-type={EndpointConnectionTypeSystem}|{EndpointConnectionTypeCode}", actualEndpointEntry.Request.IfNoneExist); Endpoint endpoint = Assert.IsType <Endpoint>(actualEndpointEntry.Resource); Assert.Equal(EndpointName, endpoint.Name); Assert.Equal(Endpoint.EndpointStatus.Active, endpoint.Status); Assert.NotNull(endpoint.ConnectionType); Assert.Equal(EndpointConnectionTypeSystem, endpoint.ConnectionType.System); Assert.Equal(EndpointConnectionTypeCode, endpoint.ConnectionType.Code); Assert.Equal(_configuration.Endpoint.ToString(), endpoint.Address); Assert.Equal(EndpointPayloadTypeText, endpoint.PayloadType.First().Text); Assert.Equal(new[] { DicomMimeType }, endpoint.PayloadMimeType); }
private async Task <FhirTransactionRequestEntry> BuildImagingStudyEntryComponent(string studyInstanceUid, string seriesInstanceUid, string sopInstanceUid, string patientResourceId) { ChangeFeedEntry changeFeedEntry = ChangeFeedGenerator.Generate(action: ChangeFeedAction.Delete, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, sopInstanceUid: sopInstanceUid); return(await PrepareRequestAsync(changeFeedEntry, patientResourceId)); }
public async Task WhenThrowAnExceptionInProcess_ThrowTheSameException() { var pipelineStep = new MockFhirTransactionPipelineStep() { OnPrepareRequestAsyncCalled = (context, cancellationToken) => { throw new Exception(); }, }; _fhirTransactionPipelineSteps.Add(pipelineStep); // Process await Assert.ThrowsAsync <Exception>(() => _fhirTransactionPipeline.ProcessAsync(ChangeFeedGenerator.Generate(), DefaultCancellationToken)); }
public async Task GivenMissingPatientId_WhenPreparingTheRequest_ThenMissingRequiredDicomTagExceptionShouldBeThrown() { var context = new FhirTransactionContext(ChangeFeedGenerator.Generate(metadata: new DicomDataset())); await Assert.ThrowsAsync <MissingRequiredDicomTagException>(() => _patientPipeline.PrepareRequestAsync(context, DefaultCancellationToken)); }
public async Task GivenAResourceToProcess_WhenProcessed_ThenTransactionShouldBeExecuted(FhirTransactionRequestMode requestMode) { // Setup the pipeline step to simulate creating/updating patient. var patientRequest = new FhirTransactionRequestEntry( requestMode, new Bundle.RequestComponent(), new ClientResourceId(), new Patient()); var pipelineStep = new MockFhirTransactionPipelineStep() { OnPrepareRequestAsyncCalled = (context, cancellationToken) => { context.Request.Patient = patientRequest; Assert.Equal(DefaultCancellationToken, cancellationToken); }, }; _fhirTransactionPipelineSteps.Add(pipelineStep); // Setup the transaction executor to return response. var responseBundle = new Bundle(); var responseEntry = new Bundle.EntryComponent() { Response = new Bundle.ResponseComponent(), Resource = new Patient(), }; responseBundle.Entry.Add(responseEntry); _fhirTransactionExecutor.ExecuteTransactionAsync( Arg.Any <Bundle>(), DefaultCancellationToken) .Returns(call => { // Make sure the request bundle is correct. Bundle requestBundle = call.ArgAt <Bundle>(0); Assert.NotNull(requestBundle); Assert.Equal(Bundle.BundleType.Transaction, requestBundle.Type); Assert.Collection( requestBundle.Entry, entry => { Assert.Equal(patientRequest.ResourceId.ToString(), entry.FullUrl); Assert.Equal(patientRequest.Request, entry.Request); Assert.Equal(patientRequest.Resource, entry.Resource); }); return(responseBundle); }); // Process await _fhirTransactionPipeline.ProcessAsync(ChangeFeedGenerator.Generate(), DefaultCancellationToken); // The response should have been processed. Assert.NotNull(_capturedFhirTransactionContext); FhirTransactionResponseEntry patientResponse = _capturedFhirTransactionContext.Response.Patient; Assert.NotNull(patientResponse); Assert.Equal(responseEntry.Response, patientResponse.Response); Assert.Equal(responseEntry.Resource, patientResponse.Resource); }
private static FhirTransactionContext CreateFhirTransactionContext() { return(new FhirTransactionContext(ChangeFeedGenerator.Generate(metadata: DefaultDicomDataset))); }