diff options
author | Stephen Toub <stoub@microsoft.com> | 2017-04-26 20:36:51 +0300 |
---|---|---|
committer | Stephen Toub <stoub@microsoft.com> | 2017-04-26 20:36:51 +0300 |
commit | f815371d499a9ea8d11abfbbf9dd6b1523faec7f (patch) | |
tree | 72aed52b4bb4450e7e712219f78ed1ce4689eb5f /src | |
parent | d281f66a286e4d30882d5dc3a3902dce5a7b029f (diff) |
Add tests for FileStream.BeginEndRead/Write
Enable most of the Read/WriteAsync tests to work for Begin/EndRead/Write as well.
Diffstat (limited to 'src')
5 files changed, 234 insertions, 341 deletions
diff --git a/src/System.IO.FileSystem/tests/FileStream/BeginRead.cs b/src/System.IO.FileSystem/tests/FileStream/BeginRead.cs deleted file mode 100644 index b155e92b13..0000000000 --- a/src/System.IO.FileSystem/tests/FileStream/BeginRead.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.IO; -using Xunit; - -namespace System.IO.Tests -{ - public class FileStream_BeginRead : FileSystemTest - { - [Fact] - public void BeginReadThrowsForNullArray() - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - AssertExtensions.Throws<ArgumentNullException>("array", () => fs.BeginRead(null, 0, 0, null, null)); - } - } - - [Fact] - public void BeginReadThrowsForNegativeOffset() - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => fs.BeginRead(new byte[0], -1, 0, null, null)); - } - } - - [Fact] - public void BeginReadThrowsForNegativeNumBytes() - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - AssertExtensions.Throws<ArgumentOutOfRangeException>("numBytes", () => fs.BeginRead(new byte[0], 0, -1, null, null)); - } - } - - [Theory - InlineData(0, 0, 1) - InlineData(0, 1, 0) - InlineData(1, 0, 2) - InlineData(1, 1, 1) - ] - public void BeginReadThrowsForBadOffset(int arraySize, int offset, int numBytes) - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - Assert.Throws<ArgumentException>(() => fs.BeginRead(new byte[arraySize], offset, numBytes, null, null)); - } - } - - [Fact] - public void BeginReadThrowsForClosed() - { - FileStream fs; - using (fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - } - - Assert.Throws<ObjectDisposedException>(() => fs.BeginRead(new byte[0], 0, 0, null, null)); - } - - [Fact] - public void BeginReadThrowsForWriteOnly() - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - Assert.Throws<NotSupportedException>(() => fs.BeginRead(new byte[0], 0, 0, null, null)); - } - } - } -} diff --git a/src/System.IO.FileSystem/tests/FileStream/BeginWrite.cs b/src/System.IO.FileSystem/tests/FileStream/BeginWrite.cs deleted file mode 100644 index 55b8f092df..0000000000 --- a/src/System.IO.FileSystem/tests/FileStream/BeginWrite.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.IO; -using Xunit; - -namespace System.IO.Tests -{ - public class FileStream_BeginWrite : FileSystemTest - { - [Fact] - public void BeginWriteThrowsForNullArray() - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - AssertExtensions.Throws<ArgumentNullException>("array", () => fs.BeginWrite(null, 0, 0, null, null)); - } - } - - [Fact] - public void BeginWriteThrowsForNegativeOffset() - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => fs.BeginWrite(new byte[0], -1, 0, null, null)); - } - } - - [Fact] - public void BeginWriteThrowsForNegativeNumBytes() - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - AssertExtensions.Throws<ArgumentOutOfRangeException>("numBytes", () => fs.BeginWrite(new byte[0], 0, -1, null, null)); - } - } - - [Theory - InlineData(0, 0, 1) - InlineData(0, 1, 0) - InlineData(1, 0, 2) - InlineData(1, 1, 1) - ] - public void BeginWriteThrowsForBadOffset(int arraySize, int offset, int numBytes) - { - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - Assert.Throws<ArgumentException>(() => fs.BeginWrite(new byte[arraySize], offset, numBytes, null, null)); - } - } - - [Fact] - public void BeginWriteThrowsForClosed() - { - FileStream fs; - using (fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - } - - Assert.Throws<ObjectDisposedException>(() => fs.BeginWrite(new byte[0], 0, 0, null, null)); - } - - [Fact] - public void BeginWriteThrowsForReadOnly() - { - string testPath = GetTestFilePath(); - using (FileStream fs = new FileStream(testPath, FileMode.Create, FileAccess.Write)) - { - } - - using (FileStream fs = new FileStream(testPath, FileMode.Open, FileAccess.Read)) - { - Assert.Throws<NotSupportedException>(() => fs.BeginWrite(new byte[0], 0, 0, null, null)); - } - } - } -} diff --git a/src/System.IO.FileSystem/tests/FileStream/ReadAsync.cs b/src/System.IO.FileSystem/tests/FileStream/ReadAsync.cs index c9fad0ab5b..dd72d2a984 100644 --- a/src/System.IO.FileSystem/tests/FileStream/ReadAsync.cs +++ b/src/System.IO.FileSystem/tests/FileStream/ReadAsync.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -11,15 +9,22 @@ using Xunit; namespace System.IO.Tests { - public class FileStream_ReadAsync : FileSystemTest + public abstract class FileStream_AsyncReads : FileSystemTest { + protected virtual string BufferParamName => "buffer"; + protected virtual string OffsetParamName => "offset"; + protected virtual string CountParamName => "count"; + protected abstract Task<int> ReadAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken); + private Task<int> ReadAsync(FileStream stream, byte[] buffer, int offset, int count) => + ReadAsync(stream, buffer, offset, count, CancellationToken.None); + [Fact] public void NullBufferThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(null, 0, 1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, null, 0, 1))); } } @@ -28,12 +33,12 @@ namespace System.IO.Tests { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], -1, 1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, 1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(null, -1, 1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, 1))); } } @@ -42,16 +47,16 @@ namespace System.IO.Tests { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, -1))); // offset is checked before count - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], -1, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, -1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(null, -1, -1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, -1))); } } @@ -62,25 +67,25 @@ namespace System.IO.Tests { // offset out of bounds Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 1, 1))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 1, 1))); // offset out of bounds for 0 count ReadAsync Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 2, 0))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 2, 0))); // offset out of bounds even for 0 length buffer Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[0], 1, 0))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[0], 1, 0))); // combination offset and count out of bounds Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[2], 1, 2))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2))); // edges Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[0], int.MaxValue, 0))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[0], int.MaxValue, 0))); Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[0], int.MaxValue, int.MaxValue))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[0], int.MaxValue, int.MaxValue))); } } @@ -91,26 +96,26 @@ namespace System.IO.Tests { fs.Dispose(); Assert.Throws<ObjectDisposedException>(() => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 1))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 1))); // even for noop ReadAsync Assert.Throws<ObjectDisposedException>(() => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 0))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 0))); // out of bounds checking happens first Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[2], 1, 2))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2))); // count is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, -1))); // offset is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], -1, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, -1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(null, -1, -1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, -1))); } } @@ -120,67 +125,28 @@ namespace System.IO.Tests using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) { Assert.Throws<NotSupportedException>(() => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 1))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 1))); fs.Dispose(); // Disposed checking happens first Assert.Throws<ObjectDisposedException>(() => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 1))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, 1))); // out of bounds checking happens first Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[2], 1, 2))); - - // count is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, -1))); - - // offset is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], -1, -1))); - - // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(null, -1, -1))); - } - } - - [Fact] - public void CancelledTokenFastPath() - { - CancellationTokenSource cts = new CancellationTokenSource(); - cts.Cancel(); - CancellationToken cancelledToken = cts.Token; - - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) - { - FSAssert.IsCancelled(fs.ReadAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); - } - - using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) - { - // before write only check - FSAssert.IsCancelled(fs.ReadAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); - - fs.Dispose(); - // before disposed check - FSAssert.IsCancelled(fs.ReadAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); - - // out of bounds checking happens first - Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[2], 1, 2, cancelledToken))); + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2))); // count is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, -1, cancelledToken))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, -1))); // offset is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], -1, -1, cancelledToken))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, -1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.ReadAsync(null, -1, -1, cancelledToken))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, -1))); } } @@ -191,12 +157,12 @@ namespace System.IO.Tests { // note that these do not succeed synchronously even though they do nothing. - Assert.Equal(0, await fs.ReadAsync(new byte[0], 0, 0)); - Assert.Equal(0, await fs.ReadAsync(new byte[1], 0, 0)); + Assert.Equal(0, await ReadAsync(fs, new byte[0], 0, 0)); + Assert.Equal(0, await ReadAsync(fs, new byte[1], 0, 0)); // even though offset is out of bounds of buffer, this is still allowed // for the last element - Assert.Equal(0, await fs.ReadAsync(new byte[1], 1, 0)); - Assert.Equal(0, await fs.ReadAsync(new byte[2], 1, 0)); + Assert.Equal(0, await ReadAsync(fs, new byte[1], 1, 0)); + Assert.Equal(0, await ReadAsync(fs, new byte[2], 1, 0)); } } @@ -211,16 +177,16 @@ namespace System.IO.Tests TestBuffer.CopyTo(buffer, 0); // note that these do not succeed synchronously even though they do nothing. - Assert.Equal(0, await fs.ReadAsync(buffer, 0, 1)); + Assert.Equal(0, await ReadAsync(fs, buffer, 0, 1)); Assert.Equal(TestBuffer, buffer); - Assert.Equal(0, await fs.ReadAsync(buffer, 0, buffer.Length)); + Assert.Equal(0, await ReadAsync(fs, buffer, 0, buffer.Length)); Assert.Equal(TestBuffer, buffer); - Assert.Equal(0, await fs.ReadAsync(buffer, buffer.Length - 1, 1)); + Assert.Equal(0, await ReadAsync(fs, buffer, buffer.Length - 1, 1)); Assert.Equal(TestBuffer, buffer); - Assert.Equal(0, await fs.ReadAsync(buffer, buffer.Length / 2, buffer.Length - buffer.Length / 2)); + Assert.Equal(0, await ReadAsync(fs, buffer, buffer.Length / 2, buffer.Length - buffer.Length / 2)); Assert.Equal(TestBuffer, buffer); } } @@ -242,13 +208,13 @@ namespace System.IO.Tests byte[] buffer = new byte[TestBuffer.Length]; // prime the internal buffer - Assert.Equal(TestBuffer.Length, await fs.ReadAsync(buffer, 0, buffer.Length)); + Assert.Equal(TestBuffer.Length, await ReadAsync(fs, buffer, 0, buffer.Length)); Assert.Equal(TestBuffer, buffer); Array.Clear(buffer, 0, buffer.Length); // read should now complete synchronously since it is serviced by the read buffer filled in the first request - Assert.Equal(TestBuffer.Length, FSAssert.CompletesSynchronously(fs.ReadAsync(buffer, 0, buffer.Length))); + Assert.Equal(TestBuffer.Length, FSAssert.CompletesSynchronously(ReadAsync(fs, buffer, 0, buffer.Length))); Assert.Equal(TestBuffer, buffer); } } @@ -265,13 +231,13 @@ namespace System.IO.Tests using (FileStream fs = new FileStream(fileName, FileMode.Open)) { byte[] buffer = new byte[TestBuffer.Length]; - Assert.Equal(TestBuffer.Length, await fs.ReadAsync(buffer, 0, buffer.Length)); + Assert.Equal(TestBuffer.Length, await ReadAsync(fs, buffer, 0, buffer.Length)); Assert.Equal(TestBuffer, buffer); // ReadAsync with too large buffer at front of buffer fs.Position = 0; buffer = new byte[TestBuffer.Length * 2]; - Assert.Equal(TestBuffer.Length, await fs.ReadAsync(buffer, 0, buffer.Length)); + Assert.Equal(TestBuffer.Length, await ReadAsync(fs, buffer, 0, buffer.Length)); Assert.Equal(TestBuffer, buffer.Take(TestBuffer.Length)); // Remainder of buffer should be untouched. Assert.Equal(new byte[buffer.Length - TestBuffer.Length], buffer.Skip(TestBuffer.Length)); @@ -279,7 +245,7 @@ namespace System.IO.Tests // ReadAsync with too large buffer in middle of buffer fs.Position = 0; buffer = new byte[TestBuffer.Length * 2]; - Assert.Equal(TestBuffer.Length, await fs.ReadAsync(buffer, 2, buffer.Length - 2)); + Assert.Equal(TestBuffer.Length, await ReadAsync(fs, buffer, 2, buffer.Length - 2)); Assert.Equal(TestBuffer, buffer.Skip(2).Take(TestBuffer.Length)); // Remainder of buffer should be untouched. Assert.Equal(new byte[2], buffer.Take(2)); @@ -301,7 +267,7 @@ namespace System.IO.Tests { byte[] buffer = new byte[fs.Length]; CancellationTokenSource cts = new CancellationTokenSource(); - Task<int> readTask = fs.ReadAsync(buffer, 0, buffer.Length, cts.Token); + Task<int> readTask = ReadAsync(fs, buffer, 0, buffer.Length, cts.Token); cts.Cancel(); try { @@ -362,7 +328,7 @@ namespace System.IO.Tests else { // 90%: Async read - bytesRead = await stream.ReadAsync(buffer, 0, bytesToRead, tokenSource.Token); + bytesRead = await ReadAsync(stream, buffer, 0, bytesToRead, tokenSource.Token); } // 10%: Verify data (burns a lot of CPU time) @@ -392,4 +358,61 @@ namespace System.IO.Tests } } } + + public class FileStream_ReadAsync_AsyncReads : FileStream_AsyncReads + { + protected override Task<int> ReadAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + stream.ReadAsync(buffer, offset, count, cancellationToken); + + [Fact] + public void CancelledTokenFastPath() + { + var cts = new CancellationTokenSource(); + cts.Cancel(); + CancellationToken cancelledToken = cts.Token; + + using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) + { + FSAssert.IsCancelled(ReadAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); + } + + using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write)) + { + // before write only check + FSAssert.IsCancelled(ReadAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); + + fs.Dispose(); + // before disposed check + FSAssert.IsCancelled(ReadAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); + + // out of bounds checking happens first + Assert.Throws<ArgumentException>(null, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[2], 1, 2, cancelledToken))); + + // count is checked prior + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], 0, -1, cancelledToken))); + + // offset is checked prior + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, new byte[1], -1, -1, cancelledToken))); + + // buffer is checked first + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(ReadAsync(fs, null, -1, -1, cancelledToken))); + } + } + } + + public class FileStream_BeginEndRead_AsyncReads : FileStream_AsyncReads + { + protected override Task<int> ReadAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + Task.Factory.FromAsync( + (callback, state) => stream.BeginRead(buffer, offset, count, callback, state), + iar => stream.EndRead(iar), + null); + + protected override string BufferParamName => "array"; + protected override string CountParamName => "numBytes"; + } } diff --git a/src/System.IO.FileSystem/tests/FileStream/WriteAsync.cs b/src/System.IO.FileSystem/tests/FileStream/WriteAsync.cs index 067ed97238..fa1f45095d 100644 --- a/src/System.IO.FileSystem/tests/FileStream/WriteAsync.cs +++ b/src/System.IO.FileSystem/tests/FileStream/WriteAsync.cs @@ -10,15 +10,22 @@ using Xunit; namespace System.IO.Tests { - public class FileStream_WriteAsync : FileSystemTest + public abstract class FileStream_AsyncWrites : FileSystemTest { + protected virtual string BufferParamName => "buffer"; + protected virtual string OffsetParamName => "offset"; + protected virtual string CountParamName => "count"; + private Task WriteAsync(FileStream stream, byte[] buffer, int offset, int count) => + WriteAsync(stream, buffer, offset, count, CancellationToken.None); + protected abstract Task WriteAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken); + [Fact] public void NullBufferThrows() { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(null, 0, 1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, null, 0, 1))); } } @@ -27,12 +34,12 @@ namespace System.IO.Tests { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, 1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], -1, 1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, 1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, null, -1, 1))); } } @@ -41,16 +48,16 @@ namespace System.IO.Tests { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, -1))); // offset is checked before count - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], -1, -1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, -1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, null, -1, -1))); } } @@ -61,25 +68,25 @@ namespace System.IO.Tests { // offset out of bounds Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 1, 1))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 1, 1))); // offset out of bounds for 0 count WriteAsync Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 2, 0))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 2, 0))); // offset out of bounds even for 0 length buffer Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[0], 1, 0))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[0], 1, 0))); // combination offset and count out of bounds Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[2], 1, 2))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[2], 1, 2))); // edges Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[0], int.MaxValue, 0))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[0], int.MaxValue, 0))); Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[0], int.MaxValue, int.MaxValue))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[0], int.MaxValue, int.MaxValue))); } } @@ -90,26 +97,26 @@ namespace System.IO.Tests { fs.Dispose(); Assert.Throws<ObjectDisposedException>(() => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, 1))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, 1))); // even for noop WriteAsync Assert.Throws<ObjectDisposedException>(() => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, 0))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, 0))); // out of bounds checking happens first Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[2], 1, 2))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[2], 1, 2))); // count is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, -1))); // offset is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], -1, -1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, -1))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, null, -1, -1))); } } @@ -123,68 +130,28 @@ namespace System.IO.Tests using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { Assert.Throws<NotSupportedException>(() => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, 1))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, 1))); fs.Dispose(); // Disposed checking happens first Assert.Throws<ObjectDisposedException>(() => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, 1))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, 1))); // out of bounds checking happens first Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[2], 1, 2))); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[2], 1, 2))); // count is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, -1))); // offset is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, -1))); + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], -1, -1))); // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, -1))); - } - } - - [Fact] - public void CancelledTokenFastPath() - { - CancellationTokenSource cts = new CancellationTokenSource(); - cts.Cancel(); - CancellationToken cancelledToken = cts.Token; - - string fileName = GetTestFilePath(); - using (FileStream fs = new FileStream(fileName, FileMode.Create)) - { - FSAssert.IsCancelled(fs.WriteAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); - } - - using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) - { - // before read only check - FSAssert.IsCancelled(fs.WriteAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); - - fs.Dispose(); - // before disposed check - FSAssert.IsCancelled(fs.WriteAsync(new byte[1], 0, 1, cancelledToken), cancelledToken); - - // out of bounds checking happens first - Assert.Throws<ArgumentException>(null, () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[2], 1, 2, cancelledToken))); - - // count is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], 0, -1, cancelledToken))); - - // offset is checked prior - AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[1], -1, -1, cancelledToken))); - - // buffer is checked first - AssertExtensions.Throws<ArgumentNullException>("buffer", () => - FSAssert.CompletesSynchronously(fs.WriteAsync(null, -1, -1, cancelledToken))); + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, null, -1, -1))); } } @@ -195,12 +162,12 @@ namespace System.IO.Tests { // note that these do not succeed synchronously even though they do nothing. - await fs.WriteAsync(new byte[0], 0, 0); - await fs.WriteAsync(new byte[1], 0, 0); + await WriteAsync(fs, new byte[0], 0, 0); + await WriteAsync(fs, new byte[1], 0, 0); // even though offset is out of bounds of buffer, this is still allowed // for the last element - await fs.WriteAsync(new byte[1], 1, 0); - await fs.WriteAsync(new byte[2], 1, 0); + await WriteAsync(fs, new byte[1], 1, 0); + await WriteAsync(fs, new byte[2], 1, 0); Assert.Equal(0, fs.Length); Assert.Equal(0, fs.Position); } @@ -214,7 +181,7 @@ namespace System.IO.Tests GetTestFilePath(), FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete, TestBuffer.Length * 2, useAsync: true)) { - FSAssert.CompletesSynchronously(fs.WriteAsync(new byte[TestBuffer.Length], 0, TestBuffer.Length)); + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[TestBuffer.Length], 0, TestBuffer.Length)); } } @@ -223,7 +190,7 @@ namespace System.IO.Tests { using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create)) { - await fs.WriteAsync(TestBuffer, 0, TestBuffer.Length); + await WriteAsync(fs, TestBuffer, 0, TestBuffer.Length); Assert.Equal(TestBuffer.Length, fs.Length); Assert.Equal(TestBuffer.Length, fs.Position); @@ -242,7 +209,7 @@ namespace System.IO.Tests { byte[] buffer = new byte[writeSize]; CancellationTokenSource cts = new CancellationTokenSource(); - Task writeTask = fs.WriteAsync(buffer, 0, buffer.Length, cts.Token); + Task writeTask = WriteAsync(fs, buffer, 0, buffer.Length, cts.Token); cts.Cancel(); try { @@ -263,27 +230,27 @@ namespace System.IO.Tests using (FileStream fs = new FileStream(GetTestFilePath(), FileMode.Create, FileAccess.Write, FileShare.None, 3, useAsync: true)) { // Fill buffer; should trigger flush of full buffer, no additional I/O - await fs.WriteAsync(TestBuffer, 0, 3); + await WriteAsync(fs, TestBuffer, 0, 3); Assert.True(fs.Length == 3); // Add to next buffer - await fs.WriteAsync(TestBuffer, 0, 1); + await WriteAsync(fs, TestBuffer, 0, 1); Assert.True(fs.Length == 4); // Complete that buffer; should trigger flush of full buffer, no additional I/O - await fs.WriteAsync(TestBuffer, 0, 2); + await WriteAsync(fs, TestBuffer, 0, 2); Assert.True(fs.Length == 6); // Add to next buffer - await fs.WriteAsync(TestBuffer, 0, 2); + await WriteAsync(fs, TestBuffer, 0, 2); Assert.True(fs.Length == 8); // Overflow buffer with amount that could fit in a buffer; should trigger a flush, with additional I/O - await fs.WriteAsync(TestBuffer, 0, 2); + await WriteAsync(fs, TestBuffer, 0, 2); Assert.True(fs.Length == 10); // Overflow buffer with amount that couldn't fit in a buffer; shouldn't be anything to flush, just an additional I/O - await fs.WriteAsync(TestBuffer, 0, 4); + await WriteAsync(fs, TestBuffer, 0, 4); Assert.True(fs.Length == 14); } } @@ -352,7 +319,7 @@ namespace System.IO.Tests Task[] writes = new Task[numWrites]; for (int i = 0; i < numWrites; i++) { - writes[i] = fs.WriteAsync(expectedData, i * writeSize, writeSize, cancellationToken); + writes[i] = WriteAsync(fs, expectedData, i * writeSize, writeSize, cancellationToken); Assert.Null(writes[i].Exception); if (useAsync) { @@ -384,7 +351,7 @@ namespace System.IO.Tests Assert.Equal(TestBuffer[0], await ReadByteAsync(fs)); Assert.Equal(TestBuffer[1], await ReadByteAsync(fs)); Assert.Equal(TestBuffer[2], await ReadByteAsync(fs)); - await fs.WriteAsync(TestBuffer, 0, TestBuffer.Length); + await WriteAsync(fs, TestBuffer, 0, TestBuffer.Length); fs.Position = 0; Assert.Equal(TestBuffer[0], await ReadByteAsync(fs)); @@ -442,7 +409,7 @@ namespace System.IO.Tests else { // 90%: Async write - await stream.WriteAsync(dataToWrite, 0, bytesToWrite, tokenSource.Token); + await WriteAsync(stream, dataToWrite, 0, bytesToWrite, tokenSource.Token); } } catch (TaskCanceledException) @@ -454,4 +421,62 @@ namespace System.IO.Tests } while (DateTime.UtcNow - testStartTime <= testRunTime); } } + + public class FileStream_WriteAsync_AsyncWrites : FileStream_AsyncWrites + { + protected override Task WriteAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + stream.WriteAsync(buffer, offset, count, cancellationToken); + + [Fact] + public void CancelledTokenFastPath() + { + CancellationTokenSource cts = new CancellationTokenSource(); + cts.Cancel(); + CancellationToken cancelledToken = cts.Token; + + string fileName = GetTestFilePath(); + using (FileStream fs = new FileStream(fileName, FileMode.Create)) + { + FSAssert.IsCancelled(WriteAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); + } + + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) + { + // before read only check + FSAssert.IsCancelled(WriteAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); + + fs.Dispose(); + // before disposed check + FSAssert.IsCancelled(WriteAsync(fs, new byte[1], 0, 1, cancelledToken), cancelledToken); + + // out of bounds checking happens first + Assert.Throws<ArgumentException>(null, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[2], 1, 2, cancelledToken))); + + // count is checked prior + AssertExtensions.Throws<ArgumentOutOfRangeException>(CountParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], 0, -1, cancelledToken))); + + // offset is checked prior + AssertExtensions.Throws<ArgumentOutOfRangeException>(OffsetParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, new byte[1], -1, -1, cancelledToken))); + + // buffer is checked first + AssertExtensions.Throws<ArgumentNullException>(BufferParamName, () => + FSAssert.CompletesSynchronously(WriteAsync(fs, null, -1, -1, cancelledToken))); + } + } + } + + public class FileStream_BeginEndWrite_AsyncWrites : FileStream_AsyncWrites + { + protected override Task WriteAsync(FileStream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + Task.Factory.FromAsync( + (callback, state) => stream.BeginWrite(buffer, offset, count, callback, state), + iar => stream.EndWrite(iar), + null); + + protected override string BufferParamName => "array"; + protected override string CountParamName => "numBytes"; + } } diff --git a/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 7749fa5fbe..d265aaf3a2 100644 --- a/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -19,9 +19,7 @@ <Compile Include="FileStream\Handle.cs" /> <Compile Include="Directory\GetLogicalDrives.cs" /> <Compile Include="DirectoryInfo\Serialization.cs" /> - <Compile Include="FileStream\BeginRead.cs" /> <Compile Include="FileStream\EndRead.cs" /> - <Compile Include="FileStream\BeginWrite.cs" /> <Compile Include="FileStream\EndWrite.cs" /> <Compile Include="FileStream\LockUnlock.cs" /> <Compile Include="File\EncryptDecrypt.cs" /> |