|
// 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.
#nullable disable
using Microsoft.CodeAnalysis;
using Roslyn.Test.Utilities;
using System;
using System.IO;
using Xunit;
namespace Roslyn.Utilities.UnitTests.InternalUtilities
{
public class StreamExtensionsTests
{
[Fact]
public void TryReadAll_CallsReadMultipleTimes()
{
var firstRead = true;
var sourceArray = new byte[] { 1, 2, 3, 4 };
int sourceOffset = 0;
var stream = new TestStream(readFunc: (buf, offset, count) =>
{
if (firstRead)
{
count = count / 2;
firstRead = false;
}
Array.Copy(sourceArray, sourceOffset, buf, offset, count);
sourceOffset += count;
return count;
});
var destArray = new byte[4];
var destCopy = destArray.AsImmutable();
// Note: Buffer is in undefined state after receiving an exception
Assert.Equal(sourceArray.Length, stream.TryReadAll(destArray, 0, sourceArray.Length));
Assert.Equal(sourceArray, destArray);
}
[Fact]
public void TryReadAll_ExceptionsPropagate()
{
var buffer = new byte[10];
var stream = new TestStream(readFunc: (_1, _2, _3) => { throw new IOException(); });
Assert.Throws<IOException>(() => stream.TryReadAll(null, 0, 1));
stream = new TestStream(readFunc: (buf, offset, count) =>
{
if (offset + count > buf.Length)
{
throw new ArgumentException();
}
return 0;
});
Assert.Equal(0, stream.TryReadAll(buffer, 0, 1));
Assert.Throws<ArgumentException>(() => stream.TryReadAll(buffer, 0, 100));
}
[Fact]
public void TryReadAll_ExceptionMayChangeOutput()
{
var firstRead = true;
var sourceArray = new byte[] { 1, 2, 3, 4 };
var stream = new TestStream(readFunc: (buf, offset, count) =>
{
if (firstRead)
{
count = count / 2;
Array.Copy(sourceArray, 0, buf, offset, count);
firstRead = false;
return count;
}
throw new IOException();
});
var destArray = new byte[4];
var destCopy = destArray.AsImmutable();
// Note: Buffer is in undefined state after receiving an exception
Assert.Throws<IOException>(() => stream.TryReadAll(destArray, 0, sourceArray.Length));
Assert.NotEqual(destArray, destCopy);
}
[Fact]
public void TryReadAll_ExceptionMayChangePosition()
{
var firstRead = true;
var sourceArray = new byte[] { 1, 2, 3, 4 };
var backingStream = new MemoryStream(sourceArray);
var stream = new TestStream(readFunc: (buf, offset, count) =>
{
if (firstRead)
{
count = count / 2;
backingStream.Read(buf, offset, count);
firstRead = false;
return count;
}
throw new IOException();
});
var destArray = new byte[4];
Assert.Equal(0, backingStream.Position);
Assert.Throws<IOException>(() => stream.TryReadAll(destArray, 0, sourceArray.Length));
Assert.Equal(2, backingStream.Position);
}
[Fact]
public void TryReadAll_PrematureEndOfStream()
{
var sourceArray = new byte[] { 1, 2, 3, 4 };
var stream = new MemoryStream(sourceArray);
var destArray = new byte[6];
// Try to read more bytes than exist in the stream
Assert.Equal(4, stream.TryReadAll(destArray, 0, 6));
var expected = new byte[] { 1, 2, 3, 4, 0, 0 };
Assert.Equal(expected, destArray);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void ReadAllBytes(bool canSeek)
{
var sourceArray = new byte[] { 1, 2, 3, 4 };
var stream = new TestStream(canSeek: canSeek, backingStream: new MemoryStream(sourceArray));
stream.ReadByte();
Assert.Equal(new byte[] { 2, 3, 4 }, stream.ReadAllBytes());
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void ReadAllBytes_End(bool canSeek)
{
var sourceArray = new byte[] { 1, 2 };
var stream = new TestStream(canSeek: canSeek, backingStream: new MemoryStream(sourceArray));
stream.ReadByte();
stream.ReadByte();
Assert.Equal(new byte[0], stream.ReadAllBytes());
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void ReadAllBytes_Resize(bool canSeek)
{
var sourceArray = new byte[] { 1, 2 };
var stream = new TestStream(canSeek: canSeek, backingStream: new MemoryStream(sourceArray), length: 3);
Assert.Equal(new byte[] { 1, 2 }, stream.ReadAllBytes());
}
}
}
|