Imported Upstream version 5.0.0.42

Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-04-10 11:41:01 +00:00
parent 1190d13a04
commit 6bdd276d05
19939 changed files with 3099680 additions and 93811 deletions

View File

@@ -0,0 +1,133 @@
// 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.Collections.Generic;
using System.IO;
using System.Text;
using Xunit;
namespace System.IO.Tests
{
public class BinaryReaderTests
{
protected virtual Stream CreateStream()
{
return new MemoryStream();
}
[Fact]
public void BinaryReader_DisposeTests()
{
// Disposing multiple times should not throw an exception
using (Stream memStream = CreateStream())
using (BinaryReader binaryReader = new BinaryReader(memStream))
{
binaryReader.Dispose();
binaryReader.Dispose();
binaryReader.Dispose();
}
}
[Fact]
public void BinaryReader_CloseTests()
{
// Closing multiple times should not throw an exception
using (Stream memStream = CreateStream())
using (BinaryReader binaryReader = new BinaryReader(memStream))
{
binaryReader.Close();
binaryReader.Close();
binaryReader.Close();
}
}
[Fact]
public void BinaryReader_DisposeTests_Negative()
{
using (Stream memStream = CreateStream())
{
BinaryReader binaryReader = new BinaryReader(memStream);
binaryReader.Dispose();
ValidateDisposedExceptions(binaryReader);
}
}
[Fact]
public void BinaryReader_CloseTests_Negative()
{
using (Stream memStream = CreateStream())
{
BinaryReader binaryReader = new BinaryReader(memStream);
binaryReader.Close();
ValidateDisposedExceptions(binaryReader);
}
}
private void ValidateDisposedExceptions(BinaryReader binaryReader)
{
byte[] byteBuffer = new byte[10];
char[] charBuffer = new char[10];
Assert.Throws<ObjectDisposedException>(() => binaryReader.PeekChar());
Assert.Throws<ObjectDisposedException>(() => binaryReader.Read());
Assert.Throws<ObjectDisposedException>(() => binaryReader.Read(byteBuffer, 0, 1));
Assert.Throws<ObjectDisposedException>(() => binaryReader.Read(charBuffer, 0, 1));
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadBoolean());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadByte());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadBytes(1));
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadChar());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadChars(1));
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadDecimal());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadDouble());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadInt16());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadInt32());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadInt64());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadSByte());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadSingle());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadString());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadUInt16());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadUInt32());
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadUInt64());
}
public class NegEncoding : UTF8Encoding
{
public override Decoder GetDecoder()
{
return new NegDecoder();
}
public class NegDecoder : Decoder
{
public override int GetCharCount(byte[] bytes, int index, int count)
{
return 1;
}
public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
return -10000000;
}
}
}
[Fact]
public void Read_InvalidEncoding()
{
using (var str = CreateStream())
{
byte[] memb = new byte[100];
new Random(345).NextBytes(memb);
str.Write(memb, 0, 100);
str.Position = 0;
using (var reader = new BinaryReader(str, new NegEncoding()))
{
Assert.Throws<ArgumentOutOfRangeException>("charsRemaining", () => reader.Read(new char[10], 0, 10));
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,181 @@
// 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 Xunit;
using System;
using System.IO;
using System.Text;
namespace System.IO.Tests
{
public class BinaryWriter_WriteTests
{
[Fact]
public void BinaryWriter_WriteBoolTest()
{
// [] Write a series of booleans to a stream
using(Stream mstr = CreateStream())
using(BinaryWriter dw2 = new BinaryWriter(mstr))
using(BinaryReader dr2 = new BinaryReader(mstr))
{
dw2.Write(false);
dw2.Write(false);
dw2.Write(true);
dw2.Write(false);
dw2.Write(true);
dw2.Write(5);
dw2.Write(0);
dw2.Flush();
mstr.Position = 0;
Assert.False(dr2.ReadBoolean()); //false
Assert.False(dr2.ReadBoolean()); //false
Assert.True(dr2.ReadBoolean()); //true
Assert.False(dr2.ReadBoolean()); //false
Assert.True(dr2.ReadBoolean()); //true
Assert.Equal(5, dr2.ReadInt32()); //5
Assert.Equal(0, dr2.ReadInt32()); //0
}
}
[Fact]
public void BinaryWriter_WriteSingleTest()
{
float[] sglArr = new float[] {
float.MinValue, float.MaxValue, float.Epsilon, float.PositiveInfinity, float.NegativeInfinity, new float(),
0, (float)(-1E20), (float)(-3.5E-20), (float)(1.4E-10), (float)10000.2, (float)2.3E30
};
WriteTest(sglArr, (bw, s) => bw.Write(s), (br) => br.ReadSingle());
}
[Fact]
public void BinaryWriter_WriteDecimalTest()
{
decimal[] decArr = new decimal[] {
decimal.One, decimal.Zero, decimal.MinusOne, decimal.MinValue, decimal.MaxValue,
new decimal(-1000.5), new decimal(-10.0E-40), new decimal(3.4E-40898), new decimal(3.4E-28),
new decimal(3.4E+28), new decimal(0.45), new decimal(5.55), new decimal(3.4899E23)
};
WriteTest(decArr, (bw, s) => bw.Write(s), (br) => br.ReadDecimal());
}
[Fact]
public void BinaryWriter_WriteDoubleTest()
{
double[] dblArr = new double[] {
double.NegativeInfinity, double.PositiveInfinity, double.Epsilon, double.MinValue, double.MaxValue,
-3E59, -1000.5, -1E-40, 3.4E-37, 0.45, 5.55, 3.4899E233
};
WriteTest(dblArr, (bw, s) => bw.Write(s), (br) => br.ReadDouble());
}
[Fact]
public void BinaryWriter_WriteInt16Test()
{
short[] i16Arr = new short[] { short.MinValue, short.MaxValue, 0, -10000, 10000, -50, 50 };
WriteTest(i16Arr, (bw, s) => bw.Write(s), (br) => br.ReadInt16());
}
[Fact]
public void BinaryWriter_WriteInt32Test()
{
int[] i32arr = new int[] { int.MinValue, int.MaxValue, 0, -10000, 10000, -50, 50 };
WriteTest(i32arr, (bw, s) => bw.Write(s), (br) => br.ReadInt32());
}
[Fact]
public void BinaryWriter_WriteInt64Test()
{
long[] i64arr = new long[] { long.MinValue, long.MaxValue, 0, -10000, 10000, -50, 50 };
WriteTest(i64arr, (bw, s) => bw.Write(s), (br) => br.ReadInt64());
}
[Fact]
public void BinaryWriter_WriteUInt16Test()
{
ushort[] ui16Arr = new ushort[] { ushort.MinValue, ushort.MaxValue, 0, 100, 1000, 10000, ushort.MaxValue - 100 };
WriteTest(ui16Arr, (bw, s) => bw.Write(s), (br) => br.ReadUInt16());
}
[Fact]
public void BinaryWriter_WriteUInt32Test()
{
uint[] ui32Arr = new uint[] { uint.MinValue, uint.MaxValue, 0, 100, 1000, 10000, uint.MaxValue - 100 };
WriteTest(ui32Arr, (bw, s) => bw.Write(s), (br) => br.ReadUInt32());
}
[Fact]
public void BinaryWriter_WriteUInt64Test()
{
ulong[] ui64Arr = new ulong[] { ulong.MinValue, ulong.MaxValue, 0, 100, 1000, 10000, ulong.MaxValue - 100 };
WriteTest(ui64Arr, (bw, s) => bw.Write(s), (br) => br.ReadUInt64());
}
[Fact]
public void BinaryWriter_WriteStringTest()
{
StringBuilder sb = new StringBuilder();
string str1;
for (int ii = 0; ii < 5; ii++)
sb.Append("abc");
str1 = sb.ToString();
string[] strArr = new string[] {
"ABC", "\t\t\n\n\n\0\r\r\v\v\t\0\rHello", "This is a normal string", "12345667789!@#$%^&&())_+_)@#",
"ABSDAFJPIRUETROPEWTGRUOGHJDOLJHLDHWEROTYIETYWsdifhsiudyoweurscnkjhdfusiyugjlskdjfoiwueriye", " ",
"\0\0\0\t\t\tHey\"\"", "\u0022\u0011", str1, string.Empty };
WriteTest(strArr, (bw, s) => bw.Write(s), (br) => br.ReadString());
}
[Fact]
public void BinaryWriter_WriteStringTest_Null()
{
using (Stream memStream = CreateStream())
using (BinaryWriter dw2 = new BinaryWriter(memStream))
{
Assert.Throws<ArgumentNullException>(() => dw2.Write((string)null));
}
}
protected virtual Stream CreateStream()
{
return new MemoryStream();
}
private void WriteTest<T>(T[] testElements, Action<BinaryWriter, T> write, Func<BinaryReader, T> read)
{
using (Stream memStream = CreateStream())
using (BinaryWriter writer = new BinaryWriter(memStream))
using (BinaryReader reader = new BinaryReader(memStream))
{
for (int i = 0; i < testElements.Length; i++)
{
write(writer, testElements[i]);
}
writer.Flush();
memStream.Position = 0;
for (int i = 0; i < testElements.Length; i++)
{
Assert.Equal(testElements[i], read(reader));
}
// We've reached the end of the stream. Check for expected EndOfStreamException
Assert.Throws<EndOfStreamException>(() => read(reader));
}
}
}
}

View File

@@ -0,0 +1,381 @@
// 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.Collections.Generic;
using System.IO;
using System.Text;
using Xunit;
namespace System.IO.Tests
{
public class BinaryWriterTests
{
protected virtual Stream CreateStream()
{
return new MemoryStream();
}
[Fact]
public void BinaryWriter_CtorAndWriteTests1()
{
// [] Smoke test to ensure that we can write with the constructed writer
using (Stream mstr = CreateStream())
using (BinaryWriter dw2 = new BinaryWriter(mstr))
using (BinaryReader dr2 = new BinaryReader(mstr))
{
dw2.Write(true);
dw2.Flush();
mstr.Position = 0;
Assert.True(dr2.ReadBoolean());
}
}
[Fact]
public void BinaryWriter_CtorAndWriteTests1_Negative()
{
// [] Should throw ArgumentNullException for null argument
Assert.Throws<ArgumentNullException>(() => new BinaryWriter(null));
// [] Can't construct a BinaryWriter on a readonly stream
using (Stream memStream = new MemoryStream(new byte[10], false))
{
Assert.Throws<ArgumentException>(() => new BinaryWriter(memStream));
}
// [] Can't construct a BinaryWriter with a closed stream
{
Stream memStream = CreateStream();
memStream.Dispose();
Assert.Throws<ArgumentException>(() => new BinaryWriter(memStream));
}
}
[Theory]
[MemberData(nameof(EncodingAndEncodingStrings))]
public void BinaryWriter_EncodingCtorAndWriteTests(Encoding encoding, string testString)
{
using (Stream memStream = CreateStream())
using (BinaryWriter writer = new BinaryWriter(memStream, encoding))
using (BinaryReader reader = new BinaryReader(memStream, encoding))
{
writer.Write(testString);
writer.Flush();
memStream.Position = 0;
Assert.Equal(testString, reader.ReadString());
}
}
public static IEnumerable<object[]> EncodingAndEncodingStrings
{
get
{
yield return new object[] { Encoding.UTF8, "This is UTF8\u00FF" };
yield return new object[] { Encoding.BigEndianUnicode, "This is BigEndianUnicode\u00FF" };
yield return new object[] { Encoding.Unicode, "This is Unicode\u00FF" };
}
}
[Fact]
public void BinaryWriter_EncodingCtorAndWriteTests_Negative()
{
// [] Check for ArgumentNullException on null stream
Assert.Throws<ArgumentNullException>(() => new BinaryReader((Stream)null, Encoding.UTF8));
// [] Check for ArgumentNullException on null encoding
Assert.Throws<ArgumentNullException>(() => new BinaryReader(CreateStream(), null));
}
[Fact]
public void BinaryWriter_SeekTests()
{
int[] iArrLargeValues = new int[] { 10000, 100000, int.MaxValue / 200, int.MaxValue / 1000, short.MaxValue, int.MaxValue, int.MaxValue - 1, int.MaxValue / 2, int.MaxValue / 10, int.MaxValue / 100 };
BinaryWriter dw2 = null;
MemoryStream mstr = null;
byte[] bArr = null;
StringBuilder sb = new StringBuilder();
Int64 lReturn = 0;
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("Hello, this is my string".ToCharArray());
for (int iLoop = 0; iLoop < iArrLargeValues.Length; iLoop++)
{
lReturn = dw2.Seek(iArrLargeValues[iLoop], SeekOrigin.Begin);
Assert.Equal(iArrLargeValues[iLoop], lReturn);
}
dw2.Dispose();
mstr.Dispose();
// [] Seek from start of stream
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("0123456789".ToCharArray());
lReturn = dw2.Seek(0, SeekOrigin.Begin);
Assert.Equal(0, lReturn);
dw2.Write("lki".ToCharArray());
dw2.Flush();
bArr = mstr.ToArray();
sb = new StringBuilder();
for (int i = 0; i < bArr.Length; i++)
sb.Append((char)bArr[i]);
Assert.Equal("lki3456789", sb.ToString());
dw2.Dispose();
mstr.Dispose();
// [] Seek into stream from start
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("0123456789".ToCharArray());
lReturn = dw2.Seek(3, SeekOrigin.Begin);
Assert.Equal(3, lReturn);
dw2.Write("lk".ToCharArray());
dw2.Flush();
bArr = mstr.ToArray();
sb = new StringBuilder();
for (int i = 0; i < bArr.Length; i++)
sb.Append((char)bArr[i]);
Assert.Equal("012lk56789", sb.ToString());
dw2.Dispose();
mstr.Dispose();
// [] Seek from end of stream
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("0123456789".ToCharArray());
lReturn = dw2.Seek(-3, SeekOrigin.End);
Assert.Equal(7, lReturn);
dw2.Write("ll".ToCharArray());
dw2.Flush();
bArr = mstr.ToArray();
sb = new StringBuilder();
for (int i = 0; i < bArr.Length; i++)
sb.Append((char)bArr[i]);
Assert.Equal("0123456ll9", sb.ToString());
dw2.Dispose();
mstr.Dispose();
// [] Seeking from current position
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("0123456789".ToCharArray());
mstr.Position = 2;
lReturn = dw2.Seek(2, SeekOrigin.Current);
Assert.Equal(4, lReturn);
dw2.Write("ll".ToCharArray());
dw2.Flush();
bArr = mstr.ToArray();
sb = new StringBuilder();
for (int i = 0; i < bArr.Length; i++)
sb.Append((char)bArr[i]);
Assert.Equal("0123ll6789", sb.ToString());
dw2.Dispose();
mstr.Dispose();
// [] Seeking past the end from middle
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("0123456789".ToCharArray());
lReturn = dw2.Seek(4, SeekOrigin.End); //This wont throw any exception now.
Assert.Equal(14, mstr.Position);
dw2.Dispose();
mstr.Dispose();
// [] Seek past the end from beginning
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("0123456789".ToCharArray());
lReturn = dw2.Seek(11, SeekOrigin.Begin); //This wont throw any exception now.
Assert.Equal(11, mstr.Position);
dw2.Dispose();
mstr.Dispose();
// [] Seek to the end
mstr = new MemoryStream();
dw2 = new BinaryWriter(mstr);
dw2.Write("0123456789".ToCharArray());
lReturn = dw2.Seek(10, SeekOrigin.Begin);
Assert.Equal(10, lReturn);
dw2.Write("ll".ToCharArray());
bArr = mstr.ToArray();
sb = new StringBuilder();
for (int i = 0; i < bArr.Length; i++)
sb.Append((char)bArr[i]);
Assert.Equal("0123456789ll", sb.ToString());
dw2.Dispose();
mstr.Dispose();
}
[Theory]
[InlineData(-1)]
[InlineData(-2)]
[InlineData(-10000)]
[InlineData(int.MinValue)]
public void BinaryWriter_SeekTests_NegativeOffset(int invalidValue)
{
// [] IOException if offset is negative
using (Stream memStream = CreateStream())
using (BinaryWriter writer = new BinaryWriter(memStream))
{
writer.Write("Hello, this is my string".ToCharArray());
Assert.Throws<IOException>(() => writer.Seek(invalidValue, SeekOrigin.Begin));
}
}
[Fact]
public void BinaryWriter_SeekTests_InvalidSeekOrigin()
{
// [] ArgumentException for invalid seekOrigin
using (Stream memStream = CreateStream())
using (BinaryWriter writer = new BinaryWriter(memStream))
{
writer.Write("012345789".ToCharArray());
Assert.Throws<ArgumentException>(() =>
{
writer.Seek(3, ~SeekOrigin.Begin);
});
}
}
[Fact]
public void BinaryWriter_BaseStreamTests()
{
// [] Get the base stream for MemoryStream
using (Stream ms2 = CreateStream())
using (BinaryWriter sr2 = new BinaryWriter(ms2))
{
Assert.Same(ms2, sr2.BaseStream);
}
}
[Fact]
public virtual void BinaryWriter_FlushTests()
{
// [] Check that flush updates the underlying stream
using (Stream memstr2 = CreateStream())
using (BinaryWriter bw2 = new BinaryWriter(memstr2))
{
string str = "HelloWorld";
int expectedLength = str.Length + 1; // 1 for 7-bit encoded length
bw2.Write(str);
Assert.Equal(expectedLength, memstr2.Length);
bw2.Flush();
Assert.Equal(expectedLength, memstr2.Length);
}
// [] Flushing a closed writer may throw an exception depending on the underlying stream
using (Stream memstr2 = CreateStream())
{
BinaryWriter bw2 = new BinaryWriter(memstr2);
bw2.Dispose();
bw2.Flush();
}
}
[Fact]
public void BinaryWriter_DisposeTests()
{
// Disposing multiple times should not throw an exception
using (Stream memStream = CreateStream())
using (BinaryWriter binaryWriter = new BinaryWriter(memStream))
{
binaryWriter.Dispose();
binaryWriter.Dispose();
binaryWriter.Dispose();
}
}
#if netstandard17
[Fact]
public void BinaryWriter_CloseTests()
{
// Closing multiple times should not throw an exception
using (Stream memStream = CreateStream())
using (BinaryWriter binaryWriter = new BinaryWriter(memStream))
{
binaryWriter.Close();
binaryWriter.Close();
binaryWriter.Close();
}
}
#endif //netstandard17
[Fact]
public void BinaryWriter_DisposeTests_Negative()
{
using (Stream memStream = CreateStream())
{
BinaryWriter binaryWriter = new BinaryWriter(memStream);
binaryWriter.Dispose();
ValidateDisposedExceptions(binaryWriter);
}
}
#if netstandard17
[Fact]
public void BinaryWriter_CloseTests_Negative()
{
using (Stream memStream = CreateStream())
{
BinaryWriter binaryWriter = new BinaryWriter(memStream);
binaryWriter.Close();
ValidateDisposedExceptions(binaryWriter);
}
}
#endif //netstandard17
private void ValidateDisposedExceptions(BinaryWriter binaryWriter)
{
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Seek(1, SeekOrigin.Begin));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write(new byte[2], 0, 2));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write(new char[2], 0, 2));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write(true));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((byte)4));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write(new byte[] { 1, 2 }));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write('a'));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write(new char[] { 'a', 'b' }));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write(5.3));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((short)3));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write(33));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((Int64)42));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((sbyte)4));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write("Hello There"));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((float)4.3));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((UInt16)3));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((uint)4));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write((ulong)5));
Assert.Throws<ObjectDisposedException>(() => binaryWriter.Write("Bah"));
}
}
}

View File

@@ -0,0 +1,77 @@
// 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.Diagnostics;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public class BufferedStreamFlushTests
{
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task ShouldNotFlushUnderlyingStreamIfReadOnly(bool underlyingCanSeek)
{
var underlying = new DelegateStream(
canReadFunc: () => true,
canWriteFunc: () => false,
canSeekFunc: () => underlyingCanSeek,
readFunc: (_, __, ___) => 123,
writeFunc: (_, __, ___) =>
{
throw new NotSupportedException();
},
seekFunc: (_, __) => 123L
);
var wrapper = new CallTrackingStream(underlying);
var buffered = new BufferedStream(wrapper);
buffered.ReadByte();
buffered.Flush();
Assert.Equal(0, wrapper.TimesCalled(nameof(wrapper.Flush)));
await buffered.FlushAsync();
Assert.Equal(0, wrapper.TimesCalled(nameof(wrapper.FlushAsync)));
}
[Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(false, false)]
public async Task ShouldAlwaysFlushUnderlyingStreamIfWritable(bool underlyingCanRead, bool underlyingCanSeek)
{
var underlying = new DelegateStream(
canReadFunc: () => underlyingCanRead,
canWriteFunc: () => true,
canSeekFunc: () => underlyingCanSeek,
readFunc: (_, __, ___) => 123,
writeFunc: (_, __, ___) => { },
seekFunc: (_, __) => 123L
);
var wrapper = new CallTrackingStream(underlying);
var buffered = new BufferedStream(wrapper);
buffered.Flush();
Assert.Equal(1, wrapper.TimesCalled(nameof(wrapper.Flush)));
await buffered.FlushAsync();
Assert.Equal(1, wrapper.TimesCalled(nameof(wrapper.FlushAsync)));
buffered.WriteByte(0);
buffered.Flush();
Assert.Equal(2, wrapper.TimesCalled(nameof(wrapper.Flush)));
await buffered.FlushAsync();
Assert.Equal(2, wrapper.TimesCalled(nameof(wrapper.FlushAsync)));
}
}
}

View File

@@ -0,0 +1,154 @@
// 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.Threading;
using Xunit;
namespace System.IO.Tests
{
public class BufferedStream_InvalidParameters
{
[Fact]
public static void NullConstructor_Throws_ArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => new BufferedStream(null));
}
[Fact]
public static void NegativeBufferSize_Throws_ArgumentOutOfRangeException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => new BufferedStream(new MemoryStream(), -1));
}
[Fact]
public static void ZeroBufferSize_Throws_ArgumentNullException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => new BufferedStream(new MemoryStream(), 0));
}
[Fact]
public static void UnderlyingStreamDisposed_Throws_ObjectDisposedException()
{
MemoryStream disposedStream = new MemoryStream();
disposedStream.Dispose();
Assert.Throws<ObjectDisposedException>(() => new BufferedStream(disposedStream));
}
[Fact]
public static void SetPositionToNegativeValue_Throws_ArgumentOutOfRangeException()
{
using (BufferedStream stream = new BufferedStream(new MemoryStream()))
{
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Position = -1);
}
}
[Fact]
public static void Read_Arguments()
{
using (BufferedStream stream = new BufferedStream(new MemoryStream()))
{
byte[] array = new byte[10];
Assert.Throws<ArgumentNullException>("array", () => stream.Read(null, 1, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Read(array, -1, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Read(array, 1, -1));
Assert.Throws<ArgumentException>(() => stream.Read(array, 9, 2));
}
}
[Fact]
public static void Write_Arguments()
{
using (BufferedStream stream = new BufferedStream(new MemoryStream()))
{
byte[] array = new byte[10];
Assert.Throws<ArgumentNullException>("array", () => stream.Write(null, 1, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(array, -1, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => stream.Write(array, 1, -1));
Assert.Throws<ArgumentException>(() => stream.Write(array, 9, 2));
}
}
[Fact]
public static void SetLength_NegativeValue()
{
using (MemoryStream underlying = new MemoryStream())
using (BufferedStream stream = new BufferedStream(underlying))
{
Assert.Throws<ArgumentOutOfRangeException>(() => stream.SetLength(-1));
stream.SetLength(1);
Assert.Equal(1, underlying.Length);
Assert.Equal(1, stream.Length);
}
}
[Fact]
public static void ReadOnUnreadableStream_Throws_NotSupportedException()
{
using (WrappedMemoryStream underlying = new WrappedMemoryStream(false, true, true))
using (BufferedStream stream = new BufferedStream(underlying))
{
Assert.Throws<NotSupportedException>(() => stream.Read(new byte[] { 1 }, 0, 1));
}
}
[Fact]
public static void WriteOnUnwritableStream_Throws_NotSupportedException()
{
using (WrappedMemoryStream underlying = new WrappedMemoryStream(true, false, true))
using (BufferedStream stream = new BufferedStream(underlying))
{
Assert.Throws<NotSupportedException>(() => stream.Write(new byte[] { 1 }, 0, 1));
}
}
[Fact]
public static void SeekOnUnseekableStream_Throws_NotSupportedException()
{
using (WrappedMemoryStream underlying = new WrappedMemoryStream(true, true, false))
using (BufferedStream stream = new BufferedStream(underlying))
{
Assert.Throws<NotSupportedException>(() => stream.Seek(0, new SeekOrigin()));
}
}
[Fact]
public void CopyToAsync_InvalidArguments_Throws()
{
using (var s = new BufferedStream(new MemoryStream()))
{
// Null destination
Assert.Throws<ArgumentNullException>("destination", () => { s.CopyToAsync(null); });
// Buffer size out-of-range
Assert.Throws<ArgumentOutOfRangeException>("bufferSize", () => { s.CopyToAsync(new MemoryStream(), 0); });
Assert.Throws<ArgumentOutOfRangeException>("bufferSize", () => { s.CopyToAsync(new MemoryStream(), -1, CancellationToken.None); });
// Copying to non-writable stream
Assert.Throws<NotSupportedException>(() => { s.CopyToAsync(new WrappedMemoryStream(canRead: true, canWrite: false, canSeek: true)); });
// Copying to a non-writable and non-readable stream
Assert.Throws<ObjectDisposedException>(() => { s.CopyToAsync(new WrappedMemoryStream(canRead: false, canWrite: false, canSeek: false)); });
// Copying after disposing the buffer stream
s.Dispose();
Assert.Throws<ObjectDisposedException>(() => { s.CopyToAsync(new MemoryStream()); });
}
// Copying after disposing the underlying stream
using (var ms = new MemoryStream())
using (var s = new BufferedStream(ms))
{
ms.Dispose();
Assert.Throws<ObjectDisposedException>(() => { s.CopyToAsync(new MemoryStream()); });
}
// Copying from a non-readable source
using (var s = new BufferedStream(new WrappedMemoryStream(canRead: false, canWrite: true, canSeek: true)))
{
Assert.Throws<NotSupportedException>(() => { s.CopyToAsync(new MemoryStream()); });
}
}
}
}

View File

@@ -0,0 +1,281 @@
// 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.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public class BufferedStream_StreamAsync : StreamAsync
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
[Fact]
public async Task ConcurrentOperationsAreSerialized()
{
byte[] data = Enumerable.Range(0, 1000).Select(i => (byte)i).ToArray();
var mcaos = new ManuallyReleaseAsyncOperationsStream();
var stream = new BufferedStream(mcaos, 1);
var tasks = new Task[4];
for (int i = 0; i < 4; i++)
{
tasks[i] = stream.WriteAsync(data, 250 * i, 250);
}
Assert.False(tasks.All(t => t.IsCompleted));
mcaos.Release();
await Task.WhenAll(tasks);
stream.Position = 0;
for (int i = 0; i < tasks.Length; i++)
{
Assert.Equal(i, stream.ReadByte());
}
}
[Fact]
public void UnderlyingStreamThrowsExceptions()
{
var stream = new BufferedStream(new ThrowsExceptionFromAsyncOperationsStream());
Assert.Equal(TaskStatus.Faulted, stream.ReadAsync(new byte[1], 0, 1).Status);
Assert.Equal(TaskStatus.Faulted, stream.WriteAsync(new byte[10000], 0, 10000).Status);
stream.WriteByte(1);
Assert.Equal(TaskStatus.Faulted, stream.FlushAsync().Status);
}
[Fact]
public async Task CopyToAsyncTest_RequiresAsyncFlushingOfWrites()
{
byte[] data = Enumerable.Range(0, 1000).Select(i => (byte)(i % 256)).ToArray();
var manualReleaseStream = new ManuallyReleaseAsyncOperationsStream();
var src = new BufferedStream(manualReleaseStream);
src.Write(data, 0, data.Length);
src.Position = 0;
var dst = new MemoryStream();
data[0] = 42;
src.WriteByte(42);
dst.WriteByte(42);
Task copyTask = src.CopyToAsync(dst);
manualReleaseStream.Release();
await copyTask;
Assert.Equal(data, dst.ToArray());
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task CopyToAsyncTest_ReadBeforeCopy_CopiesAllData(bool wrappedStreamCanSeek)
{
byte[] data = Enumerable.Range(0, 1000).Select(i => (byte)(i % 256)).ToArray();
var wrapped = new ManuallyReleaseAsyncOperationsStream();
wrapped.Release();
wrapped.Write(data, 0, data.Length);
wrapped.Position = 0;
wrapped.SetCanSeek(wrappedStreamCanSeek);
var src = new BufferedStream(wrapped, 100);
src.ReadByte();
var dst = new MemoryStream();
await src.CopyToAsync(dst);
var expected = new byte[data.Length - 1];
Array.Copy(data, 1, expected, 0, expected.Length);
Assert.Equal(expected, dst.ToArray());
}
}
public class BufferedStream_StreamMethods : StreamMethods
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
protected override Stream CreateStream(int bufferSize)
{
return new BufferedStream(new MemoryStream(), bufferSize);
}
}
public class BufferedStream_TestLeaveOpen : TestLeaveOpen
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
}
public class StreamWriterWithBufferedStream_CloseTests : CloseTests
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
}
public class StreamWriterWithBufferedStream_FlushTests : FlushTests
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
[Fact]
public void WriteAfterRead_NonSeekableStream_Throws()
{
var wrapped = new WrappedMemoryStream(canRead: true, canWrite: true, canSeek: false, data: new byte[] { 1, 2, 3, 4, 5 });
var s = new BufferedStream(wrapped);
s.Read(new byte[3], 0, 3);
Assert.Throws<NotSupportedException>(() => s.Write(new byte[10], 0, 10));
}
}
public class StreamWriterWithBufferedStream_WriteTests : WriteTests
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
}
public class StreamReaderWithBufferedStream_Tests : StreamReaderTests
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
protected override Stream GetSmallStream()
{
byte[] testData = new byte[] { 72, 69, 76, 76, 79 };
return new BufferedStream(new MemoryStream(testData));
}
protected override Stream GetLargeStream()
{
byte[] testData = new byte[] { 72, 69, 76, 76, 79 };
List<byte> data = new List<byte>();
for (int i = 0; i < 1000; i++)
{
data.AddRange(testData);
}
return new BufferedStream(new MemoryStream(data.ToArray()));
}
}
public class BinaryWriterWithBufferedStream_Tests : BinaryWriterTests
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
[Fact]
public override void BinaryWriter_FlushTests()
{
// [] Check that flush updates the underlying stream
using (Stream memstr2 = CreateStream())
using (BinaryWriter bw2 = new BinaryWriter(memstr2))
{
string str = "HelloWorld";
int expectedLength = str.Length + 1; // 1 for 7-bit encoded length
bw2.Write(str);
Assert.Equal(expectedLength, memstr2.Length);
bw2.Flush();
Assert.Equal(expectedLength, memstr2.Length);
}
// [] Flushing a closed writer may throw an exception depending on the underlying stream
using (Stream memstr2 = CreateStream())
{
BinaryWriter bw2 = new BinaryWriter(memstr2);
bw2.Dispose();
Assert.Throws<ObjectDisposedException>(() => bw2.Flush());
}
}
}
public class BinaryWriterWithBufferedStream_WriteByteCharTests : BinaryWriter_WriteByteCharTests
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
}
public class BinaryWriterWithBufferedStream_WriteTests : BinaryWriter_WriteTests
{
protected override Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
}
internal sealed class ManuallyReleaseAsyncOperationsStream : MemoryStream
{
private readonly TaskCompletionSource<bool> _tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
private bool _canSeek = true;
public override bool CanSeek => _canSeek;
public void SetCanSeek(bool canSeek) => _canSeek = canSeek;
public void Release() { _tcs.SetResult(true); }
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
await _tcs.Task;
return await base.ReadAsync(buffer, offset, count, cancellationToken);
}
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
await _tcs.Task;
await base.WriteAsync(buffer, offset, count, cancellationToken);
}
public override async Task FlushAsync(CancellationToken cancellationToken)
{
await _tcs.Task;
await base.FlushAsync(cancellationToken);
}
}
internal sealed class ThrowsExceptionFromAsyncOperationsStream : MemoryStream
{
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
throw new InvalidOperationException("Exception from ReadAsync");
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
throw new InvalidOperationException("Exception from WriteAsync");
}
public override Task FlushAsync(CancellationToken cancellationToken)
{
throw new InvalidOperationException("Exception from FlushAsync");
}
}
}

View File

@@ -0,0 +1,27 @@
// 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.IO;
using Xunit;
namespace System.IO.Tests
{
public partial class BufferedStreamTests
{
[Fact]
public void UnderlyingStream()
{
var underlyingStream = new MemoryStream();
var bufferedStream = new BufferedStream(underlyingStream);
Assert.Same(underlyingStream, bufferedStream.UnderlyingStream);
}
[Fact]
public void BufferSize()
{
var bufferedStream = new BufferedStream(new MemoryStream(), 1234);
Assert.Equal(1234, bufferedStream.BufferSize);
}
}
}

View File

@@ -0,0 +1,40 @@
// 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.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public class BufferedStream_NS17
{
protected Stream CreateStream()
{
return new BufferedStream(new MemoryStream());
}
public void EndCallback(IAsyncResult ar)
{ }
[Fact]
public void BeginEndReadTest()
{
Stream stream = CreateStream();
IAsyncResult result = stream.BeginRead(new byte[1], 0, 1, new AsyncCallback(EndCallback), new object());
stream.EndRead(result);
}
[Fact]
public void BeginEndWriteTest()
{
Stream stream = CreateStream();
IAsyncResult result = stream.BeginWrite(new byte[1], 0, 1, new AsyncCallback(EndCallback), new object());
stream.EndWrite(result);
}
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netstandard1.5;
netcoreapp;
netstandard;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,176 @@
// 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.Text;
using System.CodeDom.Compiler;
using Xunit;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Globalization;
namespace System.CodeDom.Tests
{
public class IndentedTextWriterTests
{
[Fact]
public static void Ctor_ExpectedDefaults()
{
var sb = new StringBuilder();
var sw = new StringWriter(sb);
var itw = new IndentedTextWriter(sw);
Assert.IsType<UnicodeEncoding>(itw.Encoding);
Assert.Equal(0, itw.Indent);
Assert.Same(sw, itw.InnerWriter);
Assert.Equal(sw.NewLine, itw.NewLine);
Assert.Equal(new string(' ', 4), IndentedTextWriter.DefaultTabString);
}
[Theory]
[InlineData(42)]
[InlineData(4)]
[InlineData(-1)]
[InlineData(-4)]
[InlineData(0)]
[InlineData(8)]
public static void Indent_RoundtripsAndAffectsOutput(int indent)
{
const string TabString = "\t\t";
var sb = new StringBuilder();
var sw = new StringWriter(sb);
var itw = new IndentedTextWriter(sw, TabString);
itw.Indent = indent;
Assert.Equal(indent >= 0 ? indent : 0, itw.Indent);
itw.WriteLine("first");
itw.WriteLine("second");
itw.WriteLine("third");
string expectedTab = string.Concat(Enumerable.Repeat(TabString, itw.Indent));
Assert.Equal(
"first" + Environment.NewLine +
expectedTab + "second" + Environment.NewLine +
expectedTab + "third" + Environment.NewLine,
sb.ToString());
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("space")]
[InlineData(" ")]
public static void TabString_UsesProvidedString(string tabString)
{
var sb = new StringBuilder();
var sw = new StringWriter(sb);
using (var itw = tabString == null ? new IndentedTextWriter(sw) : new IndentedTextWriter(sw, tabString))
{
itw.Indent = 1;
if (tabString == null)
{
tabString = IndentedTextWriter.DefaultTabString;
}
itw.WriteLine();
itw.WriteLine("Should be indented");
itw.Flush();
Assert.Equal(itw.NewLine + tabString + "Should be indented" + itw.NewLine, sb.ToString());
itw.Close();
}
}
[Theory]
[InlineData("\r\n")]
[InlineData("\n")]
[InlineData("newline")]
public static async Task Writes_ProducesExpectedOutput(string newline)
{
var sb = new StringBuilder();
var sw = new StringWriter(sb, CultureInfo.InvariantCulture);
var itw = new IndentedTextWriter(sw, "t");
itw.Indent = 1;
itw.NewLine = newline;
itw.WriteLine();
itw.Write(true);
itw.Write('a');
itw.Write(new char[] { 'b', 'c' });
itw.Write(new char[] { 'd', 'e' }, 0, 2);
itw.Write(4m);
itw.Write(5.6);
itw.Write(6.7f);
itw.Write(8);
itw.Write(9L);
itw.Write((object)10);
itw.Write("11");
itw.Write(12u);
itw.Write(13uL);
itw.Write("{0}", 14);
itw.Write("{0} {1}", 15, 16);
itw.Write("{0} {1} {2}", 15, 16, 17);
itw.Write("{0} {1} {2} {3}", 15, 16, 17, 18);
itw.WriteLine(true);
itw.WriteLine('a');
itw.WriteLine(new char[] { 'b', 'c' });
itw.WriteLine(new char[] { 'd', 'e' }, 0, 2);
itw.WriteLine(4m);
itw.WriteLine(5.6);
itw.WriteLine(6.7f);
itw.WriteLine(8);
itw.WriteLine(9L);
itw.WriteLine((object)10);
itw.WriteLine("11");
itw.WriteLine(12u);
itw.WriteLine(13uL);
itw.WriteLine("{0}", 14);
itw.WriteLine("{0} {1}", 15, 16);
itw.WriteLine("{0} {1} {2}", 15, 16, 17);
itw.WriteLine("{0} {1} {2} {3}", 15, 16, 17, 18);
await itw.WriteAsync('a');
await itw.WriteAsync(new char[] { 'b', 'c' });
await itw.WriteAsync(new char[] { 'd', 'e' }, 0, 2);
await itw.WriteAsync("1");
await itw.WriteLineAsync('a');
await itw.WriteLineAsync(new char[] { 'b', 'c' });
await itw.WriteLineAsync(new char[] { 'd', 'e' }, 0, 2);
await itw.WriteLineAsync("1");
itw.WriteLineNoTabs("notabs");
Assert.Equal(
"" + newline +
"tTrueabcde45.66.789101112131415 1615 16 1715 16 17 18True" + newline +
"ta" + newline +
"tbc" + newline +
"tde" + newline +
"t4" + newline +
"t5.6" + newline +
"t6.7" + newline +
"t8" + newline +
"t9" + newline +
"t10" + newline +
"t11" + newline +
"t12" + newline +
"t13" + newline +
"t14" + newline +
"t15 16" + newline +
"t15 16 17" + newline +
"t15 16 17 18" + newline +
"tabcde1a" + newline +
"tbc" + newline +
"tde" + newline +
"t1" + newline +
"notabs" + newline,
sb.ToString());
}
}
}

View File

@@ -0,0 +1,39 @@
// 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 Xunit;
namespace System.IO.Tests
{
public static class InvalidDataExceptionTests
{
[Fact]
public static void DefaultConstructor()
{
InvalidDataException ide = new InvalidDataException();
Assert.NotNull(ide.Message);
}
[Fact]
public static void MessageConstructor()
{
string message = "MessageConstructor";
InvalidDataException ide = new InvalidDataException(message);
Assert.Equal(message, ide.Message);
}
[Fact]
public static void MessageInnerExceptionConstructor()
{
string message = "MessageConstructor";
Exception innerException = new Exception();
InvalidDataException ide = new InvalidDataException(message, innerException);
Assert.Equal(message, ide.Message);
Assert.Same(innerException, ide.InnerException);
}
}
}

View File

@@ -0,0 +1,41 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class MemoryStream_ConstructorTests
{
[Theory]
[InlineData(10, -1, int.MaxValue)]
[InlineData(10, 6, -1)]
public static void MemoryStream_Ctor_NegativeIndeces(int arraySize, int index, int count)
{
Assert.Throws<ArgumentOutOfRangeException>(() => new MemoryStream(new byte[arraySize], index, count));
}
[Theory]
[InlineData(1, 2, 1)]
[InlineData(7, 8, 2)]
public static void MemoryStream_Ctor_OutOfRangeIndeces(int arraySize, int index, int count)
{
Assert.Throws<ArgumentException>(() => new MemoryStream(new byte[arraySize], index, count));
}
[Fact]
public static void MemoryStream_Ctor_NullArray()
{
Assert.Throws<ArgumentNullException>(() => new MemoryStream(null, 5, 2));
}
[Fact]
public static void MemoryStream_Ctor_InvalidCapacities()
{
Assert.Throws<ArgumentOutOfRangeException>(() => new MemoryStream(int.MinValue));
Assert.Throws<ArgumentOutOfRangeException>(() => new MemoryStream(-1));
Assert.Throws<OutOfMemoryException>(() => new MemoryStream(int.MaxValue));
}
}
}

View File

@@ -0,0 +1,50 @@
// 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 Xunit;
namespace System.IO.Tests
{
public class MemoryStream_GetBufferTests
{
[Fact]
public void MemoryStream_GetBuffer_Length()
{
MemoryStream ms = new MemoryStream();
byte[] buffer = ms.GetBuffer();
Assert.Equal(0, buffer.Length);
}
[Fact]
public void MemoryStream_GetBuffer_NonExposable()
{
MemoryStream ms = new MemoryStream(new byte[100]);
Assert.Throws<UnauthorizedAccessException>(() => ms.GetBuffer());
}
[Fact]
public void MemoryStream_GetBuffer_Exposable()
{
MemoryStream ms = new MemoryStream(new byte[500], 0, 100, true, true);
byte[] buffer = ms.GetBuffer();
Assert.Equal(500, buffer.Length);
}
[Fact]
public void MemoryStream_GetBuffer()
{
byte[] testdata = new byte[100];
new Random(45135).NextBytes(testdata);
MemoryStream ms = new MemoryStream(100);
byte[] buffer = ms.GetBuffer();
Assert.Equal(100, buffer.Length);
ms.Write(testdata, 0, 100);
ms.Write(testdata, 0, 100);
Assert.Equal(200, ms.Length);
buffer = ms.GetBuffer();
Assert.Equal(256, buffer.Length); // Minimun size after writing
}
}
}

View File

@@ -0,0 +1,419 @@
// 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 Xunit;
using System;
using System.IO;
using System.Collections.Generic;
namespace System.IO.Tests
{
public class MemoryStream_TryGetBufferTests
{
[Fact]
public static void TryGetBuffer_Constructor_AlwaysReturnsTrue()
{
var stream = new MemoryStream();
ArraySegment<byte> segment;
Assert.True(stream.TryGetBuffer(out segment));
Assert.NotNull(segment.Array);
Assert.Equal(0, segment.Offset);
Assert.Equal(0, segment.Count);
}
[Fact]
public static void TryGetBuffer_Constructor_Int32_AlwaysReturnsTrue()
{
var stream = new MemoryStream(512);
ArraySegment<byte> segment;
Assert.True(stream.TryGetBuffer(out segment));
Assert.Equal(512, segment.Array.Length);
Assert.Equal(0, segment.Offset);
Assert.Equal(0, segment.Count);
}
[Fact]
public static void TryGetBuffer_Constructor_ByteArray_AlwaysReturnsFalse()
{
var stream = new MemoryStream(new byte[512]);
ArraySegment<byte> segment;
Assert.False(stream.TryGetBuffer(out segment));
}
[Fact]
public static void TryGetBuffer_Constructor_ByteArray_Bool_AlwaysReturnsFalse()
{
var stream = new MemoryStream(new byte[512], writable: true);
ArraySegment<byte> segment;
Assert.False(stream.TryGetBuffer(out segment));
}
[Fact]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_AlwaysReturnsFalse()
{
var stream = new MemoryStream(new byte[512], index: 0, count: 512);
ArraySegment<byte> segment;
Assert.False(stream.TryGetBuffer(out segment));
}
[Fact]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_AlwaysReturnsFalse()
{
var stream = new MemoryStream(new byte[512], index: 0, count: 512, writable: true);
ArraySegment<byte> segment;
Assert.False(stream.TryGetBuffer(out segment));
}
[Fact]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_Bool_FalseAsPubliclyVisible_ReturnsFalse()
{
var stream = new MemoryStream(new byte[512], index: 0, count: 512, writable: true, publiclyVisible: false);
ArraySegment<byte> segment;
Assert.False(stream.TryGetBuffer(out segment));
}
[Fact]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_Bool_TrueAsPubliclyVisible_ReturnsTrue()
{
var stream = new MemoryStream(new byte[512], index: 0, count: 512, writable: true, publiclyVisible: true);
ArraySegment<byte> segment;
Assert.True(stream.TryGetBuffer(out segment));
Assert.NotNull(segment.Array);
Assert.Equal(512, segment.Array.Length);
Assert.Equal(0, segment.Offset);
Assert.Equal(512, segment.Count);
}
[Theory]
[MemberData(nameof(GetArraysVariedBySize))]
public static void TryGetBuffer_Constructor_ByteArray_AlwaysReturnsEmptyArraySegment(byte[] array)
{
var stream = new MemoryStream(array);
ArraySegment<byte> result;
Assert.False(stream.TryGetBuffer(out result));
// publiclyVisible = false;
Assert.True(default(ArraySegment<byte>).Equals(result));
}
[Theory]
[MemberData(nameof(GetArraysVariedBySize))]
public static void TryGetBuffer_Constructor_ByteArray_Bool_AlwaysReturnsEmptyArraySegment(byte[] array)
{
var stream = new MemoryStream(array, writable: true);
ArraySegment<byte> result;
Assert.False(stream.TryGetBuffer(out result));
// publiclyVisible = false;
Assert.True(default(ArraySegment<byte>).Equals(result));
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_AlwaysReturnsEmptyArraySegment(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count);
ArraySegment<byte> result;
Assert.False(stream.TryGetBuffer(out result));
// publiclyVisible = false;
Assert.True(default(ArraySegment<byte>).Equals(result));
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_AlwaysReturnsEmptyArraySegment(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true);
ArraySegment<byte> result;
Assert.False(stream.TryGetBuffer(out result));
// publiclyVisible = false;
Assert.True(default(ArraySegment<byte>).Equals(result));
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_Bool_FalseAsPubliclyVisible_ReturnsEmptyArraySegment(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: false);
ArraySegment<byte> result;
Assert.False(stream.TryGetBuffer(out result));
// publiclyVisible = false;
Assert.True(default(ArraySegment<byte>).Equals(result));
}
[Fact]
public static void TryGetBuffer_Constructor_AlwaysReturnsOffsetSetToZero()
{
var stream = new MemoryStream();
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(0, result.Offset);
}
[Fact]
public static void TryGetBuffer_Constructor_Int32_AlwaysReturnsOffsetSetToZero()
{
var stream = new MemoryStream(512);
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(0, result.Offset);
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_Bool_ValueAsIndexAndTrueAsPubliclyVisible_AlwaysReturnsOffsetSetToIndex(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: true);
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(array.Offset, result.Offset);
}
[Fact]
public static void TryGetBuffer_Constructor_ByDefaultReturnsCountSetToZero()
{
var stream = new MemoryStream();
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(0, result.Count);
}
[Theory]
[MemberData(nameof(GetArraysVariedBySize))]
public static void TryGetBuffer_Constructor_ReturnsCountSetToWrittenLength(byte[] array)
{
var stream = new MemoryStream();
stream.Write(array, 0, array.Length);
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(array.Length, result.Count);
}
[Fact]
public static void TryGetBuffer_Constructor_Int32_ByDefaultReturnsCountSetToZero()
{
var stream = new MemoryStream(512);
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(0, result.Offset);
}
[Theory]
[MemberData(nameof(GetArraysVariedBySize))]
public static void TryGetBuffer_Constructor_Int32_ReturnsCountSetToWrittenLength(byte[] array)
{
var stream = new MemoryStream(512);
stream.Write(array, 0, array.Length);
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(array.Length, result.Count);
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_Bool_ValueAsCountAndTrueAsPubliclyVisible_AlwaysReturnsCountSetToCount(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: true);
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(array.Count, result.Count);
}
[Fact]
public static void TryGetBuffer_Constructor_ReturnsArray()
{
var stream = new MemoryStream();
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.NotNull(result.Array);
}
[Fact]
public static void TryGetBuffer_Constructor_MultipleCallsReturnsSameArray()
{
var stream = new MemoryStream();
ArraySegment<byte> result1;
ArraySegment<byte> result2;
Assert.True(stream.TryGetBuffer(out result1));
Assert.True(stream.TryGetBuffer(out result2));
Assert.Same(result1.Array, result2.Array);
}
[Fact]
public static void TryGetBuffer_Constructor_Int32_MultipleCallsReturnSameArray()
{
var stream = new MemoryStream(512);
ArraySegment<byte> result1;
ArraySegment<byte> result2;
Assert.True(stream.TryGetBuffer(out result1));
Assert.True(stream.TryGetBuffer(out result2));
Assert.Same(result1.Array, result2.Array);
}
[Fact]
public static void TryGetBuffer_Constructor_Int32_WhenWritingPastCapacity_ReturnsDifferentArrays()
{
var stream = new MemoryStream(512);
ArraySegment<byte> result1;
Assert.True(stream.TryGetBuffer(out result1));
// Force the stream to resize the underlying array
stream.Write(new byte[1024], 0, 1024);
ArraySegment<byte> result2;
Assert.True(stream.TryGetBuffer(out result2));
Assert.NotSame(result1.Array, result2.Array);
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_Constructor_ByteArray_Int32_Int32_Bool_Bool_ValueAsBufferAndTrueAsPubliclyVisible_AlwaysReturnsArraySetToBuffer(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: true);
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Same(array.Array, result.Array);
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_WhenDisposed_ReturnsTrue(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: true);
stream.Dispose();
ArraySegment<byte> segment;
Assert.True(stream.TryGetBuffer(out segment));
Assert.Same(array.Array, segment.Array);
Assert.Equal(array.Offset, segment.Offset);
Assert.Equal(array.Count, segment.Count);
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_WhenDisposed_ReturnsOffsetSetToIndex(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: true);
stream.Dispose();
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(array.Offset, result.Offset);
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_WhenDisposed_ReturnsCountSetToCount(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: true);
stream.Dispose();
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Equal(array.Count, result.Count);
}
[Theory]
[MemberData(nameof(GetArraysVariedByOffsetAndLength))]
public static void TryGetBuffer_WhenDisposed_ReturnsArraySetToBuffer(ArraySegment<byte> array)
{
var stream = new MemoryStream(array.Array, index: array.Offset, count: array.Count, writable: true, publiclyVisible: true);
stream.Dispose();
ArraySegment<byte> result;
Assert.True(stream.TryGetBuffer(out result));
Assert.Same(array.Array, result.Array);
}
public static IEnumerable<object[]> GetArraysVariedByOffsetAndLength()
{
yield return new object[] { new ArraySegment<byte>(new byte[512], 0, 512) };
yield return new object[] { new ArraySegment<byte>(new byte[512], 1, 511) };
yield return new object[] { new ArraySegment<byte>(new byte[512], 2, 510) };
yield return new object[] { new ArraySegment<byte>(new byte[512], 256, 256) };
yield return new object[] { new ArraySegment<byte>(new byte[512], 512, 0) };
yield return new object[] { new ArraySegment<byte>(new byte[512], 511, 1) };
yield return new object[] { new ArraySegment<byte>(new byte[512], 510, 2) };
}
public static IEnumerable<object[]> GetArraysVariedBySize()
{
yield return new object[] { FillWithData(new byte[0]) };
yield return new object[] { FillWithData(new byte[1]) };
yield return new object[] { FillWithData(new byte[2]) };
yield return new object[] { FillWithData(new byte[254]) };
yield return new object[] { FillWithData(new byte[255]) };
yield return new object[] { FillWithData(new byte[256]) };
yield return new object[] { FillWithData(new byte[511]) };
yield return new object[] { FillWithData(new byte[512]) };
yield return new object[] { FillWithData(new byte[513]) };
yield return new object[] { FillWithData(new byte[1023]) };
yield return new object[] { FillWithData(new byte[1024]) };
yield return new object[] { FillWithData(new byte[1025]) };
yield return new object[] { FillWithData(new byte[2047]) };
yield return new object[] { FillWithData(new byte[2048]) };
yield return new object[] { FillWithData(new byte[2049]) };
}
private static byte[] FillWithData(byte[] buffer)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = (byte)i;
}
return buffer;
}
}
}

View File

@@ -0,0 +1,273 @@
// 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 Xunit;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
namespace System.IO.Tests
{
public class MemoryStreamTests
{
[Fact]
public static void MemoryStream_Write_BeyondCapacity()
{
using (MemoryStream memoryStream = new MemoryStream())
{
long origLength = memoryStream.Length;
byte[] bytes = new byte[10];
for (int i = 0; i < bytes.Length; i++)
bytes[i] = (byte)i;
int spanPastEnd = 5;
memoryStream.Seek(spanPastEnd, SeekOrigin.End);
Assert.Equal(memoryStream.Length + spanPastEnd, memoryStream.Position);
// Test Write
memoryStream.Write(bytes, 0, bytes.Length);
long pos = memoryStream.Position;
Assert.Equal(pos, origLength + spanPastEnd + bytes.Length);
Assert.Equal(memoryStream.Length, origLength + spanPastEnd + bytes.Length);
// Verify bytes were correct.
memoryStream.Position = origLength;
byte[] newData = new byte[bytes.Length + spanPastEnd];
int n = memoryStream.Read(newData, 0, newData.Length);
Assert.Equal(n, newData.Length);
for (int i = 0; i < spanPastEnd; i++)
Assert.Equal(0, newData[i]);
for (int i = 0; i < bytes.Length; i++)
Assert.Equal(bytes[i], newData[i + spanPastEnd]);
}
}
[Fact]
public static void MemoryStream_WriteByte_BeyondCapacity()
{
using (MemoryStream memoryStream = new MemoryStream())
{
long origLength = memoryStream.Length;
byte[] bytes = new byte[10];
for (int i = 0; i < bytes.Length; i++)
bytes[i] = (byte)i;
int spanPastEnd = 5;
memoryStream.Seek(spanPastEnd, SeekOrigin.End);
Assert.Equal(memoryStream.Length + spanPastEnd, memoryStream.Position);
// Test WriteByte
origLength = memoryStream.Length;
memoryStream.Position = memoryStream.Length + spanPastEnd;
memoryStream.WriteByte(0x42);
long expected = origLength + spanPastEnd + 1;
Assert.Equal(expected, memoryStream.Position);
Assert.Equal(expected, memoryStream.Length);
}
}
[Fact]
public static void MemoryStream_GetPositionTest_Negative()
{
int iArrLen = 100;
byte[] bArr = new byte[iArrLen];
using (MemoryStream ms = new MemoryStream(bArr))
{
long iCurrentPos = ms.Position;
for (int i = -1; i > -6; i--)
{
Assert.Throws<ArgumentOutOfRangeException>(() => ms.Position = i);
Assert.Equal(ms.Position, iCurrentPos);
}
}
}
[Fact]
public static void MemoryStream_LengthTest()
{
using (MemoryStream ms2 = new MemoryStream())
{
// [] Get the Length when position is at length
ms2.SetLength(50);
ms2.Position = 50;
StreamWriter sw2 = new StreamWriter(ms2);
for (char c = 'a'; c < 'f'; c++)
sw2.Write(c);
sw2.Flush();
Assert.Equal(55, ms2.Length);
// Somewhere in the middle (set the length to be shorter.)
ms2.SetLength(30);
Assert.Equal(30, ms2.Length);
Assert.Equal(30, ms2.Position);
// Increase the length
ms2.SetLength(100);
Assert.Equal(100, ms2.Length);
Assert.Equal(30, ms2.Position);
}
}
[Fact]
public static void MemoryStream_LengthTest_Negative()
{
using (MemoryStream ms2 = new MemoryStream())
{
Assert.Throws<ArgumentOutOfRangeException>(() => ms2.SetLength(Int64.MaxValue));
Assert.Throws<ArgumentOutOfRangeException>(() => ms2.SetLength(-2));
}
}
[Fact]
public static void MemoryStream_ReadTest_Negative()
{
MemoryStream ms2 = new MemoryStream();
Assert.Throws<ArgumentNullException>(() => ms2.Read(null, 0, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => ms2.Read(new byte[] { 1 }, -1, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => ms2.Read(new byte[] { 1 }, 0, -1));
Assert.Throws<ArgumentException>(() => ms2.Read(new byte[] { 1 }, 2, 0));
Assert.Throws<ArgumentException>(() => ms2.Read(new byte[] { 1 }, 0, 2));
ms2.Dispose();
Assert.Throws<ObjectDisposedException>(() => ms2.Read(new byte[] { 1 }, 0, 1));
}
[Fact]
public static void MemoryStream_WriteToTests()
{
using (MemoryStream ms2 = new MemoryStream())
{
byte[] bytArrRet;
byte[] bytArr = new byte[] { byte.MinValue, byte.MaxValue, 1, 2, 3, 4, 5, 6, 128, 250 };
// [] Write to FileStream, check the filestream
ms2.Write(bytArr, 0, bytArr.Length);
using (MemoryStream readonlyStream = new MemoryStream())
{
ms2.WriteTo(readonlyStream);
readonlyStream.Flush();
readonlyStream.Position = 0;
bytArrRet = new byte[(int)readonlyStream.Length];
readonlyStream.Read(bytArrRet, 0, (int)readonlyStream.Length);
for (int i = 0; i < bytArr.Length; i++)
{
Assert.Equal(bytArr[i], bytArrRet[i]);
}
}
}
// [] Write to memoryStream, check the memoryStream
using (MemoryStream ms2 = new MemoryStream())
using (MemoryStream ms3 = new MemoryStream())
{
byte[] bytArrRet;
byte[] bytArr = new byte[] { byte.MinValue, byte.MaxValue, 1, 2, 3, 4, 5, 6, 128, 250 };
ms2.Write(bytArr, 0, bytArr.Length);
ms2.WriteTo(ms3);
ms3.Position = 0;
bytArrRet = new byte[(int)ms3.Length];
ms3.Read(bytArrRet, 0, (int)ms3.Length);
for (int i = 0; i < bytArr.Length; i++)
{
Assert.Equal(bytArr[i], bytArrRet[i]);
}
}
}
[Fact]
public static void MemoryStream_WriteToTests_Negative()
{
using (MemoryStream ms2 = new MemoryStream())
{
Assert.Throws<ArgumentNullException>(() => ms2.WriteTo(null));
ms2.Write(new byte[] { 1 }, 0, 1);
MemoryStream readonlyStream = new MemoryStream(new byte[1028], false);
Assert.Throws<NotSupportedException>(() => ms2.WriteTo(readonlyStream));
readonlyStream.Dispose();
// [] Pass in a closed stream
Assert.Throws<ObjectDisposedException>(() => ms2.WriteTo(readonlyStream));
}
}
[Fact]
public static void MemoryStream_CopyTo_Invalid()
{
MemoryStream memoryStream;
using (memoryStream = new MemoryStream())
{
Assert.Throws<ArgumentNullException>("destination", () => memoryStream.CopyTo(destination: null));
// Validate the destination parameter first.
Assert.Throws<ArgumentNullException>("destination", () => memoryStream.CopyTo(destination: null, bufferSize: 0));
Assert.Throws<ArgumentNullException>("destination", () => memoryStream.CopyTo(destination: null, bufferSize: -1));
// Then bufferSize.
Assert.Throws<ArgumentOutOfRangeException>("bufferSize", () => memoryStream.CopyTo(Stream.Null, bufferSize: 0)); // 0-length buffer doesn't make sense.
Assert.Throws<ArgumentOutOfRangeException>("bufferSize", () => memoryStream.CopyTo(Stream.Null, bufferSize: -1));
}
// After the Stream is disposed, we should fail on all CopyTos.
Assert.Throws<ArgumentOutOfRangeException>("bufferSize", () => memoryStream.CopyTo(Stream.Null, bufferSize: 0)); // Not before bufferSize is validated.
Assert.Throws<ArgumentOutOfRangeException>("bufferSize", () => memoryStream.CopyTo(Stream.Null, bufferSize: -1));
MemoryStream disposedStream = memoryStream;
// We should throw first for the source being disposed...
Assert.Throws<ObjectDisposedException>(() => memoryStream.CopyTo(disposedStream, 1));
// Then for the destination being disposed.
memoryStream = new MemoryStream();
Assert.Throws<ObjectDisposedException>(() => memoryStream.CopyTo(disposedStream, 1));
// Then we should check whether we can't read but can write, which isn't possible for non-subclassed MemoryStreams.
// THen we should check whether the destination can read but can't write.
var readOnlyStream = new DelegateStream(
canReadFunc: () => true,
canWriteFunc: () => false
);
Assert.Throws<NotSupportedException>(() => memoryStream.CopyTo(readOnlyStream, 1));
}
[Theory]
[MemberData(nameof(CopyToData))]
public void CopyTo(Stream source, byte[] expected)
{
using (var destination = new MemoryStream())
{
source.CopyTo(destination);
Assert.InRange(source.Position, source.Length, int.MaxValue); // Copying the data should have read to the end of the stream or stayed past the end.
Assert.Equal(expected, destination.ToArray());
}
}
public static IEnumerable<object[]> CopyToData()
{
// Stream is positioned @ beginning of data
var data1 = new byte[] { 1, 2, 3 };
var stream1 = new MemoryStream(data1);
yield return new object[] { stream1, data1 };
// Stream is positioned in the middle of data
var data2 = new byte[] { 0xff, 0xf3, 0xf0 };
var stream2 = new MemoryStream(data2) { Position = 1 };
yield return new object[] { stream2, new byte[] { 0xf3, 0xf0 } };
// Stream is positioned after end of data
var data3 = data2;
var stream3 = new MemoryStream(data3) { Position = data3.Length + 1 };
yield return new object[] { stream3, Array.Empty<byte>() };
}
}
}

View File

@@ -0,0 +1,38 @@
// 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.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public class StreamAPMTests
{
protected virtual Stream CreateStream()
{
return new MemoryStream();
}
public void EndCallback(IAsyncResult ar)
{ }
[Fact]
public void BeginEndReadTest()
{
Stream stream = CreateStream();
IAsyncResult result = stream.BeginRead(new byte[1], 0, 1, new AsyncCallback(EndCallback), new object());
stream.EndRead(result);
}
[Fact]
public void BeginEndWriteTest()
{
Stream stream = CreateStream();
IAsyncResult result = stream.BeginWrite(new byte[1], 0, 1, new AsyncCallback(EndCallback), new object());
stream.EndWrite(result);
}
}
}

View File

@@ -0,0 +1,30 @@
// 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.Linq;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public class StreamAsync
{
protected virtual Stream CreateStream() => new MemoryStream();
[Fact]
public async Task CopyToAsyncTest()
{
byte[] data = Enumerable.Range(0, 1000).Select(i => (byte)(i % 256)).ToArray();
Stream ms = CreateStream();
ms.Write(data, 0, data.Length);
ms.Position = 0;
var ms2 = new MemoryStream();
await ms.CopyToAsync(ms2);
Assert.Equal(data, ms2.ToArray());
}
}
}

View File

@@ -0,0 +1,360 @@
// 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.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public class StreamCopyToTests
{
[Fact]
public void IfCanSeekIsFalseLengthAndPositionShouldNotBeCalled()
{
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => false,
readFunc: (buffer, offset, count) => 0);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
trackingStream.CopyTo(dest);
Assert.InRange(trackingStream.TimesCalled(nameof(trackingStream.CanSeek)), 0, 1);
Assert.Equal(0, trackingStream.TimesCalled(nameof(trackingStream.Length)));
Assert.Equal(0, trackingStream.TimesCalled(nameof(trackingStream.Position)));
// We can't override CopyTo since it's not virtual, so checking TimesCalled
// for CopyTo will result in 0. Instead, we check that Read was called,
// and validate the parameters passed there.
Assert.Equal(1, trackingStream.TimesCalled(nameof(trackingStream.Read)));
byte[] outerBuffer = trackingStream.ReadBuffer;
int outerOffset = trackingStream.ReadOffset;
int outerCount = trackingStream.ReadCount;
Assert.NotNull(outerBuffer);
Assert.InRange(outerOffset, 0, outerBuffer.Length - outerCount);
Assert.InRange(outerCount, 1, int.MaxValue); // the buffer can't be size 0
}
[Fact]
public async void AsyncIfCanSeekIsFalseLengthAndPositionShouldNotBeCalled()
{
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => false,
readFunc: (buffer, offset, count) => 0);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
await trackingStream.CopyToAsync(dest);
Assert.InRange(trackingStream.TimesCalled(nameof(trackingStream.CanSeek)), 0, 1);
Assert.Equal(0, trackingStream.TimesCalled(nameof(trackingStream.Length)));
Assert.Equal(0, trackingStream.TimesCalled(nameof(trackingStream.Position)));
Assert.Equal(1, trackingStream.TimesCalled(nameof(trackingStream.CopyToAsync)));
Assert.Same(dest, trackingStream.CopyToAsyncDestination);
Assert.InRange(trackingStream.CopyToAsyncBufferSize, 1, int.MaxValue);
Assert.Equal(CancellationToken.None, trackingStream.CopyToAsyncCancellationToken);
}
[Fact]
public void IfCanSeekIsTrueLengthAndPositionShouldOnlyBeCalledOnce()
{
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
readFunc: (buffer, offset, count) => 0,
lengthFunc: () => 0L,
positionGetFunc: () => 0L);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
trackingStream.CopyTo(dest);
Assert.InRange(trackingStream.TimesCalled(nameof(trackingStream.Length)), 0, 1);
Assert.InRange(trackingStream.TimesCalled(nameof(trackingStream.Position)), 0, 1);
}
[Fact]
public async void AsyncIfCanSeekIsTrueLengthAndPositionShouldOnlyBeCalledOnce()
{
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
readFunc: (buffer, offset, count) => 0,
lengthFunc: () => 0L,
positionGetFunc: () => 0L);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
await trackingStream.CopyToAsync(dest);
Assert.InRange(trackingStream.TimesCalled(nameof(trackingStream.Length)), 0, 1);
Assert.InRange(trackingStream.TimesCalled(nameof(trackingStream.Position)), 0, 1);
}
[Theory]
[MemberData(nameof(LengthIsLessThanOrEqualToPosition))]
public void IfLengthIsLessThanOrEqualToPositionCopyToShouldStillBeCalledWithAPositiveBufferSize(long length, long position)
{
// Streams with their Lengths <= their Positions, e.g.
// new MemoryStream { Position = 3 }.SetLength(1)
// should still be called CopyTo{Async} on with a
// bufferSize of at least 1.
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
lengthFunc: () => length,
positionGetFunc: () => position,
readFunc: (buffer, offset, count) => 0);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
trackingStream.CopyTo(dest);
// CopyTo is not virtual, so we can't override it in
// CallTrackingStream and record the arguments directly.
// Instead, validate the arguments passed to Read.
Assert.Equal(1, trackingStream.TimesCalled(nameof(trackingStream.Read)));
byte[] outerBuffer = trackingStream.ReadBuffer;
int outerOffset = trackingStream.ReadOffset;
int outerCount = trackingStream.ReadCount;
Assert.NotNull(outerBuffer);
Assert.InRange(outerOffset, 0, outerBuffer.Length - outerCount);
Assert.InRange(outerCount, 1, int.MaxValue);
}
[Theory]
[MemberData(nameof(LengthIsLessThanOrEqualToPosition))]
public async void AsyncIfLengthIsLessThanOrEqualToPositionCopyToShouldStillBeCalledWithAPositiveBufferSize(long length, long position)
{
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
lengthFunc: () => length,
positionGetFunc: () => position,
readFunc: (buffer, offset, count) => 0);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
await trackingStream.CopyToAsync(dest);
Assert.Same(dest, trackingStream.CopyToAsyncDestination);
Assert.InRange(trackingStream.CopyToAsyncBufferSize, 1, int.MaxValue);
Assert.Equal(CancellationToken.None, trackingStream.CopyToAsyncCancellationToken);
}
[Theory]
[MemberData(nameof(LengthMinusPositionPositiveOverflows))]
public void IfLengthMinusPositionPositiveOverflowsBufferSizeShouldStillBePositive(long length, long position)
{
// The new implementation of Stream.CopyTo calculates the bytes left
// in the Stream by calling Length - Position. This can overflow to a
// negative number, so this tests that if that happens we don't send
// in a negative bufferSize.
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
lengthFunc: () => length,
positionGetFunc: () => position,
readFunc: (buffer, offset, count) => 0);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
trackingStream.CopyTo(dest);
// CopyTo is not virtual, so we can't override it in
// CallTrackingStream and record the arguments directly.
// Instead, validate the arguments passed to Read.
Assert.Equal(1, trackingStream.TimesCalled(nameof(trackingStream.Read)));
byte[] outerBuffer = trackingStream.ReadBuffer;
int outerOffset = trackingStream.ReadOffset;
int outerCount = trackingStream.ReadCount;
Assert.NotNull(outerBuffer);
Assert.InRange(outerOffset, 0, outerBuffer.Length - outerCount);
Assert.InRange(outerCount, 1, int.MaxValue);
}
[Theory]
[MemberData(nameof(LengthMinusPositionPositiveOverflows))]
public async void AsyncIfLengthMinusPositionPositiveOverflowsBufferSizeShouldStillBePositive(long length, long position)
{
var baseStream = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
lengthFunc: () => length,
positionGetFunc: () => position,
readFunc: (buffer, offset, count) => 0);
var trackingStream = new CallTrackingStream(baseStream);
var dest = Stream.Null;
await trackingStream.CopyToAsync(dest);
// Note: We can't check how many times ReadAsync was called
// here, since trackingStream overrides CopyToAsync and forwards
// to the inner (non-tracking) stream for the implementation
Assert.Same(dest, trackingStream.CopyToAsyncDestination);
Assert.InRange(trackingStream.CopyToAsyncBufferSize, 1, int.MaxValue);
Assert.Equal(CancellationToken.None, trackingStream.CopyToAsyncCancellationToken);
}
[Theory]
[MemberData(nameof(LengthIsGreaterThanPositionAndDoesNotOverflow))]
public void IfLengthIsGreaterThanPositionAndDoesNotOverflowEverythingShouldGoNormally(long length, long position)
{
const int ReadLimit = 7;
// Lambda state
byte[] outerBuffer = null;
int? outerOffset = null;
int? outerCount = null;
int readsLeft = ReadLimit;
var srcBase = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
lengthFunc: () => length,
positionGetFunc: () => position,
readFunc: (buffer, offset, count) =>
{
Assert.NotNull(buffer);
Assert.InRange(offset, 0, buffer.Length - count);
Assert.InRange(count, 1, int.MaxValue);
// CopyTo should always pass in the same buffer/offset/count
if (outerBuffer != null) Assert.Same(outerBuffer, buffer);
else outerBuffer = buffer;
if (outerOffset != null) Assert.Equal(outerOffset, offset);
else outerOffset = offset;
if (outerCount != null) Assert.Equal(outerCount, count);
else outerCount = count;
return --readsLeft; // CopyTo will call Read on this ReadLimit times before stopping
});
var src = new CallTrackingStream(srcBase);
var destBase = new DelegateStream(
canWriteFunc: () => true,
writeFunc: (buffer, offset, count) =>
{
Assert.Same(outerBuffer, buffer);
Assert.Equal(outerOffset, offset);
Assert.Equal(readsLeft, count);
});
var dest = new CallTrackingStream(destBase);
src.CopyTo(dest);
Assert.Equal(ReadLimit, src.TimesCalled(nameof(src.Read)));
Assert.Equal(ReadLimit - 1, dest.TimesCalled(nameof(dest.Write)));
}
[Theory]
[MemberData(nameof(LengthIsGreaterThanPositionAndDoesNotOverflow))]
public async void AsyncIfLengthIsGreaterThanPositionAndDoesNotOverflowEverythingShouldGoNormally(long length, long position)
{
const int ReadLimit = 7;
// Lambda state
byte[] outerBuffer = null;
int? outerOffset = null;
int? outerCount = null;
int readsLeft = ReadLimit;
var srcBase = new DelegateStream(
canReadFunc: () => true,
canSeekFunc: () => true,
lengthFunc: () => length,
positionGetFunc: () => position,
readFunc: (buffer, offset, count) =>
{
Assert.NotNull(buffer);
Assert.InRange(offset, 0, buffer.Length - count);
Assert.InRange(count, 1, int.MaxValue);
// CopyTo should always pass in the same buffer/offset/count
if (outerBuffer != null) Assert.Same(outerBuffer, buffer);
else outerBuffer = buffer;
if (outerOffset != null) Assert.Equal(outerOffset, offset);
else outerOffset = offset;
if (outerCount != null) Assert.Equal(outerCount, count);
else outerCount = count;
return --readsLeft; // CopyTo will call Read on this ReadLimit times before stopping
});
var src = new CallTrackingStream(srcBase);
var destBase = new DelegateStream(
canWriteFunc: () => true,
writeFunc: (buffer, offset, count) =>
{
Assert.Same(outerBuffer, buffer);
Assert.Equal(outerOffset, offset);
Assert.Equal(readsLeft, count);
});
var dest = new CallTrackingStream(destBase);
await src.CopyToAsync(dest);
// Since we override CopyToAsync in CallTrackingStream,
// src.Read will actually not get called ReadLimit
// times, src.Inner.Read will. So, we just assert that
// CopyToAsync was called once for src.
Assert.Equal(1, src.TimesCalled(nameof(src.CopyToAsync)));
Assert.Equal(ReadLimit - 1, dest.TimesCalled(nameof(dest.WriteAsync))); // dest.WriteAsync will still get called repeatedly
}
// Member data
public static IEnumerable<object[]> LengthIsLessThanOrEqualToPosition()
{
yield return new object[] { 5L, 5L }; // same number
yield return new object[] { 3L, 5L }; // length is less than position
yield return new object[] { -1L, -1L }; // negative numbers
yield return new object[] { 0L, 0L }; // both zero
yield return new object[] { -500L, 0L }; // negative number and zero
yield return new object[] { 0L, 500L }; // zero and positive number
yield return new object[] { -500L, 500L }; // negative and positive number
yield return new object[] { long.MinValue, long.MaxValue }; // length - position <= 0 will fail (overflow), but length <= position won't
}
public static IEnumerable<object[]> LengthMinusPositionPositiveOverflows()
{
yield return new object[] { long.MaxValue, long.MinValue }; // length - position will be -1
yield return new object[] { 1L, -long.MaxValue };
}
public static IEnumerable<object[]> LengthIsGreaterThanPositionAndDoesNotOverflow()
{
yield return new object[] { 5L, 3L };
yield return new object[] { -3L, -6L };
yield return new object[] { 0L, -3L };
yield return new object[] { long.MaxValue, 0 }; // should not overflow or OOM
yield return new object[] { 85000, 123 }; // at least in the current implementation, we max out the bufferSize at 81920
}
}
}

View File

@@ -0,0 +1,290 @@
// 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.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace System.IO.Tests
{
public partial class StreamMethods
{
protected virtual Stream CreateStream()
{
return new MemoryStream();
}
protected virtual Stream CreateStream(int bufferSize)
{
return new MemoryStream(new byte[bufferSize]);
}
[Fact]
public void MemoryStreamSeekStress()
{
var ms1 = CreateStream();
SeekTest(ms1, false);
}
[Fact]
public void MemoryStreamSeekStressWithInitialBuffer()
{
var ms1 = CreateStream(1024);
SeekTest(ms1, false);
}
[Fact]
public async Task MemoryStreamStress()
{
var ms1 = CreateStream();
await StreamTest(ms1, false);
}
public static void SeekTest(Stream stream, Boolean fSuppres)
{
long lngPos;
byte btValue;
stream.Position = 0;
Assert.Equal(0, stream.Position);
int length = 1 << 10; //fancy way of writing 2 to the pow 10
byte[] btArr = new byte[length];
for (int i = 0; i < btArr.Length; i++)
btArr[i] = (byte)i;
if (stream.CanWrite)
stream.Write(btArr, 0, btArr.Length);
else
stream.Position = btArr.Length;
Assert.Equal(btArr.Length, stream.Position);
lngPos = stream.Seek(0, SeekOrigin.Begin);
Assert.Equal(0, lngPos);
Assert.Equal(0, stream.Position);
for (int i = 0; i < btArr.Length; i++)
{
if (stream.CanWrite)
{
btValue = (byte)stream.ReadByte();
Assert.Equal(btArr[i], btValue);
}
else
{
stream.Seek(1, SeekOrigin.Current);
}
Assert.Equal(i + 1, stream.Position);
}
Assert.Throws<IOException>(() => stream.Seek(-5, SeekOrigin.Begin));
lngPos = stream.Seek(5, SeekOrigin.Begin);
Assert.Equal(5, lngPos);
Assert.Equal(5, stream.Position);
lngPos = stream.Seek(5, SeekOrigin.End);
Assert.Equal(length + 5, lngPos);
Assert.Throws<IOException>(() => stream.Seek(-(btArr.Length + 1), SeekOrigin.End));
lngPos = stream.Seek(-5, SeekOrigin.End);
Assert.Equal(btArr.Length - 5, lngPos);
Assert.Equal(btArr.Length - 5, stream.Position);
lngPos = stream.Seek(0, SeekOrigin.End);
Assert.Equal(btArr.Length, stream.Position);
for (int i = btArr.Length; i > 0; i--)
{
stream.Seek(-1, SeekOrigin.Current);
Assert.Equal(i - 1, stream.Position);
}
Assert.Throws<IOException>(() => stream.Seek(-1, SeekOrigin.Current));
}
public static async Task StreamTest(Stream stream, Boolean fSuppress)
{
string strValue;
int iValue;
//[] We will first use the stream's 2 writing methods
int iLength = 1 << 10;
stream.Seek(0, SeekOrigin.Begin);
for (int i = 0; i < iLength; i++)
stream.WriteByte((byte)i);
byte[] btArr = new byte[iLength];
for (int i = 0; i < iLength; i++)
btArr[i] = (byte)i;
stream.Write(btArr, 0, iLength);
//we will write many things here using a binary writer
BinaryWriter bw1 = new BinaryWriter(stream);
bw1.Write(false);
bw1.Write(true);
for (int i = 0; i < 10; i++)
{
bw1.Write((byte)i);
bw1.Write((sbyte)i);
bw1.Write((short)i);
bw1.Write((char)i);
bw1.Write((UInt16)i);
bw1.Write(i);
bw1.Write((uint)i);
bw1.Write((Int64)i);
bw1.Write((ulong)i);
bw1.Write((float)i);
bw1.Write((double)i);
}
//Some strings, chars and Bytes
char[] chArr = new char[iLength];
for (int i = 0; i < iLength; i++)
chArr[i] = (char)i;
bw1.Write(chArr);
bw1.Write(chArr, 512, 512);
bw1.Write(new string(chArr));
bw1.Write(new string(chArr));
//[] we will now read
stream.Seek(0, SeekOrigin.Begin);
for (int i = 0; i < iLength; i++)
{
Assert.Equal(i % 256, stream.ReadByte());
}
btArr = new byte[iLength];
stream.Read(btArr, 0, iLength);
for (int i = 0; i < iLength; i++)
{
Assert.Equal((byte)i, btArr[i]);
}
//Now, for the binary reader
BinaryReader br1 = new BinaryReader(stream);
Assert.False(br1.ReadBoolean());
Assert.True(br1.ReadBoolean());
for (int i = 0; i < 10; i++)
{
Assert.Equal( (byte)i, br1.ReadByte());
Assert.Equal((sbyte)i, br1.ReadSByte());
Assert.Equal((short)i, br1.ReadInt16());
Assert.Equal((char)i, br1.ReadChar());
Assert.Equal((UInt16)i, br1.ReadUInt16());
Assert.Equal(i, br1.ReadInt32());
Assert.Equal((uint)i, br1.ReadUInt32());
Assert.Equal((Int64)i, br1.ReadInt64());
Assert.Equal((ulong)i, br1.ReadUInt64());
Assert.Equal((float)i, br1.ReadSingle());
Assert.Equal((double)i, br1.ReadDouble());
}
chArr = br1.ReadChars(iLength);
for (int i = 0; i < iLength; i++)
{
Assert.Equal((char)i, chArr[i]);
}
chArr = new char[512];
chArr = br1.ReadChars(iLength / 2);
for (int i = 0; i < iLength / 2; i++)
{
Assert.Equal((char)(iLength / 2 + i), chArr[i]);
}
chArr = new char[iLength];
for (int i = 0; i < iLength; i++)
chArr[i] = (char)i;
strValue = br1.ReadString();
Assert.Equal(new string(chArr), strValue);
strValue = br1.ReadString();
Assert.Equal(new string(chArr), strValue);
stream.Seek(1, SeekOrigin.Current); // In the original test, success here would end the test
//[] we will do some async tests here now
stream.Position = 0;
btArr = new byte[iLength];
for (int i = 0; i < iLength; i++)
btArr[i] = (byte)(i + 5);
await stream.WriteAsync(btArr, 0, btArr.Length);
stream.Position = 0;
for (int i = 0; i < iLength; i++)
{
Assert.Equal((byte)(i + 5), stream.ReadByte());
}
//we will read asynchronously
stream.Position = 0;
byte[] compArr = new byte[iLength];
iValue = await stream.ReadAsync(compArr, 0, compArr.Length);
Assert.Equal(btArr.Length, iValue);
for (int i = 0; i < iLength; i++)
{
Assert.Equal(compArr[i], btArr[i]);
}
}
[Fact]
public async Task FlushAsyncTest()
{
byte[] data = Enumerable.Range(0, 8000).Select(i => (byte)i).ToArray();
Stream stream = CreateStream();
for (int i = 0; i < 4; i++)
{
await stream.WriteAsync(data, 2000 * i, 2000);
await stream.FlushAsync();
}
stream.Position = 0;
byte[] output = new byte[data.Length];
int bytesRead, totalRead = 0;
while ((bytesRead = await stream.ReadAsync(output, totalRead, data.Length - totalRead)) > 0)
totalRead += bytesRead;
Assert.Equal(data, output);
}
[Fact]
public void ArgumentValidation()
{
Stream stream = CreateStream();
Assert.Equal(TaskStatus.Canceled, stream.ReadAsync(new byte[1], 0, 1, new CancellationToken(canceled: true)).Status);
Assert.Equal(TaskStatus.Canceled, stream.WriteAsync(new byte[1], 0, 1, new CancellationToken(canceled: true)).Status);
Assert.Equal(TaskStatus.Canceled, stream.FlushAsync(new CancellationToken(canceled: true)).Status);
Assert.Throws<ArgumentNullException>("buffer", () => { stream.ReadAsync(null, 0, 0); });
Assert.Throws<ArgumentNullException>("buffer", () => { stream.WriteAsync(null, 0, 0); });
Assert.Throws<ArgumentOutOfRangeException>("offset", () => { stream.ReadAsync(new byte[1], -1, 0); });
Assert.Throws<ArgumentOutOfRangeException>("offset", () => { stream.WriteAsync(new byte[1], -1, 0); });
Assert.Throws<ArgumentOutOfRangeException>("count", () => { stream.ReadAsync(new byte[1], 0, -1); });
Assert.Throws<ArgumentOutOfRangeException>("count", () => { stream.WriteAsync(new byte[1], 0, -1); });
Assert.Throws<ArgumentException>(() => { stream.ReadAsync(new byte[1], 0, 2); });
Assert.Throws<ArgumentException>(() => { stream.WriteAsync(new byte[1], 0, 2); });
}
}
}

Some files were not shown because too many files have changed in this diff Show More