public async void GivenAMultipartRequestWithAnInvalidMultipartSection_WhenStoring_TheServerShouldReturnAccepted() { var request = new HttpRequestMessage(HttpMethod.Post, "studies"); request.Headers.Add(HeaderNames.Accept, DicomWebClient.MediaTypeApplicationDicomJson.MediaType); var multiContent = new MultipartContent("related"); multiContent.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("type", $"\"{DicomWebClient.MediaTypeApplicationDicom.MediaType}\"")); var byteContent = new ByteArrayContent(Array.Empty <byte>()); byteContent.Headers.ContentType = DicomWebClient.MediaTypeApplicationDicom; multiContent.Add(byteContent); string studyInstanceUID = TestUidGenerator.Generate(); try { DicomFile validFile = Samples.CreateRandomDicomFile(studyInstanceUID); await using (MemoryStream stream = _recyclableMemoryStreamManager.GetStream()) { await validFile.SaveAsync(stream); var validByteContent = new ByteArrayContent(stream.ToArray()); validByteContent.Headers.ContentType = DicomWebClient.MediaTypeApplicationDicom; multiContent.Add(validByteContent); } request.Content = multiContent; DicomWebResponse <DicomDataset> response = await _client.PostMultipartContentAsync(multiContent, "studies"); Assert.Equal(HttpStatusCode.Accepted, response.StatusCode); ValidationHelpers.ValidateReferencedSopSequence( response.Value, ConvertToReferencedSopSequenceEntry(validFile.Dataset)); } finally { await _client.DeleteStudyAsync(studyInstanceUID); } }
public async Task GivenMultipleErrors_WhenGettingPaginatedResults_ThenProperlyPaginateErrors() { // Add instances DicomTag tag = DicomTag.PatientName; long[] watermarks = new long[] { await AddInstanceAsync(TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate()), await AddInstanceAsync(TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate()), await AddInstanceAsync(TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate()), await AddInstanceAsync(TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate()), }; int tagKey = await AddTagAsync(tag); // Add multiple errors await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, ValidationErrorCode.PersonNameExceedMaxGroups, watermarks[0]); await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, ValidationErrorCode.ExceedMaxLength, watermarks[1]); await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, ValidationErrorCode.InvalidCharacters, watermarks[2]); await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, ValidationErrorCode.PersonNameGroupExceedMaxLength, watermarks[3]); IReadOnlyList <ExtendedQueryTagError> errors; // Page 1 errors = await _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag.GetPath(), 1, 0); Assert.Equal(1, errors.Count); Assert.Equal(errors[0].ErrorMessage, ValidationErrorCode.PersonNameExceedMaxGroups.GetMessage()); // Page 2 errors = await _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag.GetPath(), 2, 1); Assert.Equal(2, errors.Count); Assert.Equal(errors[0].ErrorMessage, ValidationErrorCode.ExceedMaxLength.GetMessage()); Assert.Equal(errors[1].ErrorMessage, ValidationErrorCode.InvalidCharacters.GetMessage()); // Page 3 errors = await _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag.GetPath(), 1, 3); Assert.Equal(1, errors.Count); Assert.Equal(errors[0].ErrorMessage, ValidationErrorCode.PersonNameGroupExceedMaxLength.GetMessage()); }
public async Task GivenStoredDicomFile_WhenRetrievingMetadataForInstance_ThenMetadataIsRetrievedCorrectly() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); DicomDataset storedInstance = await PostDicomFileAsync(ResourceType.Instance, studyInstanceUid, seriesInstanceUid, sopInstanceUid, dataSet : GenerateNewDataSet()); using DicomWebAsyncEnumerableResponse <DicomDataset> response = await _client.RetrieveInstanceMetadataAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal("application/dicom+json", response.ContentHeaders.ContentType.MediaType); DicomDataset[] datasets = await response.ToArrayAsync(); Assert.Single(datasets); ValidateResponseMetadataDataset(storedInstance, datasets[0]); }
public async Task GivenUnsupportedInternalTransferSyntax_WhenRetrieveInstance_ThenServerShouldReturnNotAcceptable() { var studyInstanceUid = TestUidGenerator.Generate(); var seriesInstanceUid = TestUidGenerator.Generate(); var sopInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFileWith8BitPixelData( studyInstanceUid, seriesInstanceUid, sopInstanceUid, transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); await InternalStoreAsync(new[] { dicomFile }); DicomWebException exception = await Assert.ThrowsAsync <DicomWebException>(() => _client.RetrieveInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, dicomTransferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID)); Assert.Equal(HttpStatusCode.NotAcceptable, exception.StatusCode); }
public async Task GivenRetrieveInstanceMetadataRequest_WhenIfNoneMatchIsNotPresent_ThenResponseMetadataIsReturnedWithETag() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); DicomDataset storedInstance = await PostDicomFileAsync(ResourceType.Instance, studyInstanceUid, seriesInstanceUid, sopInstanceUid, dataSet : GenerateNewDataSet()); using DicomWebAsyncEnumerableResponse <DicomDataset> response = await _client.RetrieveInstanceMetadataAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(KnownContentTypes.ApplicationDicomJson, response.ContentHeaders.ContentType.MediaType); DicomDataset[] datasets = await response.ToArrayAsync(); Assert.Single(datasets); ValidateResponseMetadataDataset(storedInstance, datasets[0]); }
public ChangeFeedServiceTests() { _changeFeedEntries = new List<ChangeFeedEntry> { new ChangeFeedEntry(1, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 1, 1, ChangeFeedState.Current), new ChangeFeedEntry(2, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 2, 2, ChangeFeedState.Current), new ChangeFeedEntry(3, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 3, 3, ChangeFeedState.Current), new ChangeFeedEntry(4, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 4, 4, ChangeFeedState.Current), new ChangeFeedEntry(5, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 5, 5, ChangeFeedState.Current), new ChangeFeedEntry(6, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 6, 6, ChangeFeedState.Current), new ChangeFeedEntry(7, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 7, 7, ChangeFeedState.Current), new ChangeFeedEntry(8, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 8, 8, ChangeFeedState.Current), new ChangeFeedEntry(9, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 9, 9, ChangeFeedState.Current), new ChangeFeedEntry(10, DateTime.Now, ChangeFeedAction.Create, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate(), 10, 10, ChangeFeedState.Current), }; _changeFeedStore = Substitute.For<IChangeFeedStore>(); _changeFeedStore.GetChangeFeedAsync(offset: default, limit: default, cancellationToken: default)
public async Task GivenMultipleFrames_WhenRetrieveFrame_ThenServerShouldReturnExpectedContent() { var studyInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile1 = Samples.CreateRandomDicomFileWithPixelData(studyInstanceUid, frames: 3); DicomPixelData pixelData = DicomPixelData.Create(dicomFile1.Dataset); var dicomInstance = dicomFile1.Dataset.ToInstanceIdentifier(); await InternalStoreAsync(new[] { dicomFile1 }); DicomWebResponse <IReadOnlyList <Stream> > frames = await _client.RetrieveFramesAsync(dicomInstance.StudyInstanceUid, dicomInstance.SeriesInstanceUid, dicomInstance.SopInstanceUid, frames : new[] { 1, 2 }, dicomTransferSyntax : "*"); Assert.NotNull(frames); Assert.Equal(HttpStatusCode.OK, frames.StatusCode); Assert.Equal(2, frames.Value.Count); Assert.Equal(KnownContentTypes.MultipartRelated, frames.Content.Headers.ContentType.MediaType); Assert.Equal(pixelData.GetFrame(0).Data, frames.Value[0].ToByteArray()); Assert.Equal(pixelData.GetFrame(1).Data, frames.Value[1].ToByteArray()); }
public async Task GivenMultipleTagsOnSameInstance_WhenDeleteInstance_ThenAssociatedErrorsShouldBeRemoved() { string studyUid1 = TestUidGenerator.Generate(); string seriesUid1 = TestUidGenerator.Generate(); string instanceUid1 = TestUidGenerator.Generate(); string studyUid2 = TestUidGenerator.Generate(); string seriesUid2 = TestUidGenerator.Generate(); string instanceUid2 = TestUidGenerator.Generate(); // add instances long watermark1 = await AddInstanceAsync(studyUid1, seriesUid1, instanceUid1); long watermark2 = await AddInstanceAsync(studyUid2, seriesUid2, instanceUid2); // add tags DicomTag tag1 = DicomTag.DeviceSerialNumber; int tagKey1 = await AddTagAsync(tag1); DicomTag tag2 = DicomTag.DeviceID; int tagKey2 = await AddTagAsync(tag2); // add errors ValidationErrorCode errorCode = ValidationErrorCode.DateIsInvalid; // both tag has error on instance1 await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey1, errorCode, watermark1); await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey2, errorCode, watermark1); // Only tag2 has error on instance2 await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey2, errorCode, watermark2); // delete instance1 await _indexDataStore.DeleteInstanceIndexAsync(new InstanceIdentifier(studyUid1, seriesUid1, instanceUid1, DefaultPartition.Key)); // check errors Assert.Empty(await _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag1.GetPath(), 1, 0)); var errors = await _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag2.GetPath(), int.MaxValue, 0); Assert.Single(errors); Assert.Equal(studyUid2, errors[0].StudyInstanceUid); Assert.Equal(seriesUid2, errors[0].SeriesInstanceUid); Assert.Equal(instanceUid2, errors[0].SopInstanceUid); }
public async Task GivenMultipleSeriesInStudy_WhenDeletingInstance_TheServerShouldReturnNoContentAndOnlyTargetSeriesIsDeleted() { var studyInstanceUid = TestUidGenerator.Generate(); var seriesInstanceUid1 = TestUidGenerator.Generate(); var seriesInstanceUid2 = TestUidGenerator.Generate(); var sopInstanceUid1 = TestUidGenerator.Generate(); var sopInstanceUid2 = TestUidGenerator.Generate(); await CreateFile(studyInstanceUid, seriesInstanceUid1, sopInstanceUid1); await CreateFile(studyInstanceUid, seriesInstanceUid2, sopInstanceUid2); await _client.DeleteInstanceAsync(studyInstanceUid, seriesInstanceUid1, sopInstanceUid1); await VerifySopInstanceRemoval(studyInstanceUid, seriesInstanceUid1, sopInstanceUid1); await VerifySeriesRemoval(studyInstanceUid, seriesInstanceUid1); await VerifyRemainingSeries(studyInstanceUid, seriesInstanceUid2, 1); await VerifyRemainingStudy(studyInstanceUid, 1); }
public async void GivenAllDifferentStudyInstanceUIDs_WhenStoringWithProvidedStudyInstanceUID_TheServerShouldReturnConflict() { DicomFile dicomFile1 = Samples.CreateRandomDicomFile(); DicomFile dicomFile2 = Samples.CreateRandomDicomFile(); var studyInstanceUID = TestUidGenerator.Generate(); DicomWebException <DicomDataset> exception = await Assert.ThrowsAsync <DicomWebException <DicomDataset> >(() => _client.StoreAsync( new[] { dicomFile1, dicomFile2 }, studyInstanceUID)); Assert.Equal(HttpStatusCode.Conflict, exception.StatusCode); Assert.NotNull(exception.Value); Assert.True(exception.Value.Count() == 1); ValidationHelpers.ValidateFailedSopSequence( exception.Value, ConvertToFailedSopSequenceEntry(dicomFile1.Dataset, MismatchStudyInstanceUidFailureCode), ConvertToFailedSopSequenceEntry(dicomFile2.Dataset, MismatchStudyInstanceUidFailureCode)); }
public async Task GivenUnsupportedInternalTransferSyntax_WhenRetrieveInstanceWithOriginalTransferSyntax_ThenServerShouldReturnOriginalContent() { var studyInstanceUid = TestUidGenerator.Generate(); var seriesInstanceUid = TestUidGenerator.Generate(); var sopInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFileWith8BitPixelData( studyInstanceUid, seriesInstanceUid, sopInstanceUid, transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); await InternalStoreAsync(new[] { dicomFile }); using DicomWebResponse <DicomFile> instancesInStudy = await _client.RetrieveInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, dicomTransferSyntax : "*"); Assert.Equal(dicomFile.ToByteArray(), (await instancesInStudy.GetValueAsync()).ToByteArray()); }
public async Task GivenRetrieveStudyMetadataRequest_WhenIfNoneMatchMatchesETag_ThenNotModifiedResponseIsReturned() { string studyInstanceUid = TestUidGenerator.Generate(); DicomDataset storedInstance = await PostDicomFileAsync(ResourceType.Study, studyInstanceUid, dataSet : GenerateNewDataSet()); string eTag; using (DicomWebAsyncEnumerableResponse <DicomDataset> response = await _client.RetrieveStudyMetadataAsync(studyInstanceUid)) { eTag = GetEtagFromResponse(response); } using (DicomWebAsyncEnumerableResponse <DicomDataset> response = await _client.RetrieveStudyMetadataAsync(studyInstanceUid, eTag)) { Assert.Equal(HttpStatusCode.NotModified, response.StatusCode); ValidateNoContent(response); } }
public async Task GivenExistingStudyWithMultipleItemsInEachLevel_WhenDeletingStudy_TheServerShouldReturnNoContentAndAllLevelsShouldBeRemoved() { var studyInstanceUid = TestUidGenerator.Generate(); var seriesInstanceUid1 = TestUidGenerator.Generate(); var seriesInstanceUid2 = TestUidGenerator.Generate(); var sopInstanceUid1 = TestUidGenerator.Generate(); var sopInstanceUid2 = TestUidGenerator.Generate(); var sopInstanceUid3 = TestUidGenerator.Generate(); await CreateFile(studyInstanceUid, seriesInstanceUid1, sopInstanceUid1); await CreateFile(studyInstanceUid, seriesInstanceUid2, sopInstanceUid2); await CreateFile(studyInstanceUid, seriesInstanceUid2, sopInstanceUid3); await _client.DeleteStudyAsync(studyInstanceUid); await VerifyAllRemoval(studyInstanceUid, seriesInstanceUid1, sopInstanceUid1); await VerifyAllRemoval(studyInstanceUid, seriesInstanceUid2, sopInstanceUid2); await VerifyAllRemoval(studyInstanceUid, seriesInstanceUid2, sopInstanceUid3); }
public async Task GivenStudyWithMultileInstances_WhenDeleteStudy_ThenAssociatedErrorsShouldBeRemoved() { string studyUid1 = TestUidGenerator.Generate(); string seriesUid1 = TestUidGenerator.Generate(); string instanceUid1 = TestUidGenerator.Generate(); string seriesUid2 = TestUidGenerator.Generate(); string instanceUid2 = TestUidGenerator.Generate(); string studyUid3 = TestUidGenerator.Generate(); string seriesUid3 = TestUidGenerator.Generate(); string instanceUid3 = TestUidGenerator.Generate(); // add instances: instance1 and instance2 are in same study long watermark1 = await AddInstanceAsync(studyUid1, seriesUid1, instanceUid1); long watermark2 = await AddInstanceAsync(studyUid1, seriesUid2, instanceUid2); long watermark3 = await AddInstanceAsync(studyUid3, seriesUid3, instanceUid3); // add tag DicomTag tag = DicomTag.DeviceSerialNumber; int tagKey = await AddTagAsync(tag); // add errors ValidationErrorCode errorCode = ValidationErrorCode.DateIsInvalid; await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, errorCode, watermark1); await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, errorCode, watermark2); await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync(tagKey, errorCode, watermark3); // delete instance await _indexDataStore.DeleteStudyIndexAsync(DefaultPartition.Key, studyUid1, DateTime.UtcNow); // check errors var errors = await _extendedQueryTagErrorStore.GetExtendedQueryTagErrorsAsync(tag.GetPath(), int.MaxValue, 0); Assert.Single(errors); Assert.Equal(studyUid3, errors[0].StudyInstanceUid); Assert.Equal(seriesUid3, errors[0].SeriesInstanceUid); Assert.Equal(instanceUid3, errors[0].SopInstanceUid); }
public async Task GivenAnIncorrectAcceptHeader_WhenRetrievingResource_NotAcceptableIsReturned(string acceptHeader) { // Study await _client.ValidateResponseStatusCodeAsync( string.Format(DicomWebConstants.BasStudyUriFormat, TestUidGenerator.Generate()), acceptHeader, HttpStatusCode.NotAcceptable); // Series await _client.ValidateResponseStatusCodeAsync( string.Format(DicomWebConstants.BaseSeriesUriFormat, TestUidGenerator.Generate(), TestUidGenerator.Generate()), acceptHeader, HttpStatusCode.NotAcceptable); // Instance await _client.ValidateResponseStatusCodeAsync( string.Format(DicomWebConstants.BaseInstanceUriFormat, TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate()), acceptHeader, HttpStatusCode.NotAcceptable); }
public async Task GivenExtendedQueryTagError_WhenAddExtendedQueryTagError_ThenErrorCountShouldIncrease() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); DicomTag tag = DicomTag.DeviceSerialNumber; long watermark = await AddInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid); int tagKey = await AddTagAsync(tag); await _extendedQueryTagErrorStore.AddExtendedQueryTagErrorAsync( tagKey, ValidationErrorCode.UidIsInvalid, watermark); var tagEntry = await _extendedQueryTagStore.GetExtendedQueryTagAsync(tag.GetPath()); Assert.Equal(1, tagEntry.ErrorCount); }
public async Task GivenRetrieveStudyMetadataRequest_WhenStudyIsUpdatedAndPreviousETagIsUsed_ThenResponseMetadataIsReturnedWithNewETag() { string studyInstanceUid = TestUidGenerator.Generate(); DicomDataset firstStoredInstance = await PostDicomFileAsync(ResourceType.Study, studyInstanceUid, dataSet : GenerateNewDataSet()); string eTag; using (DicomWebAsyncEnumerableResponse <DicomDataset> response = await _client.RetrieveStudyMetadataAsync(studyInstanceUid)) { eTag = GetEtagFromResponse(response); } DicomDataset secondStoredInstance = await PostDicomFileAsync(ResourceType.Study, studyInstanceUid, dataSet : GenerateNewDataSet()); using (DicomWebAsyncEnumerableResponse <DicomDataset> response = await _client.RetrieveStudyMetadataAsync(studyInstanceUid, eTag)) { await ValidateResponseMetadataDatasetAsync(response, firstStoredInstance, secondStoredInstance); } }
public async Task WhenRetrievingPartitions_TheServerShouldReturnAllPartitions() { var newPartition1 = TestUidGenerator.Generate(); var newPartition2 = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFile(); using DicomWebResponse <DicomDataset> response1 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName : newPartition1); using DicomWebResponse <DicomDataset> response2 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName : newPartition2); using DicomWebResponse <IEnumerable <PartitionEntry> > response3 = await _client.GetPartitionsAsync(); Assert.True(response3.IsSuccessStatusCode); IEnumerable <PartitionEntry> values = await response3.GetValueAsync(); Assert.Contains(values, x => x.PartitionName == newPartition1); Assert.Contains(values, x => x.PartitionName == newPartition2); }
public async Task GivenAnExistingDicomInstance_WhenDeletedByInstanceId_AdditionalInstancesShouldBeMaintained() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); Instance instance = await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid); string sopInstanceUid2 = TestUidGenerator.Generate(); await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid2); await _indexDataStore.DeleteInstanceIndexAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, Clock.UtcNow); Assert.Empty(await _testHelper.GetInstancesAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid)); Assert.NotEmpty(await _testHelper.GetInstancesAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid2)); Assert.NotEmpty(await _testHelper.GetSeriesMetadataAsync(seriesInstanceUid)); Assert.NotEmpty(await _testHelper.GetStudyMetadataAsync(studyInstanceUid)); Assert.Collection(await _testHelper.GetDeletedInstanceEntriesAsync(studyInstanceUid, seriesInstanceUid, null), ValidateSingleDeletedInstance(instance)); }
public async Task GivenFewDeletedInstances_NumMatchRetryCountShouldBeCorrect() { await _testHelper.ClearDeletedInstanceTable(); string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); Instance instance1 = await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid); await _indexDataStore.DeleteInstanceIndexAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, Clock.UtcNow); string sopInstanceUid2 = TestUidGenerator.Generate(); Instance instance2 = await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid2); await _indexDataStore.DeleteInstanceIndexAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid2, Clock.UtcNow); var numMatchRetryCount = await _indexDataStore.RetrieveNumExhaustedDeletedInstanceAttemptsAsync(0); Assert.Equal(2, numMatchRetryCount); }
public async Task GivenRetrieveSeriesMetadataRequest_WhenInstanceIsDeletedInSeriesAndPreviousETagIsUsed_ThenResponseMetadataIsReturnedWithNewETag() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string firstSopInstanceUid = TestUidGenerator.Generate(); DicomDataset firstStoredInstance = await PostDicomFileAsync(ResourceType.Instance, studyInstanceUid, seriesInstanceUid, firstSopInstanceUid, dataSet : GenerateNewDataSet()); DicomDataset secondStoredInstance = await PostDicomFileAsync(ResourceType.Series, studyInstanceUid, seriesInstanceUid, dataSet : GenerateNewDataSet()); DicomWebResponse <IReadOnlyList <DicomDataset> > response = await _client.RetrieveSeriesMetadataAsync(studyInstanceUid, seriesInstanceUid); string eTag = GetEtagFromResponse(response); await _client.DeleteInstanceAsync(studyInstanceUid, seriesInstanceUid, firstSopInstanceUid); response = await _client.RetrieveSeriesMetadataAsync(studyInstanceUid, seriesInstanceUid, eTag); Assert.Single(response.Value); ValidateResponseMetadataDataset(secondStoredInstance, response.Value.First()); }
public async Task GivenMultipleInstancesWithMixTransferSyntax_WhenRetrieveStudy_ThenServerShouldReturnNotAcceptable() { var studyInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile1 = Samples.CreateRandomDicomFileWith8BitPixelData( studyInstanceUid, TestUidGenerator.Generate(), transferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID); DicomFile dicomFile2 = Samples.CreateRandomDicomFileWith8BitPixelData( studyInstanceUid, TestUidGenerator.Generate(), transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2 }); DicomWebException exception = await Assert.ThrowsAsync <DicomWebException>(() => _client.RetrieveStudyAsync(studyInstanceUid, dicomTransferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID)); Assert.Equal(HttpStatusCode.NotAcceptable, exception.StatusCode); }
public async Task GivenDicomInstanceWithDifferentTypesOfExtendedQueryTags_WhenDeletedBySopInstanceId_ThenTagValuesShouldBeRemoved() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid2 = TestUidGenerator.Generate(); try { // Store 5 tags, 1 study level datetime tag, 2 series level string and double tags and 2 instance level long and person name tags. IReadOnlyList <QueryTag> tags = await StoreTagsOfSuportedDataTypes(); // Create 2 instances in same series and same study. Instance instance1 = await StoreInstanceWithDifferentTagValues(studyInstanceUid, seriesInstanceUid, sopInstanceUid, 1, tags); Instance instance2 = await StoreInstanceWithDifferentTagValues(studyInstanceUid, seriesInstanceUid, sopInstanceUid2, 2, tags); var queryTags = tags.ToArray(); // Delete by instance uid. await _indexDataStore.DeleteInstanceIndexAsync(DefaultPartition.Key, studyInstanceUid, seriesInstanceUid, sopInstanceUid, Clock.UtcNow); // Study and series level tags should not be deleted. Assert.Single(await _extendedQueryTagStoreTestHelper.GetExtendedQueryTagDataAsync(ExtendedQueryTagDataType.DateTimeData, queryTags[0].ExtendedQueryTagStoreEntry.Key, instance1.StudyKey)); Assert.Single(await _extendedQueryTagStoreTestHelper.GetExtendedQueryTagDataAsync(ExtendedQueryTagDataType.StringData, queryTags[1].ExtendedQueryTagStoreEntry.Key, instance1.StudyKey, instance1.SeriesKey)); Assert.Single(await _extendedQueryTagStoreTestHelper.GetExtendedQueryTagDataAsync(ExtendedQueryTagDataType.DoubleData, queryTags[2].ExtendedQueryTagStoreEntry.Key, instance1.StudyKey, instance1.SeriesKey)); // Instance level tags under the deleted instance should be deleted. Assert.Empty(await _extendedQueryTagStoreTestHelper.GetExtendedQueryTagDataAsync(ExtendedQueryTagDataType.LongData, queryTags[3].ExtendedQueryTagStoreEntry.Key, instance1.StudyKey, instance1.SeriesKey, instance1.InstanceKey)); Assert.Empty(await _extendedQueryTagStoreTestHelper.GetExtendedQueryTagDataAsync(ExtendedQueryTagDataType.PersonNameData, queryTags[4].ExtendedQueryTagStoreEntry.Key, instance1.StudyKey, instance1.SeriesKey, instance1.InstanceKey)); // Instance level tags under the other instance should not be deleted. Assert.Single(await _extendedQueryTagStoreTestHelper.GetExtendedQueryTagDataAsync(ExtendedQueryTagDataType.LongData, queryTags[3].ExtendedQueryTagStoreEntry.Key, instance1.StudyKey, instance1.SeriesKey, instance2.InstanceKey)); Assert.Single(await _extendedQueryTagStoreTestHelper.GetExtendedQueryTagDataAsync(ExtendedQueryTagDataType.PersonNameData, queryTags[4].ExtendedQueryTagStoreEntry.Key, instance1.StudyKey, instance1.SeriesKey, instance2.InstanceKey)); } finally { await CleanupExtendedQueryTags(); } }
public async Task GivenASetOfDicomInstances_WhenRetrievingChangeFeed_ThenTheExpectedInstanceAreReturned() { var studyInstanceUid = TestUidGenerator.Generate(); var seriesInstanceUid = TestUidGenerator.Generate(); var sopInstanceUids = Enumerable.Range(1, 10).Select(x => TestUidGenerator.Generate()).ToArray(); long initialSequence = -1; for (int i = 0; i < 10; i++) { await CreateFile(studyInstanceUid, seriesInstanceUid, sopInstanceUids[i]); if (initialSequence == -1) { var result = await _client.GetChangeFeedLatest(); initialSequence = result.Value.Sequence; Assert.Equal(studyInstanceUid, result.Value.StudyInstanceUid); Assert.Equal(seriesInstanceUid, result.Value.SeriesInstanceUid); Assert.Equal(sopInstanceUids[i], result.Value.SopInstanceUid); Assert.Equal(ChangeFeedAction.Create, result.Value.Action); Assert.Equal(ChangeFeedState.Current, result.Value.State); } } var changeFeedResults = await _client.GetChangeFeed(); Assert.Equal(10, changeFeedResults.Value.Count); changeFeedResults = await _client.GetChangeFeed($"?offset={initialSequence - 1}"); Assert.Equal(10, changeFeedResults.Value.Count); for (int i = 0; i < 10; i++) { Assert.Equal(studyInstanceUid, changeFeedResults.Value[i].StudyInstanceUid); Assert.Equal(seriesInstanceUid, changeFeedResults.Value[i].SeriesInstanceUid); Assert.Equal(sopInstanceUids[i], changeFeedResults.Value[i].SopInstanceUid); Assert.NotNull(changeFeedResults.Value[i].Metadata); } }
public async Task GivenRetrieveStudyMetadataRequest_WhenIfNoneMatchDoesnotMatchETag_ThenResponseMetadataIsReturnedWithNewETag() { string studyInstanceUid = TestUidGenerator.Generate(); DicomDataset firstStoredInstance = await PostDicomFileAsync(ResourceType.Study, studyInstanceUid, dataSet : GenerateNewDataSet()); DicomDataset secondStoredInstance = await PostDicomFileAsync(ResourceType.Study, studyInstanceUid, dataSet : GenerateNewDataSet()); DicomWebResponse <IReadOnlyList <DicomDataset> > response = await _client.RetrieveStudyMetadataAsync(studyInstanceUid); string eTag = GetEtagFromResponse(response); string ifNoneMatch = null; if (!string.IsNullOrEmpty(eTag)) { ifNoneMatch = string.Concat("1", eTag); } response = await _client.RetrieveStudyMetadataAsync(studyInstanceUid, ifNoneMatch); ValidateResponseMetadataDataset(response, firstStoredInstance, secondStoredInstance); }
public async void GivenRequestForStudies_WhenRetrievingQueriableExtendedQueryTags_ReturnsStudyTags(QueryResource resourceType) { var request = new QueryResourceRequest( Substitute.For <IEnumerable <KeyValuePair <string, StringValues> > >(), resourceType, TestUidGenerator.Generate(), TestUidGenerator.Generate()); List <ExtendedQueryTagStoreEntry> storeEntries = new List <ExtendedQueryTagStoreEntry>() { new ExtendedQueryTagStoreEntry(1, "00741000", "CS", null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Ready), new ExtendedQueryTagStoreEntry(2, "0040A121", "DA", null, QueryTagLevel.Series, ExtendedQueryTagStatus.Ready), new ExtendedQueryTagStoreEntry(3, "00101005", "PN", null, QueryTagLevel.Study, ExtendedQueryTagStatus.Ready), }; var list = QueryTagService.CoreQueryTags.Concat(storeEntries.Select(item => new QueryTag(item))).ToList(); _queryStore.QueryAsync(Arg.Any <QueryExpression>(), Arg.Any <CancellationToken>()).ReturnsForAnyArgs(new QueryResult(new List <VersionedInstanceIdentifier>())); await _queryService.QueryAsync(request, CancellationToken.None); _queryParser.Received().Parse(request, Arg.Do <IReadOnlyCollection <QueryTag> >(x => Assert.Equal(x, list, QueryTagComparer.Default))); }
public async Task GivenMultipleDicomInstance_WhenDeletedByStudyInstanceUid_ThenItemsBeRemovedAndAddedToDeletedInstanceTable() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); Instance instance1 = await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid); string sopInstanceUid2 = TestUidGenerator.Generate(); Instance instance2 = await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid2); await _indexDataStore.DeleteStudyIndexAsync(studyInstanceUid, Clock.UtcNow); Assert.Empty(await _testHelper.GetInstancesAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid)); Assert.Empty(await _testHelper.GetInstancesAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid2)); Assert.Empty(await _testHelper.GetSeriesMetadataAsync(seriesInstanceUid)); Assert.Empty(await _testHelper.GetStudyMetadataAsync(seriesInstanceUid)); Assert.Collection( await _testHelper.GetDeletedInstanceEntriesAsync(studyInstanceUid, null, null), ValidateSingleDeletedInstance(instance1), ValidateSingleDeletedInstance(instance2)); }
public async Task GivenMultipleDeletedInstances_OldestDeletedIsCorrect() { await _testHelper.ClearDeletedInstanceTable(); DateTimeOffset start = Clock.UtcNow; string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); Instance instance1 = await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid); await _indexDataStore.DeleteInstanceIndexAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, Clock.UtcNow); string sopInstanceUid2 = TestUidGenerator.Generate(); Instance instance2 = await CreateIndexAndVerifyInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid2); await Task.Delay(5000); await _indexDataStore.DeleteInstanceIndexAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid2, Clock.UtcNow); Assert.InRange(await _indexDataStore.GetOldestDeletedAsync(), start.AddSeconds(-1), start.AddSeconds(1)); }
public async Task WhenRetrievingWithPartitionName_TheServerShouldReturnOnlyTheSpecifiedPartition() { var newPartition1 = "partition1"; var newPartition2 = "partition2"; string studyInstanceUID = TestUidGenerator.Generate(); string seriesInstanceUID = TestUidGenerator.Generate(); string sopInstanceUID = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUID, seriesInstanceUID, sopInstanceUID); using DicomWebResponse <DicomDataset> response1 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName : newPartition1); using DicomWebResponse <DicomDataset> response2 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName : newPartition2); using DicomWebResponse <DicomFile> response3 = await _client.RetrieveInstanceAsync(studyInstanceUID, seriesInstanceUID, sopInstanceUID, partitionName : newPartition1); Assert.True(response3.IsSuccessStatusCode); using DicomWebResponse <DicomFile> response4 = await _client.RetrieveInstanceAsync(studyInstanceUID, seriesInstanceUID, sopInstanceUID, partitionName : newPartition2); Assert.True(response4.IsSuccessStatusCode); }
public async Task GivenANonExistingDicomInstance_WhenStatusIsUpdated_ThenDicomInstanceNotFoundExceptionShouldBeThrown() { string studyInstanceUid = TestUidGenerator.Generate(); string seriesInstanceUid = TestUidGenerator.Generate(); string sopInstanceUid = TestUidGenerator.Generate(); DicomDataset dataset = Samples.CreateRandomDicomFile(studyInstanceUid, seriesInstanceUid, sopInstanceUid).Dataset; long version = await _indexDataStore.CreateInstanceIndexAsync(dataset); VersionedInstanceIdentifier versionedInstanceIdentifier = new VersionedInstanceIdentifier( studyInstanceUid, seriesInstanceUid, sopInstanceUid, version); await _indexDataStore.DeleteInstanceIndexAsync(versionedInstanceIdentifier); await Assert.ThrowsAsync <InstanceNotFoundException>( () => _indexDataStore.UpdateInstanceIndexStatusAsync(versionedInstanceIdentifier, IndexStatus.Created)); Assert.Empty(await _testHelper.GetInstancesAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid)); }