diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Common/DicomInstanceId.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Common/DicomInstanceId.cs new file mode 100644 index 0000000000..70c0812dd9 --- /dev/null +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Common/DicomInstanceId.cs @@ -0,0 +1,52 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using Dicom; +using EnsureThat; +using Microsoft.Health.Dicom.Core.Extensions; +using Microsoft.Health.Dicom.Core.Features.Model; + +namespace Microsoft.Health.Dicom.Web.Tests.E2E.Common +{ + internal class DicomInstanceId + { + private const StringComparison EqualsStringComparison = StringComparison.Ordinal; + public DicomInstanceId(string studyInstanceUid, string seriesInstanceUid, string sopInstanceUid, string partitionName) + { + StudyInstanceUid = EnsureArg.IsNotNullOrWhiteSpace(studyInstanceUid, nameof(studyInstanceUid)); + SeriesInstanceUid = EnsureArg.IsNotNullOrWhiteSpace(seriesInstanceUid, nameof(seriesInstanceUid)); + SopInstanceUid = EnsureArg.IsNotNullOrWhiteSpace(sopInstanceUid, nameof(sopInstanceUid)); + PartitionName = partitionName; + } + + public string StudyInstanceUid { get; } + public string SeriesInstanceUid { get; } + public string SopInstanceUid { get; } + public string PartitionName { get; } + + public static DicomInstanceId FromDicomFile(DicomFile dicomFile, string partitionName = default) + { + InstanceIdentifier instanceIdentifier = dicomFile.Dataset.ToInstanceIdentifier(); + return new DicomInstanceId(instanceIdentifier.StudyInstanceUid, instanceIdentifier.SeriesInstanceUid, instanceIdentifier.SopInstanceUid, partitionName); + } + + public override bool Equals(object obj) + { + if (obj is DicomInstanceId instanceId) + { + return StudyInstanceUid.Equals(instanceId.StudyInstanceUid, EqualsStringComparison) && + SeriesInstanceUid.Equals(instanceId.SeriesInstanceUid, EqualsStringComparison) && + SopInstanceUid.Equals(instanceId.SopInstanceUid, EqualsStringComparison) && + PartitionName.Equals(instanceId.PartitionName, EqualsStringComparison); + } + + return false; + } + + public override int GetHashCode() => HashCode.Combine(StudyInstanceUid, SeriesInstanceUid, SopInstanceUid, PartitionName); + + } +} diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Common/DicomInstancesManager.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Common/DicomInstancesManager.cs index 39c7330391..488007dd81 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Common/DicomInstancesManager.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Common/DicomInstancesManager.cs @@ -4,26 +4,28 @@ // ------------------------------------------------------------------------------------------------- using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Dicom; using EnsureThat; using Microsoft.Health.Dicom.Client; -using Microsoft.Health.Dicom.Core.Extensions; -using Microsoft.Health.Dicom.Core.Features.Model; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Common { internal class DicomInstancesManager : IAsyncDisposable { + private readonly IDicomWebClient _dicomWebClient; - private readonly HashSet _instanceIds; + private readonly ConcurrentBag _instanceIds; public DicomInstancesManager(IDicomWebClient dicomWebClient) { _dicomWebClient = EnsureArg.IsNotNull(dicomWebClient, nameof(dicomWebClient)); - _instanceIds = new HashSet(); + _instanceIds = new ConcurrentBag(); } public async ValueTask DisposeAsync() @@ -32,7 +34,7 @@ public async ValueTask DisposeAsync() { try { - await _dicomWebClient.DeleteInstanceAsync(id.StudyInstanceUid, id.SeriesInstanceUid, id.SopInstanceUid); + await _dicomWebClient.DeleteInstanceAsync(id.StudyInstanceUid, id.SeriesInstanceUid, id.SopInstanceUid, id.PartitionName); } catch (DicomWebException) { @@ -41,12 +43,44 @@ public async ValueTask DisposeAsync() } } - public async Task StoreAsync(DicomFile dicomFile, CancellationToken cancellationToken = default) + public async Task> StoreAsync(DicomFile dicomFile, string studyInstanceUid = default, string partitionName = default, CancellationToken cancellationToken = default) { EnsureArg.IsNotNull(dicomFile, nameof(dicomFile)); - _instanceIds.Add(dicomFile.Dataset.ToInstanceIdentifier()); - await _dicomWebClient.StoreAsync(dicomFile, cancellationToken: cancellationToken); + _instanceIds.Add(DicomInstanceId.FromDicomFile(dicomFile, partitionName)); + return await _dicomWebClient.StoreAsync(dicomFile, studyInstanceUid, partitionName, cancellationToken); + } + + public async Task> StoreAsync(HttpContent content, string partitionName = default, CancellationToken cancellationToken = default, DicomInstanceId instanceId = default) + { + EnsureArg.IsNotNull(content, nameof(content)); + // Null instanceId indiates Store will fail + if (instanceId != null) + { + _instanceIds.Add(instanceId); + } + return await _dicomWebClient.StoreAsync(content, partitionName, cancellationToken); + } + + public async Task> StoreAsync(IEnumerable dicomFiles, string studyInstanceUid = default, string partitionName = default, CancellationToken cancellationToken = default) + { + EnsureArg.IsNotNull(dicomFiles, nameof(dicomFiles)); + foreach (var file in dicomFiles) + { + _instanceIds.Add(DicomInstanceId.FromDicomFile(file, partitionName)); + } + + return await _dicomWebClient.StoreAsync(dicomFiles, studyInstanceUid, partitionName, cancellationToken); } + public async Task> StoreAsync(Stream stream, string studyInstanceUid = default, string partitionName = default, CancellationToken cancellationToken = default, DicomInstanceId instanceId = default) + { + EnsureArg.IsNotNull(stream, nameof(stream)); + // Null instanceId indiates Store will fail + if (instanceId != null) + { + _instanceIds.Add(instanceId); + } + return await _dicomWebClient.StoreAsync(stream, studyInstanceUid, partitionName, cancellationToken); + } } } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/Audit/AuditTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/Audit/AuditTests.cs index c0950f9e0a..beff2091bc 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/Audit/AuditTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/Audit/AuditTests.cs @@ -14,6 +14,7 @@ using Microsoft.Health.Dicom.Core.Features.Audit; using Microsoft.Health.Dicom.Core.Features.Model; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest.Audit @@ -21,10 +22,11 @@ namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest.Audit /// /// Provides Audit specific tests. /// - public class AuditTests : IClassFixture + public class AuditTests : IClassFixture, IAsyncLifetime { private readonly AuditTestFixture _fixture; private readonly IDicomWebClient _client; + private readonly DicomInstancesManager _instancesManager; private readonly TraceAuditLogger _auditLogger; @@ -32,8 +34,8 @@ public AuditTests(AuditTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); _fixture = fixture; - _client = fixture.Client; - + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); _auditLogger = _fixture.AuditLogger; } @@ -78,7 +80,7 @@ public async Task GivenRetrieveRequestForFrame_WhenResourceIsFound_ThenAuditLogE { DicomFile dicomFile = Samples.CreateRandomDicomFileWithPixelData(frames: 1); var dicomInstance = dicomFile.Dataset.ToInstanceIdentifier(); - await _client.StoreAsync(new[] { dicomFile }, dicomInstance.StudyInstanceUid); + await _instancesManager.StoreAsync(new[] { dicomFile }, dicomInstance.StudyInstanceUid); await ExecuteAndValidate( () => _client.RetrieveFramesAsync(dicomInstance.StudyInstanceUid, dicomInstance.SeriesInstanceUid, dicomInstance.SopInstanceUid, frames: new int[] { 1 }), @@ -189,12 +191,19 @@ public async Task GivenStoreRequest_WhenStoringUsingStudyInstanceUid_ThenAuditLo InstanceIdentifier dicomInstance = dicomFile.Dataset.ToInstanceIdentifier(); await ExecuteAndValidate( - () => _client.StoreAsync(new[] { dicomFile }, studyInstanceUid), + () => _instancesManager.StoreAsync(new[] { dicomFile }, studyInstanceUid), AuditEventSubType.Store, $"studies/{dicomInstance.StudyInstanceUid}", HttpStatusCode.OK); } + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); + } + private async Task ExecuteAndValidate(Func> action, string expectedAction, string expectedPathSegment, HttpStatusCode expectedStatusCode) { if (!_fixture.IsInProcess) @@ -237,9 +246,10 @@ private async Task CreateDicomFileAndGetInstanceIdentifierAs string studyInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUid); InstanceIdentifier dicomInstance = dicomFile.Dataset.ToInstanceIdentifier(); - await _client.StoreAsync(new[] { dicomFile }, studyInstanceUid); + await _instancesManager.StoreAsync(new[] { dicomFile }, studyInstanceUid); return dicomInstance; } + } } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ChangeFeedTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ChangeFeedTests.cs index 68b7137f3e..cfa2ac40e4 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ChangeFeedTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ChangeFeedTests.cs @@ -11,6 +11,7 @@ using Microsoft.Health.Dicom.Client; using Microsoft.Health.Dicom.Client.Models; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Xunit; using ChangeFeedAction = Microsoft.Health.Dicom.Client.Models.ChangeFeedAction; using ChangeFeedState = Microsoft.Health.Dicom.Client.Models.ChangeFeedState; @@ -18,14 +19,16 @@ namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest { [CollectionDefinition("Non-Parallel Collection", DisableParallelization = true)] - public class ChangeFeedTests : IClassFixture> + public class ChangeFeedTests : IClassFixture>, IAsyncLifetime { private readonly IDicomWebClient _client; + private readonly DicomInstancesManager _instancesManager; public ChangeFeedTests(HttpIntegrationTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); } [Fact] @@ -200,10 +203,17 @@ public async Task GivenAnInvalidParameter_WhenRetrievingChangeFeedLatest_ThenBad Assert.Equal(HttpStatusCode.BadRequest, exception.StatusCode); } + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); + } + private async Task CreateFile(string studyInstanceUid, string seriesInstanceUid, string sopInstanceUid) { DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUid, seriesInstanceUid, sopInstanceUid); - await _client.StoreAsync(new[] { dicomFile1 }, studyInstanceUid); + await _instancesManager.StoreAsync(new[] { dicomFile1 }, studyInstanceUid); } } } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DataPartitionEnabledTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DataPartitionEnabledTests.cs index c3a8e1c291..88b6e475b6 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DataPartitionEnabledTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DataPartitionEnabledTests.cs @@ -13,18 +13,21 @@ using Microsoft.Health.Dicom.Client.Models; using Microsoft.Health.Dicom.Core.Features.Query; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest { - public class DataPartitionEnabledTests : IClassFixture> + public class DataPartitionEnabledTests : IClassFixture>, IAsyncLifetime { private readonly IDicomWebClient _client; + private readonly DicomInstancesManager _instancesManager; public DataPartitionEnabledTests(DataPartitionEnabledHttpIntegrationTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); } [Fact] @@ -35,8 +38,8 @@ public async Task WhenRetrievingPartitions_TheServerShouldReturnAllPartitions() DicomFile dicomFile = Samples.CreateRandomDicomFile(); - using DicomWebResponse response1 = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition1); - using DicomWebResponse response2 = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition2); + using DicomWebResponse response1 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition1); + using DicomWebResponse response2 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition2); using DicomWebResponse> response3 = await _client.GetPartitionsAsync(); Assert.True(response3.IsSuccessStatusCode); @@ -56,7 +59,7 @@ public async Task GivenDatasetWithNewPartitionName_WhenStoring_TheServerShouldRe DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUID); - using DicomWebResponse response = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition); + using DicomWebResponse response = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition); Assert.True(response.IsSuccessStatusCode); @@ -73,7 +76,7 @@ public async Task GivenDatasetWithNewPartitionName_WhenStoringWithStudyUid_TheSe var studyInstanceUID = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUid: studyInstanceUID); - using DicomWebResponse response = await _client.StoreAsync(dicomFile, studyInstanceUID, newPartition); + using DicomWebResponse response = await _instancesManager.StoreAsync(dicomFile, studyInstanceUID, newPartition); Assert.True(response.IsSuccessStatusCode); @@ -94,8 +97,8 @@ public async Task WhenRetrievingWithPartitionName_TheServerShouldReturnOnlyTheSp DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUID, seriesInstanceUID, sopInstanceUID); - using DicomWebResponse response1 = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition1); - using DicomWebResponse response2 = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition2); + using DicomWebResponse response1 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition1); + using DicomWebResponse response2 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition2); using DicomWebResponse response3 = await _client.RetrieveInstanceAsync(studyInstanceUID, seriesInstanceUID, sopInstanceUID, partitionName: newPartition1); Assert.True(response3.IsSuccessStatusCode); @@ -116,8 +119,8 @@ public async Task GivenDatasetInstancesWithDifferentPartitions_WhenDeleted_OneDe DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUID, seriesInstanceUID, sopInstanceUID); - using DicomWebResponse response1 = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition1); - using DicomWebResponse response2 = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition2); + using DicomWebResponse response1 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition1); + using DicomWebResponse response2 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition2); using DicomWebResponse response3 = await _client.DeleteInstanceAsync(studyInstanceUID, seriesInstanceUID, sopInstanceUID, newPartition1); Assert.True(response3.IsSuccessStatusCode); @@ -148,8 +151,8 @@ public async Task GivenMatchingStudiesInDifferentPartitions_WhenSearchForStudySe { DicomTag.Modality, "MRI" }, }); - using DicomWebResponse response1 = await _client.StoreAsync(new[] { file1 }, partitionName: newPartition1); - using DicomWebResponse response2 = await _client.StoreAsync(new[] { file2 }, partitionName: newPartition2); + using DicomWebResponse response1 = await _instancesManager.StoreAsync(new[] { file1 }, partitionName: newPartition1); + using DicomWebResponse response2 = await _instancesManager.StoreAsync(new[] { file2 }, partitionName: newPartition2); using DicomWebAsyncEnumerableResponse response = await _client.QueryStudySeriesAsync(studyUid, "Modality=MRI", newPartition1); @@ -168,7 +171,7 @@ public async Task GivenAnInstance_WhenRetrievingChangeFeedWithPartition_ThenPart string sopInstanceUID = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUID, seriesInstanceUID, sopInstanceUID); - using DicomWebResponse response1 = await _client.StoreAsync(new[] { dicomFile }, partitionName: newPartition); + using DicomWebResponse response1 = await _instancesManager.StoreAsync(new[] { dicomFile }, partitionName: newPartition); Assert.True(response1.IsSuccessStatusCode); long initialSequence; @@ -196,6 +199,13 @@ public async Task GivenAnInstance_WhenRetrievingChangeFeedWithPartition_ThenPart } } + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); + } + private (string SopInstanceUid, string RetrieveUri, string SopClassUid) ConvertToReferencedSopSequenceEntry(DicomDataset dicomDataset, string partitionName) { string studyInstanceUid = dicomDataset.GetSingleValue(DicomTag.StudyInstanceUID); diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DeleteTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DeleteTests.cs index 806e2d495e..13c5ed70fe 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DeleteTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DeleteTests.cs @@ -10,18 +10,21 @@ using EnsureThat; using Microsoft.Health.Dicom.Client; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest { - public class DeleteTests : IClassFixture> + public class DeleteTests : IClassFixture>, IAsyncLifetime { private readonly IDicomWebClient _client; + private readonly DicomInstancesManager _instancesManager; public DeleteTests(HttpIntegrationTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); } [Fact] @@ -274,6 +277,13 @@ public async Task GivenABadSopInstanceUid_WhenDeleting_TheServerShouldReturnBack Assert.Equal(HttpStatusCode.BadRequest, exception.StatusCode); } + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); + } + private async Task VerifyAllRemoval(string studyInstanceUid, string seriesInstanceUid, string sopInstanceUid) { await VerifySopInstanceRemoval(studyInstanceUid, seriesInstanceUid, sopInstanceUid); @@ -315,7 +325,7 @@ private async Task CreateFile(string studyInstanceUid, string seriesInstanceUid, { DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUid, seriesInstanceUid, sopInstanceUid); - await _client.StoreAsync(new[] { dicomFile1 }, studyInstanceUid); + await _instancesManager.StoreAsync(new[] { dicomFile1 }, studyInstanceUid); } } } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataETagTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataETagTests.cs index 25c884f1f5..050d7b1900 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataETagTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataETagTests.cs @@ -15,20 +15,23 @@ using Microsoft.Health.Dicom.Core.Extensions; using Microsoft.Health.Dicom.Core.Messages; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Microsoft.Net.Http.Headers; using Newtonsoft.Json; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest { - public class DicomRetrieveMetadataETagTests : IClassFixture> + public class DicomRetrieveMetadataETagTests : IClassFixture>, IAsyncLifetime { private readonly IDicomWebClient _client; + private readonly DicomInstancesManager _instancesManager; public DicomRetrieveMetadataETagTests(HttpIntegrationTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); } [Fact] @@ -319,6 +322,13 @@ public async Task GivenRetrieveInstanceMetadataRequest_WhenIfNoneMatchIsNotPrese ValidateResponseMetadataDataset(storedInstance, datasets[0]); } + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); + } + private string GetEtagFromResponse(DicomWebAsyncEnumerableResponse response) { string eTag = null; @@ -356,7 +366,7 @@ private async Task PostDicomFileAsync(ResourceType resourceType, s dicomFile.Dataset.AddOrUpdate(dataSet); } - using DicomWebResponse response = await _client.StoreAsync(new[] { dicomFile }); + using DicomWebResponse response = await _instancesManager.StoreAsync(new[] { dicomFile }); return dicomFile.Dataset; } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataTransactionTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataTransactionTests.cs index f1d600a5fb..38a62de168 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataTransactionTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/DicomRetrieveMetadataTransactionTests.cs @@ -14,19 +14,22 @@ using Microsoft.Health.Dicom.Core.Extensions; using Microsoft.Health.Dicom.Core.Messages; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Newtonsoft.Json; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest { - public class DicomRetrieveMetadataTransactionTests : IClassFixture> + public class DicomRetrieveMetadataTransactionTests : IClassFixture>, IAsyncLifetime { private readonly IDicomWebClient _client; + private readonly DicomInstancesManager _instancesManager; public DicomRetrieveMetadataTransactionTests(HttpIntegrationTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); } [Theory] @@ -220,12 +223,20 @@ private async Task PostDicomFileAsync(ResourceType resourceType, s dicomFile.Dataset.AddOrUpdate(dataSet); } - using (DicomWebResponse response = await _client.StoreAsync(new[] { dicomFile })) + using (DicomWebResponse response = await _instancesManager.StoreAsync(new[] { dicomFile })) { Assert.Equal(HttpStatusCode.OK, response.StatusCode); } return dicomFile.Dataset; } + + public Task InitializeAsync() + => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); + } } } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ExtendedQueryTagTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ExtendedQueryTagTests.cs index e51e39b054..bfe794f958 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ExtendedQueryTagTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/ExtendedQueryTagTests.cs @@ -30,8 +30,7 @@ public class ExtendedQueryTagTests : IClassFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - EnsureArg.IsNotNull(fixture.Client, nameof(fixture.Client)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); _tagManager = new DicomTagsManager(_client); _instanceManager = new DicomInstancesManager(_client); } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/HttpIntegrationTestFixture.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/HttpIntegrationTestFixture.cs index 0ff9812952..8227528544 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/HttpIntegrationTestFixture.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/HttpIntegrationTestFixture.cs @@ -28,19 +28,14 @@ public HttpIntegrationTestFixture() protected HttpIntegrationTestFixture(string targetProjectParentDirectory, bool enableDataPartitions = false) { TestDicomWebServer = TestDicomWebServerFactory.GetTestDicomWebServer(typeof(TStartup), enableDataPartitions); - Client = GetDicomWebClient(); } public bool IsInProcess => TestDicomWebServer is InProcTestDicomWebServer; - public HttpClient HttpClient => Client.HttpClient; - protected TestDicomWebServer TestDicomWebServer { get; } public RecyclableMemoryStreamManager RecyclableMemoryStreamManager { get; } = new RecyclableMemoryStreamManager(); - public IDicomWebClient Client { get; } - public IDicomWebClient GetDicomWebClient() { return GetDicomWebClient(TestApplications.GlobalAdminServicePrincipal); @@ -113,7 +108,6 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - HttpClient.Dispose(); TestDicomWebServer.Dispose(); } } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/QueryTransactionTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/QueryTransactionTests.cs index 4ccc056938..ddb2683394 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/QueryTransactionTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/QueryTransactionTests.cs @@ -4,7 +4,6 @@ // ------------------------------------------------------------------------------------------------- using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; @@ -15,19 +14,21 @@ using Microsoft.Health.Dicom.Core; using Microsoft.Health.Dicom.Core.Features.Query; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest { - public class QueryTransactionTests : IClassFixture>, IDisposable + public class QueryTransactionTests : IClassFixture>, IAsyncLifetime { private readonly IDicomWebClient _client; - private readonly HashSet _createdDicomStudies = new HashSet(); + private readonly DicomInstancesManager _instancesManager; public QueryTransactionTests(HttpIntegrationTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); } [Fact] @@ -295,23 +296,15 @@ private async Task PostDicomFileAsync(DicomDataset metadataItems = dicomFile1.Dataset.AddOrUpdate(metadataItems); } - await _client.StoreAsync(new[] { dicomFile1 }); - - _createdDicomStudies.Add(dicomFile1.Dataset.GetSingleValue(DicomTag.StudyInstanceUID)); - + await _instancesManager.StoreAsync(new[] { dicomFile1 }); return dicomFile1.Dataset; } - void IDisposable.Dispose() - { - // xunit does not seem to call IAsyncDispose.DisposeAsync() - // Also wait should be okay in a test context - foreach (string studyUid in _createdDicomStudies) - { - _client.DeleteStudyAsync(studyUid).Wait(); - } + public Task InitializeAsync() => Task.CompletedTask; - _createdDicomStudies.Clear(); + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); } } } diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Common.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Common.cs index 2298e742b5..832f736442 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Common.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Common.cs @@ -11,6 +11,7 @@ using Microsoft.Health.Dicom.Core.Extensions; using Microsoft.Health.Dicom.Core.Features.Model; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest @@ -26,31 +27,23 @@ public partial class RetrieveTransactionResourceTests : IClassFixture _studiesToClean = new HashSet(); + private readonly DicomInstancesManager _instancesManager; public RetrieveTransactionResourceTests(HttpIntegrationTestFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); } private async Task<(InstanceIdentifier, DicomFile)> CreateAndStoreDicomFile(int numberOfFrames = 0) { DicomFile dicomFile = Samples.CreateRandomDicomFileWithPixelData(frames: numberOfFrames); var dicomInstance = dicomFile.Dataset.ToInstanceIdentifier(); - await InternalStoreAsync(new[] { dicomFile }); + await _instancesManager.StoreAsync(new[] { dicomFile }); return (dicomInstance, dicomFile); } - private async Task InternalStoreAsync(IEnumerable dicomFiles) - { - await _client.StoreAsync(dicomFiles); - foreach (DicomFile dicomFile in dicomFiles) - { - _studiesToClean.Add(dicomFile.Dataset.GetString(DicomTag.StudyInstanceUID)); - } - } - private InstanceIdentifier RandomizeInstanceIdentifier(DicomDataset dataset) { InstanceIdentifier newId = new InstanceIdentifier(TestUidGenerator.Generate(), TestUidGenerator.Generate(), TestUidGenerator.Generate()); @@ -60,19 +53,11 @@ private InstanceIdentifier RandomizeInstanceIdentifier(DicomDataset dataset) return newId; } - public Task InitializeAsync() - { - return Task.CompletedTask; - } + public Task InitializeAsync() => Task.CompletedTask; public async Task DisposeAsync() { - foreach (string studyUid in _studiesToClean) - { - await _client.DeleteStudyAsync(studyUid); - } - - _studiesToClean.Clear(); + await _instancesManager.DisposeAsync(); } public static IEnumerable GetUnsupportedAcceptHeadersForStudiesAndSeries diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Frame.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Frame.cs index b92984290c..ccd0746f0a 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Frame.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Frame.cs @@ -40,7 +40,7 @@ public async Task GivenSupportedAcceptHeaders_WhenRetrieveFrame_ThenServerShould DicomFile inputDicomFile = await DicomFile.OpenAsync(transcoderTestData.InputDicomFile); var instanceId = RandomizeInstanceIdentifier(inputDicomFile.Dataset); - await InternalStoreAsync(new[] { inputDicomFile }); + await _instancesManager.StoreAsync(new[] { inputDicomFile }); DicomFile outputDicomFile = DicomFile.Open(transcoderTestData.ExpectedOutputDicomFile); DicomPixelData pixelData = DicomPixelData.Create(outputDicomFile.Dataset); @@ -89,7 +89,7 @@ public async Task GivenUnsupportedTransferSyntax_WhenRetrieveFrameWithOriginalTr transferSyntax: DicomTransferSyntax.HEVCH265Main10ProfileLevel51.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile }); + await _instancesManager.StoreAsync(new[] { dicomFile }); // Check for series using DicomWebAsyncEnumerableResponse response = await _client.RetrieveFramesAsync( @@ -120,7 +120,7 @@ public async Task GivenUnsupportedTransferSyntax_WhenRetrieveFrame_ThenServerSho transferSyntax: DicomTransferSyntax.HEVCH265Main10ProfileLevel51.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile }); + await _instancesManager.StoreAsync(new[] { dicomFile }); DicomWebException exception = await Assert.ThrowsAsync(() => _client.RetrieveFramesAsync( studyInstanceUid, @@ -141,7 +141,7 @@ public async Task GivenMultipleFrames_WhenRetrieveFrame_ThenServerShouldReturnEx DicomPixelData pixelData = DicomPixelData.Create(dicomFile1.Dataset); InstanceIdentifier dicomInstance = dicomFile1.Dataset.ToInstanceIdentifier(); - await InternalStoreAsync(new[] { dicomFile1 }); + await _instancesManager.StoreAsync(new[] { dicomFile1 }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveFramesAsync( dicomInstance.StudyInstanceUid, diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Instance.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Instance.cs index d20515993f..0eca110d8b 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Instance.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Instance.cs @@ -34,7 +34,7 @@ public async Task GivenSinglePartAcceptHeader_WhenRetrieveInstance_ThenServerSho DicomFile inputDicomFile = DicomFile.Open(transcoderTestData.InputDicomFile); var instanceId = RandomizeInstanceIdentifier(inputDicomFile.Dataset); - await InternalStoreAsync(new[] { inputDicomFile }); + await _instancesManager.StoreAsync(new[] { inputDicomFile }); using DicomWebResponse response = await _client.RetrieveInstanceAsync(instanceId.StudyInstanceUid, instanceId.SeriesInstanceUid, instanceId.SopInstanceUid, transferSyntax); @@ -61,7 +61,7 @@ public async Task GivenMultipartAcceptHeader_WhenRetrieveInstance_ThenServerShou DicomFile inputDicomFile = DicomFile.Open(transcoderTestData.InputDicomFile); var instanceId = RandomizeInstanceIdentifier(inputDicomFile.Dataset); - await InternalStoreAsync(new[] { inputDicomFile }); + await _instancesManager.StoreAsync(new[] { inputDicomFile }); var requestUri = new Uri(DicomApiVersions.Latest + string.Format(DicomWebConstants.BaseInstanceUriFormat, instanceId.StudyInstanceUid, instanceId.SeriesInstanceUid, instanceId.SopInstanceUid), UriKind.Relative); @@ -96,7 +96,7 @@ public async Task GivenUnsupportedInternalTransferSyntax_WhenRetrieveInstance_Th transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile }); + await _instancesManager.StoreAsync(new[] { dicomFile }); DicomWebException exception = await Assert.ThrowsAsync(() => _client.RetrieveInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, dicomTransferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID)); Assert.Equal(HttpStatusCode.NotAcceptable, exception.StatusCode); } @@ -116,7 +116,7 @@ public async Task GivenUnsupportedInternalTransferSyntax_WhenRetrieveInstanceWit transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile }); + await _instancesManager.StoreAsync(new[] { dicomFile }); using DicomWebResponse instancesInStudy = await _client.RetrieveInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, dicomTransferSyntax: "*"); Assert.Equal(dicomFile.ToByteArray(), (await instancesInStudy.GetValueAsync()).ToByteArray()); @@ -136,7 +136,7 @@ public async Task GivenInstanceWithoutPixelData_WhenRetrieveInstance_ThenServerS var seriesInstanceUid = TestUidGenerator.Generate(); var sopInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUid, seriesInstanceUid, sopInstanceUid); - await InternalStoreAsync(new[] { dicomFile1 }); + await _instancesManager.StoreAsync(new[] { dicomFile1 }); using DicomWebResponse instanceRetrieve = await _client.RetrieveInstanceAsync(studyInstanceUid, seriesInstanceUid, sopInstanceUid, dicomTransferSyntax: "*"); Assert.Equal(dicomFile1.ToByteArray(), (await instanceRetrieve.GetValueAsync()).ToByteArray()); diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Series.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Series.cs index 416e3958fa..295b525385 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Series.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Series.cs @@ -33,7 +33,7 @@ public async Task GivenSupportedAcceptHeaders_WhenRetrieveSeries_ThenServerShoul TranscoderTestData transcoderTestData = TranscoderTestDataHelper.GetTestData(testDataFolder); DicomFile inputDicomFile = DicomFile.Open(transcoderTestData.InputDicomFile); var instanceId = RandomizeInstanceIdentifier(inputDicomFile.Dataset); - await InternalStoreAsync(new[] { inputDicomFile }); + await _instancesManager.StoreAsync(new[] { inputDicomFile }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveSeriesAsync(instanceId.StudyInstanceUid, instanceId.SeriesInstanceUid, transferSyntax); Assert.Equal(DicomWebConstants.MultipartRelatedMediaType, response.ContentHeaders.ContentType.MediaType); @@ -86,7 +86,7 @@ public async Task GivenMultipleInstances_WhenRetrieveSeries_ThenServerShouldRetu TestUidGenerator.Generate(), transferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID); - await InternalStoreAsync(new[] { dicomFile1, dicomFile2, dicomFile3 }); + await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2, dicomFile3 }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveSeriesAsync(studyInstanceUid, seriesInstanceUid); @@ -117,7 +117,7 @@ public async Task GivenMultipleInstancesWithMixTransferSyntax_WhenRetrieveSeries transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile1, dicomFile2 }); + await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2 }); DicomWebException exception = await Assert.ThrowsAsync(() => _client.RetrieveSeriesAsync(studyInstanceUid, seriesInstanceUid, dicomTransferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID)); Assert.Equal(HttpStatusCode.NotAcceptable, exception.StatusCode); @@ -140,7 +140,7 @@ public async Task GivenMultipleInstancesWithMixTransferSyntax_WhenRetrieveSeries transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile1, dicomFile2 }); + await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2 }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveSeriesAsync(studyInstanceUid, seriesInstanceUid, dicomTransferSyntax: "*"); @@ -167,7 +167,7 @@ public async Task GivenInstanceWithoutPixelData_WhenRetrieveSeries_ThenServerSho var studyInstanceUid = TestUidGenerator.Generate(); var seriesInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUid, seriesInstanceUid); - await InternalStoreAsync(new[] { dicomFile1 }); + await _instancesManager.StoreAsync(new[] { dicomFile1 }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveSeriesAsync(studyInstanceUid, seriesInstanceUid, dicomTransferSyntax: "*"); diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Study.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Study.cs index 87a12ddcc7..d1557683a2 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Study.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/RetrieveTransactionResourceTests.Study.cs @@ -34,7 +34,7 @@ public async Task GivenSupportedAcceptHeaders_WhenRetrieveStudy_ThenServerShould DicomFile inputDicomFile = DicomFile.Open(transcoderTestData.InputDicomFile); var instanceId = RandomizeInstanceIdentifier(inputDicomFile.Dataset); - await InternalStoreAsync(new[] { inputDicomFile }); + await _instancesManager.StoreAsync(new[] { inputDicomFile }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveStudyAsync(instanceId.StudyInstanceUid, transferSyntax); Assert.Equal(DicomWebConstants.MultipartRelatedMediaType, response.ContentHeaders.ContentType.MediaType); @@ -87,7 +87,7 @@ public async Task GivenMultipleInstances_WhenRetrieveStudy_ThenServerShouldRetur TestUidGenerator.Generate(), transferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID); - await InternalStoreAsync(new[] { dicomFile1, dicomFile2, dicomFile3 }); + await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2, dicomFile3 }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveStudyAsync(studyInstanceUid); @@ -117,7 +117,7 @@ public async Task GivenMultipleInstancesWithMixTransferSyntax_WhenRetrieveStudy_ transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile1, dicomFile2 }); + await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2 }); DicomWebException exception = await Assert.ThrowsAsync(() => _client.RetrieveStudyAsync(studyInstanceUid, dicomTransferSyntax: DicomTransferSyntax.ExplicitVRLittleEndian.UID.UID)); Assert.Equal(HttpStatusCode.NotAcceptable, exception.StatusCode); } @@ -138,7 +138,7 @@ public async Task GivenMultipleInstancesWithMixTransferSyntax_WhenRetrieveStudyW transferSyntax: DicomTransferSyntax.MPEG2.UID.UID, encode: false); - await InternalStoreAsync(new[] { dicomFile1, dicomFile2 }); + await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2 }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveStudyAsync(studyInstanceUid, dicomTransferSyntax: "*"); @@ -164,7 +164,7 @@ public async Task GivenInstanceWithoutPixelData_WhenRetrieveStudy_ThenThenServer { var studyInstanceUid = TestUidGenerator.Generate(); DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUid); - await InternalStoreAsync(new[] { dicomFile1 }); + await _instancesManager.StoreAsync(new[] { dicomFile1 }); using DicomWebAsyncEnumerableResponse response = await _client.RetrieveStudyAsync(studyInstanceUid, dicomTransferSyntax: "*"); diff --git a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/StoreTransactionTests.cs b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/StoreTransactionTests.cs index f37c19834a..8d3f917586 100644 --- a/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/StoreTransactionTests.cs +++ b/test/Microsoft.Health.Dicom.Web.Tests.E2E/Rest/StoreTransactionTests.cs @@ -14,13 +14,14 @@ using EnsureThat; using Microsoft.Health.Dicom.Client; using Microsoft.Health.Dicom.Tests.Common; +using Microsoft.Health.Dicom.Web.Tests.E2E.Common; using Microsoft.IO; using Microsoft.Net.Http.Headers; using Xunit; namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest { - public class StoreTransactionTests : IClassFixture> + public class StoreTransactionTests : IClassFixture>, IAsyncLifetime { private const ushort ValidationFailedFailureCode = 43264; private const ushort SopInstanceAlreadyExistsFailureCode = 45070; @@ -28,11 +29,13 @@ public class StoreTransactionTests : IClassFixture fixture) { EnsureArg.IsNotNull(fixture, nameof(fixture)); - _client = fixture.Client; + _client = fixture.GetDicomWebClient(); + _instancesManager = new DicomInstancesManager(_client); _recyclableMemoryStreamManager = fixture.RecyclableMemoryStreamManager; } @@ -89,7 +92,7 @@ public async Task GivenAMultipartRequestWithNoContent_WhenStoring_TheServerShoul var multiContent = new MultipartContent("related"); multiContent.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("type", $"\"{DicomWebConstants.MediaTypeApplicationDicom.MediaType}\"")); - using DicomWebResponse response = await _client.StoreAsync(multiContent); + using DicomWebResponse response = await _instancesManager.StoreAsync(multiContent); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); } @@ -105,7 +108,7 @@ public async Task GivenAMultipartRequestWithEmptyContent_WhenStoring_TheServerSh multiContent.Add(byteContent); DicomWebException exception = await Assert.ThrowsAsync( - () => _client.StoreAsync(multiContent)); + () => _instancesManager.StoreAsync(multiContent)); Assert.Equal(HttpStatusCode.Conflict, exception.StatusCode); } @@ -135,7 +138,7 @@ public async Task GivenAMultipartRequestWithAnInvalidMultipartSection_WhenStorin multiContent.Add(validByteContent); } - using DicomWebResponse response = await _client.StoreAsync(multiContent); + using DicomWebResponse response = await _instancesManager.StoreAsync(multiContent, instanceId: DicomInstanceId.FromDicomFile(validFile)); Assert.Equal(HttpStatusCode.Accepted, response.StatusCode); @@ -169,7 +172,7 @@ public async Task GivenAMultipartRequestWithTypeParameterAndFirstSectionWithoutC multiContent.Add(byteContent); } - using DicomWebResponse response = await _client.StoreAsync(multiContent); + using DicomWebResponse response = await _instancesManager.StoreAsync(multiContent, instanceId: DicomInstanceId.FromDicomFile(dicomFile)); Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -191,7 +194,7 @@ public async Task GivenAllDifferentStudyInstanceUIDs_WhenStoringWithProvidedStud var studyInstanceUID = TestUidGenerator.Generate(); - DicomWebException exception = await Assert.ThrowsAsync(() => _client.StoreAsync( + DicomWebException exception = await Assert.ThrowsAsync(() => _instancesManager.StoreAsync( new[] { dicomFile1, dicomFile2 }, studyInstanceUid: studyInstanceUID)); Assert.Equal(HttpStatusCode.Conflict, exception.StatusCode); @@ -219,7 +222,7 @@ public async Task GivenOneDifferentStudyInstanceUID_WhenStoringWithProvidedStudy DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUid: studyInstanceUID1); DicomFile dicomFile2 = Samples.CreateRandomDicomFile(studyInstanceUid: studyInstanceUID2); - using DicomWebResponse response = await _client.StoreAsync(new[] { dicomFile1, dicomFile2 }, studyInstanceUid: studyInstanceUID1); + using DicomWebResponse response = await _instancesManager.StoreAsync(new[] { dicomFile1, dicomFile2 }, studyInstanceUid: studyInstanceUID1); Assert.Equal(HttpStatusCode.Accepted, response.StatusCode); @@ -250,7 +253,7 @@ public async Task GivenDatasetWithDuplicateIdentifiers_WhenStoring_TheServerShou var studyInstanceUID = TestUidGenerator.Generate(); DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUID, studyInstanceUID); - DicomWebException exception = await Assert.ThrowsAsync(() => _client.StoreAsync(new[] { dicomFile1 })); + DicomWebException exception = await Assert.ThrowsAsync(() => _instancesManager.StoreAsync(new[] { dicomFile1 })); Assert.Equal(HttpStatusCode.Conflict, exception.StatusCode); @@ -272,7 +275,7 @@ public async Task GivenExistingDataset_WhenStoring_TheServerShouldReturnConflict { DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUID); - using DicomWebResponse response = await _client.StoreAsync(new[] { dicomFile1 }); + using DicomWebResponse response = await _instancesManager.StoreAsync(new[] { dicomFile1 }); Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -285,7 +288,7 @@ public async Task GivenExistingDataset_WhenStoring_TheServerShouldReturnConflict Assert.False(dataset.TryGetSequence(DicomTag.FailedSOPSequence, out DicomSequence _)); DicomWebException exception = await Assert.ThrowsAsync( - () => _client.StoreAsync(new[] { dicomFile1 })); + () => _instancesManager.StoreAsync(new[] { dicomFile1 })); Assert.Equal(HttpStatusCode.Conflict, exception.StatusCode); @@ -306,7 +309,7 @@ public async Task GivenDatasetWithInvalidVrValue_WhenStoring_TheServerShouldRetu DicomFile dicomFile1 = Samples.CreateRandomDicomFileWithInvalidVr(studyInstanceUID); - DicomWebException exception = await Assert.ThrowsAsync(() => _client.StoreAsync(new[] { dicomFile1 })); + DicomWebException exception = await Assert.ThrowsAsync(() => _instancesManager.StoreAsync(new[] { dicomFile1 })); Assert.Equal(HttpStatusCode.Conflict, exception.StatusCode); Assert.False(exception.ResponseDataset.TryGetSequence(DicomTag.ReferencedSOPSequence, out DicomSequence _)); @@ -323,7 +326,7 @@ public async Task GivenDatasetWithInvalidUid_WhenStoring_TheServerShouldReturnCo { DicomFile dicomFile1 = Samples.CreateRandomDicomFile(studyInstanceUID, validateItems: false); - DicomWebException exception = await Assert.ThrowsAsync(() => _client.StoreAsync(new[] { dicomFile1 })); + DicomWebException exception = await Assert.ThrowsAsync(() => _instancesManager.StoreAsync(new[] { dicomFile1 })); Assert.Equal(HttpStatusCode.Conflict, exception.StatusCode); @@ -343,7 +346,7 @@ public async Task StoreSinglepart_ServerShouldReturnOK() await using MemoryStream stream = _recyclableMemoryStreamManager.GetStream(); await dicomFile.SaveAsync(stream); - using DicomWebResponse response = await _client.StoreAsync(stream); + using DicomWebResponse response = await _instancesManager.StoreAsync(stream, instanceId: DicomInstanceId.FromDicomFile(dicomFile)); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } @@ -353,7 +356,7 @@ public async Task StoreSinglepartWithStudyUID_ServerShouldReturnOK() var studyInstanceUID = TestUidGenerator.Generate(); DicomFile dicomFile = Samples.CreateRandomDicomFile(studyInstanceUid: studyInstanceUID); - using DicomWebResponse response = await _client.StoreAsync(dicomFile, studyInstanceUid: studyInstanceUID); + using DicomWebResponse response = await _instancesManager.StoreAsync(dicomFile, studyInstanceUid: studyInstanceUID); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } @@ -365,6 +368,12 @@ public static IEnumerable GetIncorrectAcceptHeaders yield return new object[] { "application/data" }; } } + public Task InitializeAsync() => Task.CompletedTask; + + public async Task DisposeAsync() + { + await _instancesManager.DisposeAsync(); + } private (string SopInstanceUid, string RetrieveUri, string SopClassUid) ConvertToReferencedSopSequenceEntry(DicomDataset dicomDataset) {