namespace System.IO.Tests
{
- // WriteChars_VeryLargeArray_DoesNotOverflow allocates a lot of memory and can cause OOM,
- // it should not be executed in parallel with other tests
- [Collection(nameof(DisableParallelization))]
public class BinaryWriter_EncodingTests
{
[Fact]
Assert.Equal(expectedBytes, stream.GetBuffer()[Get7BitEncodedIntByteLength((uint)expectedBytes.Length)..(int)stream.Length]);
}
- [OuterLoop("Allocates a lot of memory")]
- [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
- [SkipOnPlatform(TestPlatforms.Android, "OOM on Android could be uncatchable & kill the test runner")]
- public unsafe void WriteChars_VeryLargeArray_DoesNotOverflow()
- {
- const nuint INT32_OVERFLOW_SIZE = (nuint)int.MaxValue + 3;
-
- SafeBuffer unmanagedBuffer = null;
- try
- {
- try
- {
- unmanagedBuffer = SafeBufferUtil.CreateSafeBuffer(INT32_OVERFLOW_SIZE * sizeof(byte));
- }
- catch (OutOfMemoryException)
- {
- throw new SkipTestException($"Unable to execute {nameof(WriteChars_VeryLargeArray_DoesNotOverflow)} due to OOM"); // skip test in low-mem conditions
- }
-
- Assert.True((long)unmanagedBuffer.ByteLength > int.MaxValue);
-
- // reuse same memory for input and output to avoid allocating more memory and OOMs
- Span<char> span = new Span<char>((char*)unmanagedBuffer.DangerousGetHandle(), (int)(INT32_OVERFLOW_SIZE / sizeof(char)));
- span.Fill('\u0224'); // LATIN CAPITAL LETTER Z WITH HOOK
- Stream outStream = new UnmanagedMemoryStream(unmanagedBuffer, 0, (long)unmanagedBuffer.ByteLength, FileAccess.ReadWrite);
- BinaryWriter writer = new BinaryWriter(outStream);
-
- writer.Write(span); // will write slightly more than int.MaxValue bytes to the output
-
- Assert.Equal((long)INT32_OVERFLOW_SIZE, outStream.Position);
- }
- finally
- {
- unmanagedBuffer?.Dispose();
- }
- }
-
private static bool IsUsingFastUtf8(BinaryWriter writer)
{
return (bool)writer.GetType().GetField("_useFastUtf8", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(writer);
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Numerics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit;
+
+namespace System.IO.Tests
+{
+ // WriteChars_VeryLargeArray_DoesNotOverflow allocates a lot of memory and can cause OOM,
+ // it should not be executed in parallel with other tests
+ [Collection(nameof(DisableParallelization))]
+ public class BinaryWriter_EncodingTests_Serial
+ {
+ [OuterLoop("Allocates a lot of memory")]
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))]
+ [SkipOnPlatform(TestPlatforms.Android, "OOM on Android could be uncatchable & kill the test runner")]
+ public unsafe void WriteChars_VeryLargeArray_DoesNotOverflow()
+ {
+ const nuint INT32_OVERFLOW_SIZE = (nuint)int.MaxValue + 3;
+
+ SafeBuffer unmanagedBuffer = null;
+ try
+ {
+ try
+ {
+ unmanagedBuffer = SafeBufferUtil.CreateSafeBuffer(INT32_OVERFLOW_SIZE * sizeof(byte));
+ }
+ catch (OutOfMemoryException)
+ {
+ throw new SkipTestException($"Unable to execute {nameof(WriteChars_VeryLargeArray_DoesNotOverflow)} due to OOM"); // skip test in low-mem conditions
+ }
+
+ Assert.True((long)unmanagedBuffer.ByteLength > int.MaxValue);
+
+ // reuse same memory for input and output to avoid allocating more memory and OOMs
+ Span<char> span = new Span<char>((char*)unmanagedBuffer.DangerousGetHandle(), (int)(INT32_OVERFLOW_SIZE / sizeof(char)));
+ span.Fill('\u0224'); // LATIN CAPITAL LETTER Z WITH HOOK
+ Stream outStream = new UnmanagedMemoryStream(unmanagedBuffer, 0, (long)unmanagedBuffer.ByteLength, FileAccess.ReadWrite);
+ BinaryWriter writer = new BinaryWriter(outStream);
+
+ writer.Write(span); // will write slightly more than int.MaxValue bytes to the output
+
+ Assert.Equal((long)INT32_OVERFLOW_SIZE, outStream.Position);
+ }
+ finally
+ {
+ unmanagedBuffer?.Dispose();
+ }
+ }
+ }
+}
Assert.Equal(token, ex.CancellationToken);
}
- [OuterLoop("It creates 1GB file")]
- [Fact]
- [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
- public async Task ReadToEndAsync_WithCancellation()
- {
- string path = GetTestFilePath();
- CreateLargeFile(path);
-
- using StreamReader reader = File.OpenText(path);
- using CancellationTokenSource cts = new();
- var token = cts.Token;
-
- var ex = await Assert.ThrowsAnyAsync<OperationCanceledException>(async () =>
- {
- Task<string> readToEndTask = reader.ReadToEndAsync(token);
-
- // This is a time-sensitive test where the cancellation needs to happen before the async read completes.
- // A sleep may be too long a delay, so spin-wait for a very short duration before canceling.
- SpinWait spinner = default;
- while (!spinner.NextSpinWillYield)
- {
- spinner.SpinOnce(sleep1Threshold: -1);
- }
-
- cts.Cancel();
- await readToEndTask;
- });
- Assert.Equal(token, ex.CancellationToken);
- }
-
- private void CreateLargeFile(string path)
- {
- const string sentence = "A very large file used for testing StreamReader cancellation. 0123456789012345678901234567890123456789.";
- const int repeatCount = 10_000_000;
- Encoding encoding = Encoding.UTF8;
-
- using FileStream fs = File.OpenWrite(path);
- long fileSize = encoding.GetByteCount(sentence) * repeatCount;
-
- try
- {
- fs.SetLength(fileSize);
- }
- catch (IOException)
- {
- throw new SkipTestException($"Unable to run {ReadToEndAsync_WithCancellation} due to lack of available disk space");
- }
-
- using StreamWriter streamWriter = new StreamWriter(fs, encoding);
- for (int i = 0; i < repeatCount; i++)
- {
- streamWriter.WriteLine(sentence);
- }
- }
-
[Fact]
public void GetBaseStream()
{
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO.Pipes;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit;
+
+namespace System.IO.Tests
+{
+ // Run these tests on their own as they use a lot of disk space
+ [Collection(nameof(DisableParallelization))]
+ public partial class StreamReaderTests_Serial : FileCleanupTestBase
+ {
+ [OuterLoop("It creates 1GB file")]
+ [Fact]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
+ public async Task ReadToEndAsync_WithCancellation()
+ {
+ string path = GetTestFilePath();
+ CreateLargeFile(path);
+
+ using StreamReader reader = File.OpenText(path);
+ using CancellationTokenSource cts = new();
+ var token = cts.Token;
+
+ var ex = await Assert.ThrowsAnyAsync<OperationCanceledException>(async () =>
+ {
+ Task<string> readToEndTask = reader.ReadToEndAsync(token);
+
+ // This is a time-sensitive test where the cancellation needs to happen before the async read completes.
+ // A sleep may be too long a delay, so spin-wait for a very short duration before canceling.
+ SpinWait spinner = default;
+ while (!spinner.NextSpinWillYield)
+ {
+ spinner.SpinOnce(sleep1Threshold: -1);
+ }
+
+ cts.Cancel();
+ await readToEndTask;
+ });
+ Assert.Equal(token, ex.CancellationToken);
+ }
+
+ private void CreateLargeFile(string path)
+ {
+ const string sentence = "A very large file used for testing StreamReader cancellation. 0123456789012345678901234567890123456789.";
+ const int repeatCount = 10_000_000;
+ Encoding encoding = Encoding.UTF8;
+
+ using FileStream fs = File.OpenWrite(path);
+ long fileSize = encoding.GetByteCount(sentence) * repeatCount;
+
+ try
+ {
+ fs.SetLength(fileSize);
+ }
+ catch (IOException)
+ {
+ throw new SkipTestException($"Unable to run {ReadToEndAsync_WithCancellation} due to lack of available disk space");
+ }
+
+ using StreamWriter streamWriter = new StreamWriter(fs, encoding);
+ for (int i = 0; i < repeatCount; i++)
+ {
+ streamWriter.WriteLine(sentence);
+ }
+ }
+ }
+}
<Compile Include="StreamWriter\StreamWriter.StringCtorTests.cs" />
<Compile Include="BinaryWriter\BinaryWriter.DisposeAsync.cs" />
<Compile Include="BinaryWriter\BinaryWriter.EncodingTests.cs" />
+ <Compile Include="BinaryWriter\BinaryWriter.EncodingTests_Serial.cs" />
<Compile Include="BinaryWriter\BinaryWriter.WriteByteCharTests.cs" />
<Compile Include="BinaryWriter\BinaryWriter.WriteTests.cs" />
<Compile Include="BinaryWriter\BinaryWriterTests.cs" />
<Compile Include="MemoryStream\MemoryStreamTests.cs" />
<Compile Include="StreamReader\StreamReader.CtorTests.cs" />
<Compile Include="StreamReader\StreamReaderTests.cs" />
+ <Compile Include="StreamReader\StreamReaderTests_Serial.cs" />
<Compile Include="StreamWriter\StreamWriter.BaseStream.cs" />
<Compile Include="StreamWriter\StreamWriter.CloseTests.cs" />
<Compile Include="StreamWriter\StreamWriter.CtorTests.cs" />