Skip to content

Commit b7b2c2a

Browse files
committed
test: refactor CopyToTemporaryStreamTests
Signed-off-by: Kenny Pflug <kenny.pflug@live.de>
1 parent 558af0f commit b7b2c2a

File tree

1 file changed

+126
-100
lines changed

1 file changed

+126
-100
lines changed

tests/Light.TemporaryStreams.Core.Tests/CopyToTemporaryStreamTests.cs

Lines changed: 126 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Immutable;
33
using System.IO;
44
using System.Security.Cryptography;
5+
using System.Threading;
56
using System.Threading.Tasks;
67
using FluentAssertions;
78
using Light.TemporaryStreams.Hashing;
@@ -17,10 +18,8 @@ public static class CopyToTemporaryStreamTests
1718
public static async Task CopyToTemporaryStreamAsync_ShouldCreateMemoryStream_WhenSourceIsSmall(int bufferSize)
1819
{
1920
// Arrange
21+
var (service, sourceData, sourceStream) = CreateTestSetup(bufferSize);
2022
var cancellationToken = TestContext.Current.CancellationToken;
21-
var service = CreateDefaultService();
22-
var sourceData = CreateTestData(bufferSize);
23-
using var sourceStream = new MemoryStream(sourceData);
2423

2524
// Act
2625
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
@@ -29,13 +28,12 @@ public static async Task CopyToTemporaryStreamAsync_ShouldCreateMemoryStream_Whe
2928
);
3029

3130
// Assert
32-
temporaryStream.Should().NotBeNull();
33-
temporaryStream.IsFileBased.Should().BeFalse();
34-
temporaryStream.Length.Should().Be(sourceData.Length);
35-
temporaryStream.Position = 0;
36-
var copiedData = new byte[sourceData.Length];
37-
await temporaryStream.ReadExactlyAsync(copiedData, cancellationToken);
38-
copiedData.Should().Equal(sourceData);
31+
await AssertTemporaryStreamContentsMatchAsync(
32+
temporaryStream,
33+
sourceData,
34+
expectFileBased: false,
35+
cancellationToken
36+
);
3937
}
4038

4139
[Theory]
@@ -44,10 +42,8 @@ public static async Task CopyToTemporaryStreamAsync_ShouldCreateMemoryStream_Whe
4442
public static async Task CopyToTemporaryStreamAsync_ShouldCreateFileStream_WhenSourceIsLarge(int bufferSize)
4543
{
4644
// Arrange
45+
var (service, sourceData, sourceStream) = CreateTestSetup(bufferSize);
4746
var cancellationToken = TestContext.Current.CancellationToken;
48-
var service = CreateDefaultService();
49-
var sourceData = CreateTestData(bufferSize); // More than 80KB threshold
50-
using var sourceStream = new MemoryStream(sourceData);
5147

5248
// Act
5349
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
@@ -56,23 +52,20 @@ public static async Task CopyToTemporaryStreamAsync_ShouldCreateFileStream_WhenS
5652
);
5753

5854
// Assert
59-
temporaryStream.Should().NotBeNull();
60-
temporaryStream.IsFileBased.Should().BeTrue();
61-
temporaryStream.Length.Should().Be(sourceData.Length);
62-
temporaryStream.Position = 0;
63-
var copiedData = new byte[sourceData.Length];
64-
await temporaryStream.ReadExactlyAsync(copiedData, cancellationToken);
65-
copiedData.Should().Equal(sourceData);
55+
await AssertTemporaryStreamContentsMatchAsync(
56+
temporaryStream,
57+
sourceData,
58+
expectFileBased: true,
59+
cancellationToken
60+
);
6661
}
6762

6863
[Fact]
6964
public static async Task CopyToTemporaryStreamAsync_ShouldUseCopyBufferSize_WhenSpecified()
7065
{
71-
var cancellationToken = TestContext.Current.CancellationToken;
7266
// Arrange
73-
var service = CreateDefaultService();
74-
var sourceData = CreateTestData(100_000);
75-
using var sourceStream = new MemoryStream(sourceData);
67+
var (service, sourceData, sourceStream) = CreateTestSetup(100_000);
68+
var cancellationToken = TestContext.Current.CancellationToken;
7669
var filePath = Path.GetFullPath("test.txt");
7770

7871
// Act
@@ -83,21 +76,20 @@ public static async Task CopyToTemporaryStreamAsync_ShouldUseCopyBufferSize_When
8376
);
8477

8578
// Assert
86-
temporaryStream.Should().NotBeNull();
87-
temporaryStream.Length.Should().Be(sourceData.Length);
88-
temporaryStream.IsFileBased.Should().BeTrue();
89-
temporaryStream.GetUnderlyingFilePath().Should().Be(filePath);
79+
await AssertTemporaryStreamContentsMatchAsync(
80+
temporaryStream,
81+
sourceData,
82+
expectFileBased: true,
83+
cancellationToken
84+
);
9085
}
9186

9287
[Fact]
9388
public static async Task CopyToTemporaryStreamAsync_ShouldUseCustomOptions_WhenProvided()
9489
{
9590
// Arrange
91+
var (service, sourceData, sourceStream) = CreateTestSetup(50_000); // Would normally use MemoryStream
9692
var cancellationToken = TestContext.Current.CancellationToken;
97-
var service = CreateDefaultService();
98-
var sourceData = CreateTestData(50_000); // Would normally use MemoryStream
99-
using var sourceStream = new MemoryStream(sourceData);
100-
10193
var customOptions = new TemporaryStreamServiceOptions
10294
{
10395
FileThresholdInBytes = 30_000 // Force FileStream usage
@@ -111,19 +103,20 @@ public static async Task CopyToTemporaryStreamAsync_ShouldUseCustomOptions_WhenP
111103
);
112104

113105
// Assert
114-
temporaryStream.Should().NotBeNull();
115-
temporaryStream.IsFileBased.Should().BeTrue(); // Should use file due to custom threshold
116-
temporaryStream.Length.Should().Be(sourceData.Length);
106+
await AssertTemporaryStreamContentsMatchAsync(
107+
temporaryStream,
108+
sourceData,
109+
expectFileBased: true,
110+
cancellationToken
111+
);
117112
}
118113

119114
[Fact]
120115
public static async Task CopyToTemporaryStreamAsync_ShouldForwardFilePath()
121116
{
122117
// Arrange
118+
var (service, sourceData, sourceStream) = CreateTestSetup(100_000);
123119
var cancellationToken = TestContext.Current.CancellationToken;
124-
var service = CreateDefaultService();
125-
var sourceData = CreateTestData(100_000);
126-
using var sourceStream = new MemoryStream(sourceData);
127120

128121
// Act
129122
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
@@ -133,13 +126,12 @@ public static async Task CopyToTemporaryStreamAsync_ShouldForwardFilePath()
133126
);
134127

135128
// Assert
136-
temporaryStream.Should().NotBeNull();
137-
temporaryStream.IsFileBased.Should().BeTrue();
138-
temporaryStream.Length.Should().Be(sourceData.Length);
139-
temporaryStream.Position = 0;
140-
var copiedData = new byte[sourceData.Length];
141-
await temporaryStream.ReadExactlyAsync(copiedData, cancellationToken);
142-
copiedData.Should().Equal(sourceData);
129+
await AssertTemporaryStreamContentsMatchAsync(
130+
temporaryStream,
131+
sourceData,
132+
expectFileBased: true,
133+
cancellationToken
134+
);
143135
}
144136

145137
[Theory]
@@ -150,12 +142,12 @@ HashConversionMethod hashConversionMethod
150142
)
151143
{
152144
// Arrange
145+
var (service, sourceData, sourceStream) = CreateTestSetup(40_000); // Less than 80KB threshold
153146
var cancellationToken = TestContext.Current.CancellationToken;
154-
var service = CreateDefaultService();
155-
var sourceData = CreateTestData(40_000); // Less than 80KB threshold
156-
using var sourceStream = new MemoryStream(sourceData);
157-
await using var hashingPlugin =
158-
new HashingPlugin([new CopyToHashCalculator(SHA1.Create(), hashConversionMethod)]);
147+
var (hashingPlugin, expectedHash) = CreateHashingPluginWithExpectedHash(
148+
sourceData,
149+
new CopyToHashCalculator(SHA1.Create(), hashConversionMethod)
150+
);
159151

160152
// Act
161153
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
@@ -165,14 +157,12 @@ HashConversionMethod hashConversionMethod
165157
);
166158

167159
// Assert
168-
temporaryStream.Should().NotBeNull();
169-
temporaryStream.IsFileBased.Should().BeFalse();
170-
temporaryStream.Length.Should().Be(sourceData.Length);
171-
temporaryStream.Position = 0;
172-
var expectedHash = HashConverter.ConvertHashToString(SHA1.HashData(sourceData), hashConversionMethod);
173-
var copiedData = new byte[sourceData.Length];
174-
await temporaryStream.ReadExactlyAsync(copiedData, cancellationToken);
175-
copiedData.Should().Equal(sourceData);
160+
await AssertTemporaryStreamContentsMatchAsync(
161+
temporaryStream,
162+
sourceData,
163+
expectFileBased: false,
164+
cancellationToken
165+
);
176166
hashingPlugin.GetHash(nameof(SHA1)).Should().Be(expectedHash);
177167
}
178168

@@ -184,12 +174,12 @@ HashConversionMethod hashConversionMethod
184174
)
185175
{
186176
// Arrange
177+
var (service, sourceData, sourceStream) = CreateTestSetup(100_000); // More than 80KB threshold
187178
var cancellationToken = TestContext.Current.CancellationToken;
188-
var service = CreateDefaultService();
189-
var sourceData = CreateTestData(100_000); // More than 80KB threshold
190-
using var sourceStream = new MemoryStream(sourceData);
191-
await using var hashingPlugin =
192-
new HashingPlugin([new CopyToHashCalculator(MD5.Create(), hashConversionMethod)]);
179+
var (hashingPlugin, expectedHash) = CreateHashingPluginWithExpectedHash(
180+
sourceData,
181+
new CopyToHashCalculator(MD5.Create(), hashConversionMethod)
182+
);
193183

194184
// Act
195185
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
@@ -199,43 +189,25 @@ HashConversionMethod hashConversionMethod
199189
);
200190

201191
// Assert
202-
temporaryStream.Should().NotBeNull();
203-
temporaryStream.IsFileBased.Should().BeTrue();
204-
temporaryStream.Length.Should().Be(sourceData.Length);
205-
temporaryStream.Position = 0;
206-
var copiedData = new byte[sourceData.Length];
207-
await temporaryStream.ReadExactlyAsync(copiedData, cancellationToken);
208-
copiedData.Should().Equal(sourceData);
209-
var expectedHash = HashConverter.ConvertHashToString(MD5.HashData(sourceData), hashConversionMethod);
192+
await AssertTemporaryStreamContentsMatchAsync(
193+
temporaryStream,
194+
sourceData,
195+
expectFileBased: true,
196+
cancellationToken
197+
);
210198
hashingPlugin.GetHash(nameof(MD5)).Should().Be(expectedHash);
211199
}
212200

213201
[Fact]
214202
public static async Task CopyToTemporaryStreamAsync_WithHashingPlugin_ShouldSupportMultipleHashAlgorithms()
215203
{
216204
// Arrange
205+
var (service, sourceData, sourceStream) = CreateTestSetup(50_000);
217206
var cancellationToken = TestContext.Current.CancellationToken;
218-
var service = CreateDefaultService();
219-
var sourceData = CreateTestData(50_000);
220-
using var sourceStream = new MemoryStream(sourceData);
221-
222-
await using var hashingPlugin = new HashingPlugin(
223-
[
224-
new CopyToHashCalculator(SHA1.Create(), HashConversionMethod.UpperHexadecimal),
225-
new CopyToHashCalculator(SHA256.Create(), HashConversionMethod.Base64)
226-
]
227-
);
228207

229-
// Act
230-
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
231-
sourceStream,
232-
[hashingPlugin],
233-
cancellationToken: cancellationToken
234-
);
208+
var sha1Calculator = new CopyToHashCalculator(SHA1.Create(), HashConversionMethod.UpperHexadecimal);
209+
var sha256Calculator = new CopyToHashCalculator(SHA256.Create(), HashConversionMethod.Base64);
235210

236-
// Assert
237-
temporaryStream.Should().NotBeNull();
238-
temporaryStream.Length.Should().Be(sourceData.Length);
239211
var expectedSha1Hash = HashConverter.ConvertHashToString(
240212
SHA1.HashData(sourceData),
241213
HashConversionMethod.UpperHexadecimal
@@ -244,6 +216,17 @@ public static async Task CopyToTemporaryStreamAsync_WithHashingPlugin_ShouldSupp
244216
SHA256.HashData(sourceData),
245217
HashConversionMethod.Base64
246218
);
219+
220+
await using var hashingPlugin = new HashingPlugin([sha1Calculator, sha256Calculator]);
221+
222+
// Act
223+
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
224+
sourceStream,
225+
[hashingPlugin],
226+
cancellationToken: cancellationToken
227+
);
228+
229+
// Assert
247230
hashingPlugin.GetHash(nameof(SHA1)).Should().Be(expectedSha1Hash);
248231
hashingPlugin.GetHash(nameof(SHA256)).Should().Be(expectedSha256Hash);
249232
}
@@ -252,11 +235,12 @@ public static async Task CopyToTemporaryStreamAsync_WithHashingPlugin_ShouldSupp
252235
public static async Task CopyToTemporaryStreamAsync_WithHashingPlugin_ShouldUseCustomBufferSize()
253236
{
254237
// Arrange
238+
var (service, sourceData, sourceStream) = CreateTestSetup(60_000);
255239
var cancellationToken = TestContext.Current.CancellationToken;
256-
var service = CreateDefaultService();
257-
var sourceData = CreateTestData(60_000);
258-
using var sourceStream = new MemoryStream(sourceData);
259-
await using var hashingPlugin = new HashingPlugin([SHA1.Create()]);
240+
var (hashingPlugin, expectedHash) = CreateHashingPluginWithExpectedHash(
241+
sourceData,
242+
new CopyToHashCalculator(SHA1.Create(), HashConversionMethod.Base64)
243+
);
260244

261245
// Act
262246
await using var temporaryStream = await service.CopyToTemporaryStreamAsync(
@@ -269,19 +253,19 @@ public static async Task CopyToTemporaryStreamAsync_WithHashingPlugin_ShouldUseC
269253
// Assert
270254
temporaryStream.Should().NotBeNull();
271255
temporaryStream.Length.Should().Be(sourceData.Length);
272-
var expectedHash = HashConverter.ConvertHashToString(SHA1.HashData(sourceData), HashConversionMethod.Base64);
273256
hashingPlugin.GetHash(nameof(SHA1)).Should().Be(expectedHash);
274257
}
275258

276259
[Fact]
277260
public static async Task CopyToTemporaryStreamAsync_WithHashingPlugin_ShouldForwardFilePath()
278261
{
279262
// Arrange
263+
var (service, sourceData, sourceStream) = CreateTestSetup(100_000);
280264
var cancellationToken = TestContext.Current.CancellationToken;
281-
var service = CreateDefaultService();
282-
var sourceData = CreateTestData(100_000);
283-
using var sourceStream = new MemoryStream(sourceData);
284-
await using var hashingPlugin = new HashingPlugin([SHA1.Create()]);
265+
var (hashingPlugin, expectedHash) = CreateHashingPluginWithExpectedHash(
266+
sourceData,
267+
new CopyToHashCalculator(SHA1.Create(), HashConversionMethod.Base64)
268+
);
285269
var filePath = Path.GetFullPath("test.txt");
286270

287271
// Act
@@ -297,10 +281,52 @@ public static async Task CopyToTemporaryStreamAsync_WithHashingPlugin_ShouldForw
297281
temporaryStream.IsFileBased.Should().BeTrue();
298282
temporaryStream.Length.Should().Be(sourceData.Length);
299283
temporaryStream.GetUnderlyingFilePath().Should().Be(filePath);
300-
var expectedHash = HashConverter.ConvertHashToString(SHA1.HashData(sourceData), HashConversionMethod.Base64);
301284
hashingPlugin.GetHash(nameof(SHA1)).Should().Be(expectedHash);
302285
}
303286

287+
private static (TemporaryStreamService service, byte[] sourceData, MemoryStream sourceStream) CreateTestSetup(
288+
int dataSize
289+
)
290+
{
291+
var service = CreateDefaultService();
292+
var sourceData = CreateTestData(dataSize);
293+
var sourceStream = new MemoryStream(sourceData);
294+
295+
return (service, sourceData, sourceStream);
296+
}
297+
298+
private static async Task AssertTemporaryStreamContentsMatchAsync(
299+
TemporaryStream temporaryStream,
300+
byte[] expectedData,
301+
bool expectFileBased,
302+
CancellationToken cancellationToken
303+
)
304+
{
305+
temporaryStream.Should().NotBeNull();
306+
temporaryStream.IsFileBased.Should().Be(expectFileBased);
307+
temporaryStream.Length.Should().Be(expectedData.Length);
308+
309+
temporaryStream.Position = 0;
310+
var copiedData = new byte[expectedData.Length];
311+
await temporaryStream.ReadExactlyAsync(copiedData, cancellationToken);
312+
copiedData.Should().Equal(expectedData);
313+
}
314+
315+
private static (HashingPlugin plugin, string expectedHash) CreateHashingPluginWithExpectedHash(
316+
byte[] sourceData,
317+
CopyToHashCalculator hashCalculator
318+
)
319+
{
320+
var plugin = new HashingPlugin([hashCalculator]);
321+
322+
var expectedHash = HashConverter.ConvertHashToString(
323+
hashCalculator.HashAlgorithm.ComputeHash(sourceData),
324+
hashCalculator.ConversionMethod
325+
);
326+
327+
return (plugin, expectedHash);
328+
}
329+
304330
private static TemporaryStreamService CreateDefaultService() =>
305331
new (
306332
new TemporaryStreamServiceOptions(),

0 commit comments

Comments
 (0)